summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagna@src.gnome.org>2012-06-21 00:18:44 +0200
committerGiovanni Campagna <gcampagna@src.gnome.org>2012-10-30 17:24:27 +0100
commitcb1e0cf02b3fd93000fb084ff57feb4786453014 (patch)
treea7f36275833529df52b85377f9b7eccb1ef5ee05
parent22eba902546f50147058fd5a17a7930565395eda (diff)
downloadgjs-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.js22
-rw-r--r--modules/overrides/GObject.js3
-rw-r--r--modules/overrides/Gio.js48
-rw-r--r--test/js/testGDBus2.js36
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);
}