[gjs] GObject: register interfaces before creating the class
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] GObject: register interfaces before creating the class
- Date: Mon, 19 Nov 2012 22:25:38 +0000 (UTC)
commit 2405137343a8f9697f677a0f0044868971b6574e
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Mon Nov 19 20:03:26 2012 +0100
GObject: register interfaces before creating the class
Recent GType emits a warning and fails if g_type_add_interface_static()
is called on a GType that had its class referenced already, so we need
to register interfaces before even creating the JS class (as that references
the GType class)
https://bugzilla.gnome.org/show_bug.cgi?id=688214
gi/object.c | 81 +++++++++++++++++++++++++----------------
modules/overrides/GObject.js | 16 +++-----
2 files changed, 55 insertions(+), 42 deletions(-)
---
diff --git a/gi/object.c b/gi/object.c
index 7e83a15..018acd1 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -2265,6 +2265,17 @@ gjs_object_class_init(GObjectClass *class,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
}
+static inline void
+gjs_add_interface(GType instance_type,
+ GType interface_type)
+{
+ static GInterfaceInfo interface_vtable = { NULL, NULL, NULL };
+
+ g_type_add_interface_static(instance_type,
+ interface_type,
+ &interface_vtable);
+}
+
static JSBool
gjs_register_type(JSContext *cx,
uintN argc,
@@ -2272,7 +2283,7 @@ gjs_register_type(JSContext *cx,
{
jsval *argv = JS_ARGV(cx, vp);
gchar *name;
- JSObject *parent, *constructor;
+ JSObject *parent, *constructor, *interfaces;
GType instance_type, parent_type;
GTypeQuery query;
GTypeModule *type_module;
@@ -2291,13 +2302,16 @@ gjs_register_type(JSContext *cx,
0, /* n_preallocs */
(GInstanceInitFunc) NULL,
};
+ jsuint i, n_interfaces;
+ GType *iface_types;
JS_BeginRequest(cx);
if (!gjs_parse_args(cx, "register_type",
- "os", argc, argv,
+ "oso", argc, argv,
"parent", &parent,
- "name", &name))
+ "name", &name,
+ "interfaces", &interfaces))
return JS_FALSE;
if (!parent)
@@ -2306,6 +2320,35 @@ gjs_register_type(JSContext *cx,
if (!do_base_typecheck(cx, parent, JS_TRUE))
return JS_FALSE;
+ if (!JS_IsArrayObject(cx, interfaces)) {
+ gjs_throw(cx, "Invalid parameter interfaces (expected Array)");
+ return JS_FALSE;
+ }
+
+ if (!JS_GetArrayLength(cx, interfaces, &n_interfaces))
+ return JS_FALSE;
+
+ iface_types = g_alloca(sizeof(GType) * n_interfaces);
+
+ /* We do interface addition in two passes so that any failure
+ is caught early, before registering the GType (which we can't undo) */
+ for (i = 0; i < n_interfaces; i++) {
+ jsval iface_val;
+ GType iface_type;
+
+ if (!JS_GetElement(cx, interfaces, i, &iface_val))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_OBJECT(iface_val) ||
+ ((iface_type = gjs_gtype_get_actual_gtype(cx, JSVAL_TO_OBJECT(iface_val)))
+ == G_TYPE_INVALID)) {
+ gjs_throw(cx, "Invalid parameter interfaces (element %d was not a GType)", i);
+ return JS_FALSE;
+ }
+
+ iface_types[i] = iface_type;
+ }
+
if (g_type_from_name(name) != G_TYPE_INVALID) {
gjs_throw (cx, "Type name %s is already registered", name);
return JS_FALSE;
@@ -2338,6 +2381,9 @@ gjs_register_type(JSContext *cx,
g_type_set_qdata (instance_type, gjs_is_custom_type_quark(), GINT_TO_POINTER (1));
+ for (i = 0; i < n_interfaces; i++)
+ gjs_add_interface(instance_type, iface_types[i]);
+
/* create a custom JSClass */
if (!gjs_define_object_class(cx, NULL, instance_type, &constructor, NULL))
return JS_FALSE;
@@ -2350,35 +2396,6 @@ gjs_register_type(JSContext *cx,
}
static JSBool
-gjs_add_interface(JSContext *cx,
- uintN argc,
- jsval *vp)
-{
- jsval *argv = JS_ARGV(cx, vp);
- GInterfaceInfo interface_vtable = { NULL, NULL, NULL };
- ObjectInstance *priv;
- JSObject *object;
- JSObject *iface_jsobj;
-
- if (!gjs_parse_args(cx, "add_interface",
- "oo", argc, argv,
- "object", &object,
- "gtype", &iface_jsobj))
- return JS_FALSE;
-
- if (!do_base_typecheck(cx, object, JS_TRUE))
- return JS_FALSE;
-
- priv = priv_from_js(cx, object);
-
- g_type_add_interface_static(priv->gtype,
- gjs_gtype_get_actual_gtype(cx, iface_jsobj),
- &interface_vtable);
-
- return JS_TRUE;
-}
-
-static JSBool
gjs_register_property(JSContext *cx,
uintN argc,
jsval *vp)
diff --git a/modules/overrides/GObject.js b/modules/overrides/GObject.js
index e5cf3d6..7902abc 100644
--- a/modules/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -29,17 +29,15 @@ const GObjectMeta = new Lang.Class({
Extends: Lang.Class,
_init: function(params) {
- this.parent(params);
-
// retrieve all parameters and remove them from params before chaining
let properties = params.Properties;
let signals = params.Signals;
- let ifaces = params.Implements;
delete params.Properties;
delete params.Signals;
- delete params.Implements;
+
+ this.parent(params);
if (properties) {
for (let prop in properties) {
@@ -63,11 +61,6 @@ const GObjectMeta = new Lang.Class({
}
}
- if (ifaces) {
- for (let i = 0; i < ifaces.length; i++)
- Gi.add_interface(this.prototype, ifaces[i]);
- }
-
for (let prop in params) {
let value = this.prototype[prop];
if (typeof value === 'function') {
@@ -121,7 +114,10 @@ const GObjectMeta = new Lang.Class({
if (!this._isValidClass(parent))
throw new TypeError('GObject.Class used with invalid base class (is ' + parent + ')');
- let newClass = Gi.register_type(parent.prototype, gtypename);
+ let interfaces = params.Implements || [];
+ delete params.Implements;
+
+ let newClass = Gi.register_type(parent.prototype, gtypename, interfaces);
// See Class.prototype._construct in lang.js for the reasoning
// behind this direct __proto__ set.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]