[gjs] Introduce infrastructure for override modules



commit c425d9063db5ea21af5dc1ca04681e1d958dbc3d
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Tue Mar 29 16:51:55 2011 +0200

    Introduce infrastructure for override modules
    
    Override modules are JS modules that can subsume or replace native
    modules from GObject Introspection.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=646633

 Makefile-modules.am      |    3 ++
 Makefile.am              |    3 +-
 gi/ns.c                  |   18 +---------
 gi/ns.h                  |    3 +-
 gi/repo.c                |   77 ++++++++++++++++++++++++++++++++++++++++++++--
 gjs/jsapi-util.h         |    2 +-
 modules/overrides/Gio.js |    2 +
 7 files changed, 85 insertions(+), 23 deletions(-)
---
diff --git a/Makefile-modules.am b/Makefile-modules.am
index c43b2d8..fb1864d 100644
--- a/Makefile-modules.am
+++ b/Makefile-modules.am
@@ -3,6 +3,9 @@ dist_gjstweener_DATA =			\
 	modules/tweener/tweener.js	\
 	modules/tweener/tweenList.js
 
+dist_gjsoverride_DATA = 		\
+	modules/overrides/Gio.js
+
 dist_gjsjs_DATA +=		\
 	modules/gettext.js	\
 	modules/lang.js		\
diff --git a/Makefile.am b/Makefile.am
index f1a7777..b0e433a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,8 @@ TEST_PROGS =
 check_PROGRAMS = $(TEST_PROGS)
 
 gjsjsdir = @gjsjsdir@
-gjstweenerdir = @gjsjsdir@/tweener
+gjsoverridedir = $(gjsjsdir)/overrides
+gjstweenerdir = $(gjsjsdir)/tweener
 gjsnativedir = @gjsnativedir@
 
 gjs_public_includedir = $(includedir)/gjs-1.0
diff --git a/gi/ns.c b/gi/ns.c
index b9a1ea7..1033969 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -287,23 +287,9 @@ ns_new(JSContext    *context,
 }
 
 JSObject*
