diff options
author | Giovanni Campagna <gcampagna@src.gnome.org> | 2013-05-14 22:56:48 +0200 |
---|---|---|
committer | Giovanni Campagna <gcampagna@src.gnome.org> | 2013-05-19 23:07:55 +0200 |
commit | 62ac6bbcc6929ff0f9b4c2c1ec42da2391bd9777 (patch) | |
tree | d8ec0531c4fe1ee0c29d023c3a64c87c03c115fe | |
parent | 639e145b7f9b9445479f5f74b55bf89a3ad92b4e (diff) | |
download | gjs-62ac6bbcc6929ff0f9b4c2c1ec42da2391bd9777.tar.gz |
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
-rw-r--r-- | gi/object.c | 113 |
1 files 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; @@ -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; |