[gjs/wip/gdbus-2: 12/13] GDBus: allow overriding _init in a Gio.DBusProxyClass



commit cb1e0cf02b3fd93000fb084ff57feb4786453014
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Thu Jun 21 00:18:44 2012 +0200

    GDBus: allow overriding _init in a Gio.DBusProxyClass
    
    A Gio.DBusProxyClass is a Lang.Class and should behave like one,
    including the _init handling. In particular, this allows for
    "slim proxies", that can be created without passing parameters
    (or with a subset of them).
    This is implemented by moving the special initialization of DBusProxy
    to an _init override, instead of hooking into init and init_async methods.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=669350

 modules/lang.js              |   22 +++++++++++-------
 modules/overrides/GObject.js |    3 +-
 modules/overrides/Gio.js     |   48 +++++++++++++++++++++--------------------
 test/js/testGDBus2.js        |   36 +++++++++++++++++++++++++++++-
 4 files changed, 74 insertions(+), 35 deletions(-)
---
diff --git a/modules/lang.js b/modules/lang.js
index 9e5c6c4..84748b0 100644
--- a/modules/lang.js
+++ b/modules/lang.js
@@ -139,27 +139,36 @@ function _Base() {
     throw new TypeError('Cannot instantiate abstract class _Base');
 }
 
-_Base.__super__ = null;
 _Base.prototype._init = function() { };
 _Base.prototype._construct = function() {
     this._init.apply(this, arguments);
     return this;
 };
 _Base.prototype.__name__ = '_Base';
+_Base.prototype.parent = _parent;
 _Base.prototype.toString = function() {
     return '[object ' + this.__name__ + ']';
 };
 
+function getSuperClass(klass) {
+    let proto = klass.prototype;
+    let parentProto = Object.getPrototypeOf(proto);
+
+    if (parentProto)
+        return parentProto.constructor;
+    else
+        return undefined;
+}
+
 function _parent() {
     if (!this.__caller__)
         throw new TypeError("The method 'parent' cannot be called");
 
     let caller = this.__caller__;
     let name = caller._name;
-    let parent = caller._owner.__super__;
+    let parent = getSuperClass(caller._owner);
 
     let previous = parent ? parent.prototype[name] : undefined;
-
     if (!previous)
         throw new TypeError("The method '" + name + "' is not on the superclass");
 
@@ -190,7 +199,6 @@ function Class(params) {
     }
 }
 
-Class.__super__ = _Base;
 Class.prototype = Object.create(_Base.prototype);
 Class.prototype.constructor = Class;
 Class.prototype.__name__ = 'Class';
@@ -246,7 +254,6 @@ Class.prototype._construct = function(params) {
     // methods/properties of Class.prototype, like wrapFunction.
     newClass.__proto__ = this.constructor.prototype;
 
-    newClass.__super__ = parent;
     newClass.prototype = Object.create(parent.prototype);
     newClass.prototype.constructor = newClass;
 
@@ -288,10 +295,7 @@ Class.prototype._init = function(params) {
                       configurable: false,
                       enumerable: false,
                       value: name },
-        'parent': { writable: false,
-                    configurable: false,
-                    enumerable: false,
-                    value: _parent }});
+    });
 };
 
 // Merge stuff defined in native code
