[gjs] object: Support external construction of gjs-defined GObjects
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] object: Support external construction of gjs-defined GObjects
- Date: Thu, 10 Dec 2015 21:41:52 +0000 (UTC)
commit a7296c180771de23040d630e3f63e65eed16dfe5
Author: Florian Müllner <fmuellner gnome org>
Date: Tue Dec 1 13:30:54 2015 +0100
object: Support external construction of gjs-defined GObjects
Currently GObject subclasses defined in JS must be instantiated from JS
constructors, as that's where the association of the newly created native
object with the JS context and wrapper object happens. Allow this code to
run as well for GObjects that are instantiated externally via g_object_new()
(e.g. by GtkBuilder, gom, json-glib, ...) by creating the wrapper object
from the ->constructor() vfunc in that case.
https://bugzilla.gnome.org/show_bug.cgi?id=681254
gi/object.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 93 insertions(+), 10 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index ca31883..af79482 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2416,6 +2416,94 @@ gjs_object_get_gproperty (GObject *object,
}
static void
+jsobj_set_gproperty (JSContext *context,
+ JSObject *object,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ jsval jsvalue;
+ gchar *underscore_name;
+
+ if (!gjs_value_from_g_value(context, &jsvalue, value))
+ return;
+
+ underscore_name = hyphen_to_underscore((gchar *)pspec->name);
+ if (!JS_SetProperty(context, object, underscore_name, &jsvalue))
+ gjs_log_exception(context);
+ g_free (underscore_name);
+}
+
+static GObject *
+gjs_object_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *gobj = NULL;
+
+ if (object_init_list) {
+ GType parent_type = g_type_parent(type);
+
+ /* The object is being constructed from JS:
+ * Simply chain up to the first non-gjs constructor
+ */
+ while (G_OBJECT_CLASS(g_type_class_peek(parent_type))->constructor == gjs_object_constructor)
+ parent_type = g_type_parent(parent_type);
+
+ gobj = G_OBJECT_CLASS(g_type_class_peek(parent_type))->constructor(type, n_construct_properties,
construct_properties);
+ } else {
+ GjsContext *gjs_context;
+ JSContext *context;
+ JSObject *object, *constructor;
+ ObjectInstance *priv;
+
+ /* The object is being constructed from native code (e.g. GtkBuilder):
+ * Construct the JS object from the constructor, then use the GObject
+ * that was associated in gjs_object_custom_init()
+ */
+ gjs_context = gjs_context_get_current();
+ context = (JSContext*) gjs_context_get_native_context(gjs_context);
+
+ JS_BeginRequest(context);
+
+ constructor = gjs_lookup_object_constructor_from_info(context, NULL, type);
+ if (!constructor)
+ goto out;
+
+ if (n_construct_properties) {
+ JSObject *args;
+ jsval argv;
+ guint i;
+
+ args = JS_NewObject(context, NULL, NULL, NULL);
+
+ for (i = 0; i < n_construct_properties; i++)
+ jsobj_set_gproperty(context, args,
+ construct_properties[i].value,
+ construct_properties[i].pspec);
+
+ argv = OBJECT_TO_JSVAL(args);
+ object = JS_New(context, constructor, 1, &argv);
+ } else {
+ object = JS_New(context, constructor, 0, NULL);
+ }
+
+ if (!object)
+ goto out;
+
+ priv = (ObjectInstance*) JS_GetPrivate(object);
+ /* We only hold a toggle ref at this point, add back a ref that the
+ * native code can own.
+ */
+ gobj = G_OBJECT(g_object_ref(priv->gobj));
+
+out:
+ JS_EndRequest(context);
+ }
+
+ return gobj;
+}
+
+static void
gjs_object_set_gproperty (GObject *object,
guint property_id,
const GValue *value,
@@ -2424,21 +2512,12 @@ gjs_object_set_gproperty (GObject *object,
GjsContext *gjs_context;
JSContext *context;
JSObject *js_obj;
- jsval jsvalue;
- gchar *underscore_name;
gjs_context = gjs_context_get_current();
context = (JSContext*) gjs_context_get_native_context(gjs_context);
js_obj = peek_js_obj(object);
-
- if (!gjs_value_from_g_value(context, &jsvalue, value))
- return;
-
- underscore_name = hyphen_to_underscore((gchar *)pspec->name);
- if (!JS_SetProperty(context, js_obj, underscore_name, &jsvalue))
- gjs_log_exception(context);
- g_free (underscore_name);
+ jsobj_set_gproperty(context, js_obj, value, pspec);
}
static JSBool
@@ -2527,6 +2606,7 @@ gjs_object_class_init(GObjectClass *klass,
gtype = G_OBJECT_CLASS_TYPE (klass);
+ klass->constructor = gjs_object_constructor;
klass->set_property = gjs_object_set_gproperty;
klass->get_property = gjs_object_get_gproperty;
@@ -2554,6 +2634,9 @@ gjs_object_custom_init(GTypeInstance *instance,
ObjectInstance *priv;
jsval v, r;
+ if (!object_init_list)
+ return;
+
object = (JSObject*) object_init_list->data;
priv = (ObjectInstance*) JS_GetPrivate(object);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]