diff options
author | Giovanni Campagna <gcampagna@src.gnome.org> | 2012-06-21 00:18:44 +0200 |
---|---|---|
committer | Giovanni Campagna <gcampagna@src.gnome.org> | 2012-10-30 17:24:27 +0100 |
commit | cb1e0cf02b3fd93000fb084ff57feb4786453014 (patch) | |
tree | a7f36275833529df52b85377f9b7eccb1ef5ee05 | |
parent | 22eba902546f50147058fd5a17a7930565395eda (diff) | |
download | gjs-cb1e0cf02b3fd93000fb084ff57feb4786453014.tar.gz |
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
-rw-r--r-- | modules/lang.js | 22 | ||||
-rw-r--r-- | modules/overrides/GObject.js | 3 | ||||
-rw-r--r-- | modules/overrides/Gio.js | 48 | ||||
-rw-r--r-- | test/js/testGDBus2.js | 36 |
4 files changed, 74 insertions, 35 deletions
diff --git a/modules/lang.js b/modules/lang.js index 9e5c6c41..84748b0e 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 e5cf3d61..7765b31e 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 37b13847..bc6bdc55 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 96d16f69..4ec54064 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); } |