[gjs] Check for a builtin module before beginning to load it



commit 1fb10969bed279e7266de50f31d28c49352778d2
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Fri Dec 10 11:21:04 2010 -0500

    Check for a builtin module before beginning to load it
    
    When used to check for builtin modules, import_native_file() would create a
    module object, set properties on it, store it in the native class, fail
    to load a builtin module of that name, and then back everything out.
    Add a pre-check to avoid this. (It means that we do extract the module ID
    twice when we actually load a built-in module, but built-in modules will
    a small fraction of modules.)
    
    V2: Modified by Colin Walters <walters verbum org> for the fact that
    gjs_string_get_ascii() now mallocs.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=635371

 gjs/importer.c |    3 +-
 gjs/native.c   |  132 +++++++++++++++++++++++++++++++++++++++----------------
 gjs/native.h   |    5 ++
 3 files changed, 100 insertions(+), 40 deletions(-)
---
diff --git a/gjs/importer.c b/gjs/importer.c
index 4c03582..d875a38 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -515,7 +515,8 @@ do_import(JSContext  *context,
     directories = NULL;
 
     /* First try importing an internal module like byteArray */
-    if (import_native_file(context, obj, name, NULL)) {
+    if (gjs_is_registered_native_module(context, obj, name) &&
+        import_native_file(context, obj, name, NULL)) {
         gjs_debug(GJS_DEBUG_IMPORTER,
                   "successfully imported module '%s'", name);
         result = JS_TRUE;
diff --git a/gjs/native.c b/gjs/native.c
index 822fd6a..c2d49f9 100644
--- a/gjs/native.c
+++ b/gjs/native.c
@@ -90,6 +90,88 @@ module_get_parent(JSContext *context,
     }
 }
 
+static char *
+get_module_name(JSContext *context,
+                JSObject  *module_obj,
+                jsval     *tmp)
+{
+    if (gjs_object_get_property(context, module_obj, "__moduleName__", tmp) &&
+        JSVAL_IS_STRING(*tmp))
+        return gjs_string_get_ascii(context, *tmp);
+    else
+        return NULL;
+}
+
+static GjsNativeModule *
+lookup_native_module(JSContext  *context,
+                     JSObject   *parent,
+                     const char *name,
+                     gboolean    is_definition)
+{
+    GjsNativeModule *native_module;
+    GString *module_id;
+
+    module_id = g_string_new(name);
+    while (parent != NULL) {
+        const char *name;
+        jsval tmp;
+
+        name = get_module_name(context, parent, &tmp);
+        if (name != NULL) {
+            g_string_prepend(module_id, name);
+        }
+
+        /* Move up to parent */
+        parent = module_get_parent(context, parent);
+    }
+
+    if (is_definition)
+        gjs_debug(GJS_DEBUG_NATIVE,
+                  "Defining native module '%s'",
+                  module_id->str);
+
+    if (modules != NULL)
+        native_module = g_hash_table_lookup(modules, module_id->str);
+    else
+        native_module = NULL;
+
+    if (native_module == NULL) {
+        if (is_definition) {
+            gjs_throw(context,
+                      "No native module '%s' has registered itself",
+                      module_id->str);
+        }
+        g_string_free(module_id, TRUE);
+        return NULL;
+    }
+
+    g_string_free(module_id, TRUE);
+
+    return native_module;
+}
+
+/**
+ * gjs_is_registered_native_module:
+ * @context:
+ * @parent: the parent object defining the namespace
+ * @name: name of the module
+ *
+ * Checks if a native module corresponding to @name has already
+ * been registered. This is used to check to see if a name is a
+ * builtin module without starting to try and load it.
+ */
+gboolean
+gjs_is_registered_native_module(JSContext  *context,
+                                JSObject   *parent,
+                                const char *name)
+{
+    GjsNativeModule *native_module;
+
+    native_module = lookup_native_module(context, parent, name, FALSE);
+
+    return native_module != NULL;
+}
+
 /**
  * gjs_import_native_module:
  * @context:
@@ -108,9 +190,9 @@ gjs_import_native_module(JSContext        *context,
                          GjsNativeFlags *flags_p)
 {
     GModule *gmodule = NULL;
-    GString *module_id;
-    JSObject *parent;
     GjsNativeModule *native_module;
+    JSObject *parent;
+    jsval tmp;
 
     if (flags_p)
         *flags_p = 0;
@@ -133,49 +215,21 @@ gjs_import_native_module(JSContext        *context,
      * a native module. We just have to reverse-engineer
      * the module id from module_obj.
      */
-    module_id = g_string_new(NULL);
-    parent = module_obj;
-    while (parent != NULL) {
-        jsval value;
-
-        if (gjs_object_get_property(context, parent, "__moduleName__", &value) &&
-            JSVAL_IS_STRING(value)) {
-            char *name;
-            name = gjs_string_get_ascii(context, value);
-
-            if (module_id->len > 0)
-                g_string_prepend(module_id, ".");
-
-            g_string_prepend(module_id, name);
-            g_free(name);
-        }
-
-        /* Move up to parent */
-        parent = module_get_parent(context, parent);
+    {
+        char *module_name = get_module_name(context, module_obj, &tmp);
+        native_module = lookup_native_module (context,
+                                              module_get_parent(context, module_obj),
+                                              module_name,
+                                              TRUE);
+        g_free(module_name);
     }
 
-    gjs_debug(GJS_DEBUG_NATIVE,
-              "Defining native module '%s'",
-              module_id->str);
-
-    if (modules != NULL)
-        native_module = g_hash_table_lookup(modules, module_id->str);
-    else
-        native_module = NULL;
-
-    if (native_module == NULL) {
-        if (filename) {
-            gjs_throw(context,
-                      "No native module '%s' has registered itself",
-                      module_id->str);
+    if (!native_module) {
+        if (gmodule)
             g_module_close(gmodule);
-        }
-        g_string_free(module_id, TRUE);
         return JS_FALSE;
     }
 
-    g_string_free(module_id, TRUE);
-
     if (flags_p)
         *flags_p = native_module->flags;
 
diff --git a/gjs/native.h b/gjs/native.h
index 4a8224e..f30d763 100644
--- a/gjs/native.h
+++ b/gjs/native.h
@@ -81,6 +81,11 @@ void   gjs_register_native_module (const char            *module_id,
                                    GjsDefineModuleFunc  func,
                                    GjsNativeFlags       flags);
 
+/* called by importer.c to to check for already loaded modules */
+gboolean gjs_is_registered_native_module(JSContext  *context,
+                                         JSObject   *parent,
+                                         const char *name);
+
 /* called by importer.c to load a native module once it finds
  * it in the search path
  */



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