From 62ac6bbcc6929ff0f9b4c2c1ec42da2391bd9777 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Tue, 14 May 2013 22:56:48 +0200 Subject: 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 file changed, 44 insertions(+), 69 deletions(-) diff --git a/gi/object.c b/gi/object.c index a49dae71..1462cbff 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; @@ -103,16 +103,6 @@ typedef enum { VALUE_WAS_SET } 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) { @@ -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; -- cgit v1.2.1