[gjs] object: stop using GObject properties to set up context and instance for derived classes



commit 62ac6bbcc6929ff0f9b4c2c1ec42da2391bd9777
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue May 14 22:56:48 2013 +0200

    object: stop using GObject properties to set up context and instance for derived classes
    
    It was an ugly hack, that would easily break with derived classes.
    Instead, use a global stack of constructing objects, that is
    pushed when building the JS object and retrieved in instance_init()
    
    https://bugzilla.gnome.org/show_bug.cgi?id=699817

 gi/object.c |  113 +++++++++++++++++++++++------------------------------------
 1 files changed, 44 insertions(+), 69 deletions(-)
---
diff --git a/gi/object.c b/gi/object.c
index a49dae7..1462cbf 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -82,11 +82,11 @@ typedef struct
 
 enum {
     PROP_0,
-    PROP_JS_CONTEXT,
-    PROP_JS_OBJECT,
     PROP_JS_HANDLED,
 };
 
+static GSList *object_init_list;
+
 static struct JSClass gjs_object_instance_class;
 static GThread *gjs_eval_thread;
 static volatile gint pending_idle_toggles;
@@ -104,16 +104,6 @@ typedef enum {
 } ValueFromPropertyResult;
 
 static GQuark
-gjs_context_quark(void)
-{
-    static GQuark val = 0;
-    if (!val)
-        val = g_quark_from_static_string ("gjs::context");
-
-    return val;
-}
-
-static GQuark
 gjs_is_custom_type_quark (void)
 {
     static GQuark val = 0;
@@ -677,28 +667,6 @@ object_instance_props_to_g_parameters(JSContext   *context,
     gparams = g_array_new(/* nul term */ FALSE, /* clear */ TRUE,
                           sizeof(GParameter));
 
-    /* For custom types we register, we need to set additional
-       properties for the JS context and JS object, so that we can retrieve
-       them inside the constructor, when handling construct properties
-       There is no other way to set those, as we need them before
-       g_object_newv returns.
-       We also need to ensure that these are the first properties set
-       (luckily g_object_newv preserves the order)
-    */
-    if (g_type_get_qdata(gtype, gjs_is_custom_type_quark())) {
-        GParameter gparam = { "js-context", { 0, } };
-
-        g_value_init(&gparam.value, G_TYPE_POINTER);
-        g_value_set_pointer(&gparam.value, context);
-
-        g_array_append_val(gparams, gparam);
-
-        gparam.name = "js-object";
-        g_value_set_pointer(&gparam.value, obj);
-
-        g_array_append_val(gparams, gparam);
-    }
-
     if (argc == 0 || JSVAL_IS_VOID(argv[0]))
         goto out;
 
@@ -1210,6 +1178,13 @@ object_instance_init (JSContext *context,
         return JS_FALSE;
     }
 
+    /* Mark this object in the construction stack, it
+       will be popped in gjs_object_custom_init() later
+       down.
+    */
+    if (g_type_get_qdata(gtype, gjs_is_custom_type_quark()))
+        object_init_list = g_slist_prepend(object_init_list, *object);
+
     gobj = g_object_newv(gtype, n_params, params);
 
     free_g_params(params, n_params);
@@ -2334,17 +2309,15 @@ gjs_object_get_gproperty (GObject    *object,
                           GValue     *value,
                           GParamSpec *pspec)
 {
+    GjsContext *gjs_context;
     JSContext *context;
     JSObject *js_obj;
     jsval jsvalue;
     gchar *underscore_name;
 
-    if (property_id != PROP_JS_HANDLED) {
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-        return;
-    }
+    gjs_context = gjs_context_get_current();
+    context = gjs_context_get_native_context(gjs_context);
 
-    context = g_object_get_qdata(object, gjs_context_quark());
     js_obj = peek_js_obj(object);
 
     underscore_name = hyphen_to_underscore((gchar *)pspec->name);
@@ -2361,29 +2334,14 @@ gjs_object_set_gproperty (GObject      *object,
                           const GValue *value,
                           GParamSpec   *pspec)
 {
+    GjsContext *gjs_context;
     JSContext *context;
     JSObject *js_obj;
     jsval jsvalue;
     gchar *underscore_name;
 
-    if (property_id == PROP_JS_CONTEXT) {
-        context = g_value_get_pointer (value);
-        g_object_set_qdata(object, gjs_context_quark(), context);
-        return;
-    }
-
-    context = g_object_get_qdata(object, gjs_context_quark());
-
-    if (property_id == PROP_JS_OBJECT) {
-        js_obj = g_value_get_pointer (value);
-        associate_js_gobject(context, js_obj, object);
-        return;
-    }
-
-    if (property_id != PROP_JS_HANDLED) {
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-        return;
-    }
+    gjs_context = gjs_context_get_current();
+    context = gjs_context_get_native_context(gjs_context);
 
     js_obj = peek_js_obj(object);
 
@@ -2402,20 +2360,37 @@ gjs_object_class_init(GObjectClass *class,
     class->set_property = gjs_object_set_gproperty;
     class->get_property = gjs_object_get_gproperty;
 
-    g_object_class_install_property (class, PROP_JS_CONTEXT,
-                                     g_param_spec_pointer ("js-context",
-                                                           "JSContext",
-                                                           "The JSContext this object was created for",
-                                                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS));
-
-    g_object_class_install_property (class, PROP_JS_OBJECT,
-                                     g_param_spec_pointer ("js-object",
-                                                           "JSObject",
-                                                           "The JSObject wrapping this GObject",
-                                                           G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS));
     gjs_eval_thread = g_thread_self();
 }
 
+static void
+gjs_object_custom_init(GTypeInstance *instance,
+                       gpointer       g_class)
+{
+    GjsContext *gjs_context;
+    JSContext *context;
+    JSObject *object;
+    ObjectInstance *priv;
+
+    object = object_init_list->data;
+    priv = JS_GetPrivate(object);
+
+    if (priv->gtype != G_TYPE_FROM_INSTANCE (instance)) {
+        /* This is not the most derived instance_init function,
+           do nothing.
+         */
+        return;
+    }
+
+    object_init_list = g_slist_delete_link(object_init_list,
+                                           object_init_list);
+
+    gjs_context = gjs_context_get_current();
+    context = gjs_context_get_native_context(gjs_context);
+
+    associate_js_gobject(context, object, G_OBJECT (instance));
+}
+
 static inline void
 gjs_add_interface(GType instance_type,
                   GType interface_type)
@@ -2451,7 +2426,7 @@ gjs_register_type(JSContext *cx,
 
        0,    /* instance_size */
        0,    /* n_preallocs */
-       (GInstanceInitFunc) NULL,
+       gjs_object_custom_init,
     };
     guint32 i, n_interfaces;
     GType *iface_types;


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