-gjs_define_ns(JSContext    *context,
-              JSObject     *in_object,
+gjs_create_ns(JSContext    *context,
               const char   *ns_name,
               GIRepository *repo)
 {
-    JSObject *ns;
-
-    ns = ns_new(context, ns_name, repo);
-
-    if (!JS_DefineProperty(context, in_object,
-                           ns_name, OBJECT_TO_JSVAL(ns),
-                           NULL, NULL,
-                           GJS_MODULE_PROP_FLAGS))
-        gjs_fatal("no memory to define ns property");
-
-    gjs_debug(GJS_DEBUG_GNAMESPACE,
-              "Defined namespace '%s' %p in GIRepository %p", ns_name, ns, in_object);
-
-    return ns;
+    return ns_new(context, ns_name, repo);
 }
diff --git a/gi/ns.h b/gi/ns.h
index d5bf2ac..f717ea6 100644
--- a/gi/ns.h
+++ b/gi/ns.h
@@ -32,8 +32,7 @@
 
 G_BEGIN_DECLS
 
-JSObject* gjs_define_ns(JSContext    *context,
-                        JSObject     *in_object,
+JSObject* gjs_create_ns(JSContext    *context,
                         const char   *ns_name,
                         GIRepository *repo);
 
diff --git a/gi/repo.c b/gi/repo.c
index a17ed4c..955f561 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -50,6 +50,8 @@ static struct JSClass gjs_repo_class;
 
 GJS_DEFINE_PRIV_FROM_JS(Repo, gjs_repo_class)
 
+static JSObject * lookup_override_function(JSContext *, const char *);
+
 static JSObject*
 resolve_namespace_object(JSContext  *context,
                          JSObject   *repo_obj,
@@ -61,7 +63,9 @@ resolve_namespace_object(JSContext  *context,
     JSObject *versions;
     jsval version_val;
     char *version;
-    JSObject *result;
+    JSObject *namespace;
+    JSObject *override;
+    jsval result;
 
     JS_BeginRequest(context);
 
@@ -101,9 +105,33 @@ resolve_namespace_object(JSContext  *context,
      * with the given namespace name, pointing to that namespace
      * in the repo.
      */
-    result = gjs_define_ns(context, repo_obj, ns_name, repo);
+    namespace = gjs_create_ns(context, ns_name, repo);
+    JS_AddObjectRoot(context, &namespace);
+
+    override = lookup_override_function(context, ns_name);
+    if (override && !JS_CallFunctionValue (context,
+                                           namespace, /* thisp */
+                                           OBJECT_TO_JSVAL(override), /* callee */
+                                           0, /* argc */
+                                           NULL, /* argv */
+                                           &result)) {
+        JS_RemoveObjectRoot(context, &namespace);
+        JS_EndRequest(context);
+        return NULL;
+    }
+
+    if (!JS_DefineProperty(context, repo_obj,
+                           ns_name, OBJECT_TO_JSVAL(namespace),
+                           NULL, NULL,
+                           GJS_MODULE_PROP_FLAGS))
+        gjs_fatal("no memory to define ns property");
+
+    gjs_debug(GJS_DEBUG_GNAMESPACE,
+              "Defined namespace '%s' %p in GIRepository %p", ns_name, namespace, repo_obj);
+
+    JS_RemoveObjectRoot(context, &namespace);
     JS_EndRequest(context);
-    return result;
+    return namespace;
 }
 
 /*
@@ -503,6 +531,49 @@ gjs_lookup_namespace_object(JSContext  *context,
     return gjs_lookup_namespace_object_by_name(context, ns);
 }
 
+static JSObject*
+lookup_override_function(JSContext  *context,
+                         const char *ns)
+{
+    JSObject *global;
+    jsval importer;
+    jsval overridespkg;
+    jsval module;
+    jsval function;
+
+    JS_BeginRequest(context);
+    global = gjs_get_import_global(context);
+
+    importer = JSVAL_VOID;
+    if (!gjs_object_require_property(context, global, "global object", "imports", &importer) ||
+        !JSVAL_IS_OBJECT(importer))
+        goto fail;
+
+    overridespkg = JSVAL_VOID;
+    if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(importer), "importer",
+                                        "overrides", &overridespkg) ||
+        !JSVAL_IS_OBJECT(overridespkg))
+        goto fail;
+
+    module = JSVAL_VOID;
+    if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(overridespkg), "GI repository object", ns, &module)
+        || !JSVAL_IS_OBJECT(module))
+        goto fail;
+
+    if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(module), "override module",
+                                     "_init", &function) ||
+        !JSVAL_IS_OBJECT(function))
+        goto fail;
+
+    JS_EndRequest(context);
+    return JSVAL_TO_OBJECT(function);
+
+ fail:
+    JS_ClearPendingException(context);
+    JS_EndRequest(context);
+    return NULL;
+}
+
 JSObject*
 gjs_lookup_namespace_object_by_name(JSContext      *context,
                                     const char     *ns)
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 4d61916..bd3c5fe 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -53,7 +53,7 @@ typedef struct GjsRootedArray GjsRootedArray;
  * PERMANENT: forbid deleting the prop
  * ENUMERATE: allows copyProperties to work among other reasons to have it
  */
-#define GJS_MODULE_PROP_FLAGS (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_ENUMERATE)
+#define GJS_MODULE_PROP_FLAGS (JSPROP_PERMANENT | JSPROP_ENUMERATE)
 
 /* priv_from_js_with_typecheck checks that the object is in fact an
  * instance of the specified class before accessing its private data.
diff --git a/modules/overrides/Gio.js b/modules/overrides/Gio.js
new file mode 100644
index 0000000..bbb3bbe
--- /dev/null
+++ b/modules/overrides/Gio.js
@@ -0,0 +1,2 @@
+function _init() {
+}



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