diff --git a/modules/overrides/GObject.js b/modules/overrides/GObject.js
index e5cf3d6..7765b31 100644
--- a/modules/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -126,7 +126,6 @@ const GObjectMeta = new Lang.Class({
         // See Class.prototype._construct in lang.js for the reasoning
         // behind this direct __proto__ set.
         newClass.__proto__ = this.constructor.prototype;
-        newClass.__super__ = parent;
 
         newClass._init.apply(newClass, arguments);
 
@@ -248,6 +247,8 @@ function _init() {
         return this;
     };
 
+    this.Object.prototype.parent = Lang._parent;
+
     // fake enum for signal accumulators, keep in sync with gi/object.c
     this.AccumulatorType = {
         NONE: 0,
diff --git a/modules/overrides/Gio.js b/modules/overrides/Gio.js
index 37b1384..bc6bdc5 100644
--- a/modules/overrides/Gio.js
+++ b/modules/overrides/Gio.js
@@ -1,4 +1,4 @@
-// application/javascript;version=1.8
+// -*- mode: js; indent-tabs-mode: nil -*-
 // Copyright 2011 Giovanni Campagna
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,7 +24,7 @@ var GObject = imports.gi.GObject;
 var GjsPrivate = imports.gi.GjsPrivate;
 var Lang = imports.lang;
 var Signals = imports.signals;
-var Gio;
+var Gio = imports.gi.Gio;
 
 function _signatureLength(sig) {
     var counter = 0;
@@ -197,10 +197,17 @@ function _propertySetter(value, name, signature) {
               }));
 }
 
-function _addDBusConvenience() {
-    // Check if this is actually using new-style bindings
-    if (this.constructor instanceof DBusProxyClass)
-        return;
+function _proxyInitOverride(params) {
+    // Extend params with Interface and Interface.name
+    if (!params)
+        params = { };
+    if (!params.g_interface_name) {
+        params.g_interface_name = this.Interface.name;
+        params.g_interface_info = this.Interface;
+    }
+
+    // Build the actual object
+    this.parent(params);
 
     let info = this.g_interface_info;
     if (!info)
@@ -209,6 +216,11 @@ function _addDBusConvenience() {
     if (info.signals.length > 0)
         this.connect('g-signal', _convertToNativeSignal);
 
+    // Check if this is using new-style bindings (and thus
+    // invokers and property accessors are already installed)
+    if (this.constructor instanceof DBusProxyClass)
+        return;
+
     let i, methods = info.methods;
     for (i = 0; i < methods.length; i++) {
         var method = methods[i];
@@ -231,7 +243,12 @@ const DBusProxyClass = new Lang.Class({
     Extends: GObject.Class,
 
     _construct: function(params) {
-        params.Extends = Gio.DBusProxy;
+        if (!params.Extends)
+            params.Extends = Gio.DBusProxy;
+
+        if (!(params.Extends == Gio.DBusProxy ||
+              params.Extends.prototype instanceof Gio.DBusProxy))
+            throw new TypeError('Gio.DBusProxyClass used with invalid base class ' + params.Extends);
 
         return this.parent(params);
     },
@@ -242,18 +259,6 @@ const DBusProxyClass = new Lang.Class({
         if (!(classParams.Interface instanceof Gio.DBusInterfaceInfo))
             classParams.Interface = _newInterfaceInfo(classParams.Interface);
 
-        classParams._init = function(params) {
-            let klass = this.constructor;
-            if (!params)
-                params = { };
-            params.g_interface_name = this.Interface.name;
-            params.g_interface_info = this.Interface;
-
-            this.parent(params);
-
-            this.connect('g-signal', _convertToNativeSignal);
-        }
-
         // build the actual class
         this.parent(classParams);
 
@@ -571,8 +576,6 @@ function _wrapJSObject(interfaceInfo, jsObj) {
 }
 
 function _init() {
-    Gio = this;
-
     Gio.DBus = {
         get session() {
             return Gio.bus_get_sync(Gio.BusType.SESSION, null);
@@ -608,8 +611,7 @@ function _init() {
         return Gio.bus_unown_name(id);
     };
 
-    _injectToMethod(Gio.DBusProxy.prototype, 'init', _addDBusConvenience);
-    _injectToMethod(Gio.DBusProxy.prototype, 'init_async', _addDBusConvenience);
+    Gio.DBusProxy.prototype._init = Lang.Class.prototype.wrapFunction.call(Gio.DBusProxy, '_init', _proxyInitOverride);
 
     Gio.DBusProxyClass = DBusProxyClass;
     Gio.DBusProxy.prototype.__metaclass__ = DBusProxyClass;
diff --git a/test/js/testGDBus2.js b/test/js/testGDBus2.js
index 96d16f6..4ec5406 100644
--- a/test/js/testGDBus2.js
+++ b/test/js/testGDBus2.js
@@ -208,6 +208,18 @@ const TestProxy = new Lang.Class({
     Interface: TestIface,
 });
 
+const TestSlimProxy = new Lang.Class({
+    Name: 'TestSlimProxy',
+    Extends: Gio.DBusProxy,
+    Interface: TestIface,
+
+    _init: function() {
+	this.parent({ g_bus_type: Gio.BusType.SESSION,
+		      g_name: 'org.gnome.gjs.Test',
+		      g_object_path: '/org/gnome/gjs/Test' });
+    },
+});
+
 var proxy, exporter;
 
 function testExportStuff() {
@@ -251,6 +263,26 @@ function testInitStuff() {
     assertNotUndefined(proxy);
 }
 
+function testInitSlimStuff() {
+    var theError;
+    proxy = new TestSlimProxy();
+    proxy.init_async(GLib.PRIORITY_DEFAULT, null, function (obj, result) {
+        try {
+            obj.init_finish(result);
+        } catch(error) {
+            theError = error;
+            proxy = obj;
+        }
+
+        Mainloop.quit('testGDBus');
+    });
+
+    Mainloop.run('testGDBus');
+
+    assertUndefined(theError);
+    assertNotUndefined(proxy);
+}
+
 function testFrobateStuff() {
     let theResult, theExcp;
     proxy.frobateStuffRemote({}, null, function(proxy, result) {
@@ -386,8 +418,8 @@ function testEmitSignal() {
 
     assertUndefined('result should be undefined', theResult);
     assertUndefined('no exception set', theExcp);
-    assertEquals('number of signals received', signalReceived, 1);
-    assertEquals('signal argument', signalArgument, "foobar");
+    assertEquals('number of signals received', 1, signalReceived);
+    assertEquals('signal argument', 'foobar', signalArgument);
 
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]