[gjs/wip/fix-imports] Revert recent import changes
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/fix-imports] Revert recent import changes
- Date: Wed, 2 Oct 2013 03:10:31 +0000 (UTC)
commit eb3edba5f7e4a68f9e81a276ba74c64038def0ea
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Tue Oct 1 23:08:56 2013 -0400
Revert recent import changes
These don't do well with circular imports, so revert them for now.
I'll have to land a revised patch soon.
gi/object.c | 10 +-
gi/repo.c | 9 +-
gi/repo.h | 2 +-
gjs/byteArray.c | 13 +--
gjs/byteArray.h | 2 +-
gjs/context.c | 6 +-
gjs/gi.c | 4 +-
gjs/gi.h | 4 +-
gjs/importer.c | 373 ++++++++++++++++++++++++++++++++----------------
gjs/native.c | 75 ++++++++--
gjs/native.h | 30 +++-
modules/cairo-module.h | 2 +-
modules/cairo.c | 7 +-
modules/console.c | 11 +-
modules/console.h | 2 +-
modules/modules.c | 6 +-
modules/system.c | 8 +-
modules/system.h | 2 +-
18 files changed, 372 insertions(+), 194 deletions(-)
---
diff --git a/gi/object.c b/gi/object.c
index 039b65f..0549254 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -2676,16 +2676,10 @@ static JSFunctionSpec module_funcs[] = {
JSBool
gjs_define_private_gi_stuff(JSContext *context,
- JSObject **module_out)
+ JSObject *module_obj)
{
- JSObject *module;
-
- module = JS_NewObject (context, NULL, NULL, NULL);
-
- if (!JS_DefineFunctions(context, module, &module_funcs[0]))
+ if (!JS_DefineFunctions(context, module_obj, &module_funcs[0]))
return JS_FALSE;
- *module_out = module;
-
return JS_TRUE;
}
diff --git a/gi/repo.c b/gi/repo.c
index 993290a..3b10d90 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -345,13 +345,18 @@ repo_new(JSContext *context)
JSBool
gjs_define_repo(JSContext *context,
- JSObject **module_out,
+ JSObject *module_obj,
const char *name)
{
JSObject *repo;
repo = repo_new(context);
- *module_out = repo;
+
+ if (!JS_DefineProperty(context, module_obj,
+ name, OBJECT_TO_JSVAL(repo),
+ NULL, NULL,
+ GJS_MODULE_PROP_FLAGS))
+ return JS_FALSE;
return JS_TRUE;
}
diff --git a/gi/repo.h b/gi/repo.h
index 60d5be4..940a6e7 100644
--- a/gi/repo.h
+++ b/gi/repo.h
@@ -33,7 +33,7 @@
G_BEGIN_DECLS
JSBool gjs_define_repo (JSContext *context,
- JSObject **module_out,
+ JSObject *module_obj,
const char *name);
const char* gjs_info_type_name (GIInfoType type);
JSObject* gjs_lookup_private_namespace (JSContext *context);
diff --git a/gjs/byteArray.c b/gjs/byteArray.c
index 1145b9e..4597d68 100644
--- a/gjs/byteArray.c
+++ b/gjs/byteArray.c
@@ -910,14 +910,10 @@ static JSFunctionSpec gjs_byte_array_module_funcs[] = {
};
JSBool
-gjs_define_byte_array_stuff(JSContext *context,
- JSObject **module_out)
+gjs_define_byte_array_stuff(JSContext *context,
+ JSObject *in_object)
{
- JSObject *module;
-
- module = JS_NewObject (context, NULL, NULL, NULL);
-
- gjs_byte_array_prototype = JS_InitClass(context, module,
+ gjs_byte_array_prototype = JS_InitClass(context, in_object,
NULL,
&gjs_byte_array_class,
gjs_byte_array_constructor,
@@ -930,9 +926,8 @@ gjs_define_byte_array_stuff(JSContext *context,
if (gjs_byte_array_prototype == NULL)
return JS_FALSE;
- if (!JS_DefineFunctions(context, module, &gjs_byte_array_module_funcs[0]))
+ if (!JS_DefineFunctions(context, in_object, &gjs_byte_array_module_funcs[0]))
return JS_FALSE;
- *module_out = module;
return JS_TRUE;
}
diff --git a/gjs/byteArray.h b/gjs/byteArray.h
index c3b4234..2d0dadc 100644
--- a/gjs/byteArray.h
+++ b/gjs/byteArray.h
@@ -38,7 +38,7 @@ JSBool gjs_typecheck_bytearray (JSContext *context,
JSBool throw);
JSBool gjs_define_byte_array_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *in_object);
JSObject * gjs_byte_array_from_byte_array (JSContext *context,
GByteArray *array);
diff --git a/gjs/context.c b/gjs/context.c
index cb2fe1b..c9353d7 100644
--- a/gjs/context.c
+++ b/gjs/context.c
@@ -354,9 +354,9 @@ gjs_context_class_init(GjsContextClass *klass)
g_free (priv_typelib_dir);
}
- gjs_register_native_module("byteArray", gjs_define_byte_array_stuff);
- gjs_register_native_module("_gi", gjs_define_private_gi_stuff);
- gjs_register_native_module("gi", gjs_define_gi_stuff);
+ gjs_register_native_module("byteArray", gjs_define_byte_array_stuff, 0);
+ gjs_register_native_module("_gi", gjs_define_private_gi_stuff, 0);
+ gjs_register_native_module("gi", gjs_define_gi_stuff, GJS_NATIVE_SUPPLIES_MODULE_OBJ);
gjs_register_static_modules();
}
diff --git a/gjs/gi.c b/gjs/gi.c
index 6ff4847..0e43122 100644
--- a/gjs/gi.c
+++ b/gjs/gi.c
@@ -33,7 +33,7 @@
JSBool
gjs_define_gi_stuff(JSContext *context,
- JSObject **module_out)
+ JSObject *module_obj)
{
- return gjs_define_repo(context, module_out, "gi");
+ return gjs_define_repo(context, module_obj, "gi");
}
diff --git a/gjs/gi.h b/gjs/gi.h
index 837d03d..c8da00f 100644
--- a/gjs/gi.h
+++ b/gjs/gi.h
@@ -31,9 +31,9 @@
G_BEGIN_DECLS
JSBool gjs_define_gi_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *module_obj);
JSBool gjs_define_private_gi_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *module_obj);
G_END_DECLS
diff --git a/gjs/importer.c b/gjs/importer.c
index f7fbd7e..c0651e2 100644
--- a/gjs/importer.c
+++ b/gjs/importer.c
@@ -31,8 +31,6 @@
#include <gjs/compat.h>
#include <gjs/runtime.h>
-#include <gio/gio.h>
-
#include <string.h>
#define MODULE_INIT_FILENAME "__init__.js"
@@ -130,6 +128,107 @@ import_directory(JSContext *context,
}
static JSBool
+finish_import(JSContext *context,
+ const char *name)
+{
+ if (JS_IsExceptionPending(context)) {
+ /* I am not sure whether this can happen, but if it does we want to trap it.
+ */
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Module '%s' reported an exception but gjs_import_native_module() returned TRUE",
+ name);
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+define_import(JSContext *context,
+ JSObject *obj,
+ JSObject *module_obj,
+ const char *name)
+{
+ if (!JS_DefineProperty(context, obj,
+ name, OBJECT_TO_JSVAL(module_obj),
+ NULL, NULL,
+ GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT)) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Failed to define '%s' in importer",
+ name);
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/* Make the property we set in define_import permament;
+ * we do this after the import succesfully completes.
+ */
+static JSBool
+seal_import(JSContext *context,
+ JSObject *obj,
+ const char *name)
+{
+ JSBool found;
+ unsigned attrs;
+
+ if (!JS_GetPropertyAttributes(context, obj, name,
+ &attrs, &found) || !found) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Failed to get attributes to seal '%s' in importer",
+ name);
+ return JS_FALSE;
+ }
+
+ attrs |= JSPROP_PERMANENT;
+
+ if (!JS_SetPropertyAttributes(context, obj, name,
+ attrs, &found) || !found) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Failed to set attributes to seal '%s' in importer",
+ name);
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/* An import failed. Delete the property pointing to the import
+ * from the parent namespace. In complicated situations this might
+ * not be sufficient to get us fully back to a sane state. If:
+ *
+ * - We import module A
+ * - module A imports module B
+ * - module B imports module A, storing a reference to the current
+ * module A module object
+ * - module A subsequently throws an exception
+ *
+ * Then module B is left imported, but the imported module B has
+ * a reference to the failed module A module object. To handle this
+ * we could could try to track the entire "import operation" and
+ * roll back *all* modifications made to the namespace objects.
+ * It's not clear that the complexity would be worth the small gain
+ * in robustness. (You can still come up with ways of defeating
+ * the attempt to clean up.)
+ */
+static void
+cancel_import(JSContext *context,
+ JSObject *obj,
+ const char *name)
+{
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Cleaning up from failed import of '%s'",
+ name);
+
+ if (!JS_DeleteProperty(context, obj, name)) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Failed to delete '%s' in importer",
+ name);
+ }
+}
+
+static JSBool
import_native_file(JSContext *context,
JSObject *obj,
const char *name)
@@ -139,67 +238,102 @@ import_native_file(JSContext *context,
gjs_debug(GJS_DEBUG_IMPORTER, "Importing '%s'", name);
- if (!gjs_import_native_module(context, name, &module_obj))
- goto out;
+ module_obj = JS_NewObject(context, NULL, NULL, NULL);
+ if (module_obj == NULL) {
+ return JS_FALSE;
+ }
+
+ /* We store the module object into the parent module before
+ * initializing the module. If the module has the
+ * GJS_NATIVE_SUPPLIES_MODULE_OBJ flag, it will just overwrite
+ * the reference we stored when it initializes.
+ */
+ if (!define_import(context, obj, module_obj, name))
+ return JS_FALSE;
if (!define_meta_properties(context, module_obj, NULL, name, obj))
goto out;
- if (JS_IsExceptionPending(context)) {
- /* I am not sure whether this can happen, but if it does we want to trap it.
- */
- gjs_debug(GJS_DEBUG_IMPORTER,
- "Module '%s' reported an exception but gjs_import_native_module() returned TRUE",
- name);
+ if (!gjs_import_native_module(context, module_obj, name))
goto out;
- }
- if (!JS_DefineProperty(context, obj,
- name, OBJECT_TO_JSVAL(module_obj),
- NULL, NULL, GJS_MODULE_PROP_FLAGS))
+ if (!finish_import(context, name))
+ goto out;
+
+ if (!seal_import(context, obj, name))
goto out;
retval = JS_TRUE;
out:
+ if (!retval)
+ cancel_import(context, obj, name);
+
return retval;
}
-static JSBool
-import_file(JSContext *context,
- const char *name,
- GFile *file,
- JSObject **module_out)
+static JSObject *
+load_module_init(JSContext *context,
+ JSObject *in_object,
+ const char *full_path)
{
- JSBool ret = JS_FALSE;
- JSObject *module_obj;
- char *script = NULL;
- char *full_path = NULL;
- gsize script_len = 0;
+ char *script;
+ gsize script_len;
jsval script_retval;
- GError *error = NULL;
+ JSObject *module_obj;
+ GError *error;
+ JSBool found;
+ jsid module_init_name;
+
+ /* First we check if js module has already been loaded */
+ module_init_name = gjs_runtime_get_const_string(JS_GetRuntime(context),
+ GJS_STRING_MODULE_INIT);
+ if (JS_HasPropertyById(context, in_object, module_init_name, &found) && found) {
+ jsval module_obj_val;
+
+ if (JS_GetPropertyById(context,
+ in_object,
+ module_init_name,
+ &module_obj_val)) {
+ return JSVAL_TO_OBJECT(module_obj_val);
+ }
+ }
module_obj = JS_NewObject(context, NULL, NULL, NULL);
- if (module_obj == NULL)
- goto out;
+ if (module_obj == NULL) {
+ return JS_FALSE;
+ }
- if (!(g_file_load_contents(file, NULL, &script, &script_len, NULL, &error))) {
- if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY) &&
- !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY) &&
- !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ /* https://bugzilla.mozilla.org/show_bug.cgi?id=599651 means we
+ * can't just pass in the global as the parent */
+ JS_SetParent(context, module_obj,
+ gjs_get_import_global (context));
+
+ /* Define module in importer for future use and to avoid module_obj
+ * object to be garbage collected during the evaluation of the script */
+ JS_DefinePropertyById(context, in_object,
+ module_init_name, OBJECT_TO_JSVAL(module_obj),
+ NULL, NULL,
+ GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT);
+
+ script_len = 0;
+ error = NULL;
+
+ if (!g_file_get_contents(full_path, &script, &script_len, &error)) {
+ if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) &&
+ !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) &&
+ !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
gjs_throw_g_error(context, error);
else
g_error_free(error);
- goto out;
+ return NULL;
}
g_assert(script != NULL);
gjs_debug(GJS_DEBUG_IMPORTER, "Importing %s", full_path);
- full_path = g_file_get_parse_name (file);
-
if (!JS_EvaluateScript(context,
module_obj,
script,
@@ -207,6 +341,7 @@ import_file(JSContext *context,
full_path,
1, /* line number */
&script_retval)) {
+ g_free(script);
/* If JSOPTION_DONT_REPORT_UNCAUGHT is set then the exception
* would be left set after the evaluate and not go to the error
@@ -214,62 +349,18 @@ import_file(JSContext *context,
*/
if (JS_IsExceptionPending(context)) {
gjs_debug(GJS_DEBUG_IMPORTER,
- "Module '%s' left an exception set",
- name);
+ "Module " MODULE_INIT_FILENAME " left an exception set");
gjs_log_and_keep_exception(context);
} else {
gjs_throw(context,
- "JS_EvaluateScript() returned FALSE but did not set exception");
+ "JS_EvaluateScript() returned FALSE but did not set exception");
}
- goto out;
+ return NULL;
}
- ret = JS_TRUE;
-
- out:
g_free(script);
- g_free(full_path);
- *module_out = module_obj;
- return ret;
-}
-static JSObject *
-load_module_init(JSContext *context,
- JSObject *in_object,
- const char *full_path)
-{
- JSObject *module_obj;
- JSBool found;
- jsid module_init_name;
- GFile *file;
-
- /* First we check if js module has already been loaded */
- module_init_name = gjs_runtime_get_const_string(JS_GetRuntime(context),
- GJS_STRING_MODULE_INIT);
- if (JS_HasPropertyById(context, in_object, module_init_name, &found) && found) {
- jsval module_obj_val;
-
- if (JS_GetPropertyById(context,
- in_object,
- module_init_name,
- &module_obj_val)) {
- return JSVAL_TO_OBJECT(module_obj_val);
- }
- }
-
- file = g_file_new_for_commandline_arg(full_path);
- if (!import_file (context, "__init__", file, &module_obj))
- goto out;
-
- if (!JS_DefinePropertyById(context, in_object,
- module_init_name, OBJECT_TO_JSVAL(module_obj),
- NULL, NULL,
- GJS_MODULE_PROP_FLAGS & ~JSPROP_PERMANENT))
- goto out;
-
- out:
- g_object_unref (file);
return module_obj;
}
@@ -314,35 +405,87 @@ load_module_elements(JSContext *context,
}
static JSBool
-import_file_on_module(JSContext *context,
- JSObject *obj,
- const char *name,
- GFile *file)
+import_file(JSContext *context,
+ JSObject *obj,
+ const char *name,
+ const char *full_path)
{
+ char *script;
+ gsize script_len;
JSObject *module_obj;
+ GError *error;
+ jsval script_retval;
JSBool retval = JS_FALSE;
- gchar *full_path;
-
- full_path = g_file_get_parse_name (file);
gjs_debug(GJS_DEBUG_IMPORTER,
"Importing '%s'", full_path);
- if (!import_file (context, name, file, &module_obj))
- goto out;
+ module_obj = JS_NewObject(context, NULL, NULL, NULL);
+ if (module_obj == NULL) {
+ return JS_FALSE;
+ }
+
+ if (!define_import(context, obj, module_obj, name))
+ return JS_FALSE;
if (!define_meta_properties(context, module_obj, full_path, name, obj))
goto out;
- if (!JS_DefineProperty(context, obj,
- name, OBJECT_TO_JSVAL(module_obj),
- NULL, NULL, GJS_MODULE_PROP_FLAGS))
+ script_len = 0;
+ error = NULL;
+
+ if (!(g_file_get_contents(full_path, &script, &script_len, &error))) {
+ if (!g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_ISDIR) &&
+ !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR) &&
+ !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ gjs_throw_g_error(context, error);
+ else
+ g_error_free(error);
+
+ goto out;
+ }
+
+ g_assert(script != NULL);
+
+ if (!JS_EvaluateScript(context,
+ module_obj,
+ script,
+ script_len,
+ full_path,
+ 1, /* line number */
+ &script_retval)) {
+ g_free(script);
+
+ /* If JSOPTION_DONT_REPORT_UNCAUGHT is set then the exception
+ * would be left set after the evaluate and not go to the error
+ * reporter function.
+ */
+ if (JS_IsExceptionPending(context)) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "Module '%s' left an exception set",
+ name);
+ gjs_log_and_keep_exception(context);
+ } else {
+ gjs_throw(context,
+ "JS_EvaluateScript() returned FALSE but did not set exception");
+ }
+
+ goto out;
+ }
+
+ g_free(script);
+
+ if (!finish_import(context, name))
+ goto out;
+
+ if (!seal_import(context, obj, name))
goto out;
retval = JS_TRUE;
out:
- g_free (full_path);
+ if (!retval)
+ cancel_import(context, obj, name);
return retval;
}
@@ -364,8 +507,6 @@ do_import(JSContext *context,
JSBool result;
GPtrArray *directories;
jsid search_path_name;
- GFile *gfile;
- gboolean exists;
search_path_name = gjs_runtime_get_const_string(JS_GetRuntime(context),
GJS_STRING_SEARCH_PATH);
@@ -465,9 +606,8 @@ do_import(JSContext *context,
g_free(full_path);
full_path = g_build_filename(dirname, name,
NULL);
- gfile = g_file_new_for_commandline_arg(full_path);
- if (g_file_query_file_type(gfile, 0, NULL) == G_FILE_TYPE_DIRECTORY) {
+ if (g_file_test(full_path, G_FILE_TEST_IS_DIR)) {
gjs_debug(GJS_DEBUG_IMPORTER,
"Adding directory '%s' to child importer '%s'",
full_path, name);
@@ -479,8 +619,6 @@ do_import(JSContext *context,
full_path = NULL;
}
- g_object_unref(gfile);
-
/* If we just added to directories, we know we don't need to
* check for a file. If we added to directories on an earlier
* iteration, we want to ignore any files later in the
@@ -495,31 +633,24 @@ do_import(JSContext *context,
g_free(full_path);
full_path = g_build_filename(dirname, filename,
NULL);
- gfile = g_file_new_for_commandline_arg(full_path);
- exists = g_file_query_exists(gfile, NULL);
- if (!exists) {
- gjs_debug(GJS_DEBUG_IMPORTER,
- "JS import '%s' not found in %s",
- name, dirname);
-
- g_object_unref(gfile);
- continue;
- }
+ if (g_file_test(full_path, G_FILE_TEST_EXISTS)) {
+ if (import_file(context, obj, name, full_path)) {
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "successfully imported module '%s'", name);
+ result = JS_TRUE;
+ }
- if (import_file_on_module (context, obj, name, gfile)) {
- gjs_debug(GJS_DEBUG_IMPORTER,
- "successfully imported module '%s'", name);
- result = JS_TRUE;
+ /* Don't keep searching path if we fail to load the file for
+ * reasons other than it doesn't exist... i.e. broken files
+ * block searching for nonbroken ones
+ */
+ goto out;
}
- g_object_unref(gfile);
-
- /* Don't keep searching path if we fail to load the file for
- * reasons other than it doesn't exist... i.e. broken files
- * block searching for nonbroken ones
- */
- goto out;
+ gjs_debug(GJS_DEBUG_IMPORTER,
+ "JS import '%s' not found in %s",
+ name, dirname);
}
if (directories != NULL) {
diff --git a/gjs/native.c b/gjs/native.c
index 5041dbe..05d5936 100644
--- a/gjs/native.c
+++ b/gjs/native.c
@@ -32,14 +32,30 @@
#include "jsapi-util.h"
#include "runtime.h"
+typedef struct {
+ GjsDefineModuleFunc func;
+ GjsNativeFlags flags;
+} GjsNativeModule;
+
static GHashTable *modules = NULL;
+static void
+native_module_free(void *data)
+{
+ g_slice_free(GjsNativeModule, data);
+}
+
void
-gjs_register_native_module (const char *module_id,
- GjsDefineModuleFunc func)
+gjs_register_native_module (const char *module_id,
+ GjsDefineModuleFunc func,
+ GjsNativeFlags flags)
{
- if (modules == NULL)
- modules = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+ GjsNativeModule *module;
+
+ if (modules == NULL) {
+ modules = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, native_module_free);
+ }
if (g_hash_table_lookup(modules, module_id) != NULL) {
g_warning("A second native module tried to register the same id '%s'",
@@ -47,13 +63,34 @@ gjs_register_native_module (const char *module_id,
return;
}
- g_hash_table_replace(modules, g_strdup(module_id), func);
+ module = g_slice_new(GjsNativeModule);
+ module->func = func;
+ module->flags = flags;
+
+ g_hash_table_replace(modules,
+ g_strdup(module_id),
+ module);
gjs_debug(GJS_DEBUG_NATIVE,
"Registered native JS module '%s'",
module_id);
}
+static JSObject*
+module_get_parent(JSContext *context,
+ JSObject *module_obj)
+{
+ jsval value;
+
+ if (gjs_object_get_property_const(context, module_obj, GJS_STRING_PARENT_MODULE, &value) &&
+ !JSVAL_IS_NULL(value) &&
+ JSVAL_IS_OBJECT(value)) {
+ return JSVAL_TO_OBJECT(value);
+ } else {
+ return NULL;
+ }
+}
+
/**
* gjs_is_registered_native_module:
* @context:
@@ -83,27 +120,39 @@ gjs_is_registered_native_module(JSContext *context,
* Return a native module that's been preloaded.
*/
JSBool
-gjs_import_native_module(JSContext *context,
- const char *name,
- JSObject **module_out)
+gjs_import_native_module(JSContext *context,
+ JSObject *module_obj,
+ const char *name)
{
- GjsDefineModuleFunc func;
+ GjsNativeModule *native_module;
+ JSObject *parent;
gjs_debug(GJS_DEBUG_NATIVE,
"Defining native module '%s'",
name);
if (modules != NULL)
- func = g_hash_table_lookup(modules, name);
+ native_module = g_hash_table_lookup(modules, name);
else
- func = NULL;
+ native_module = NULL;
- if (!func) {
+ if (!native_module) {
gjs_throw(context,
"No native module '%s' has registered itself",
name);
return JS_FALSE;
}
- return func (context, module_out);
+ if (native_module->flags & GJS_NATIVE_SUPPLIES_MODULE_OBJ) {
+
+ /* In this case we just throw away "module_obj" eventually,
+ * since the native module defines itself in the parent of
+ * module_obj directly.
+ */
+ parent = module_get_parent(context, module_obj);
+ return (* native_module->func) (context, parent);
+ } else {
+ return (* native_module->func) (context, module_obj);
+ }
}
+
diff --git a/gjs/native.h b/gjs/native.h
index d2f4b4a..902f7bc 100644
--- a/gjs/native.h
+++ b/gjs/native.h
@@ -33,12 +33,30 @@
G_BEGIN_DECLS
-typedef JSBool (* GjsDefineModuleFunc) (JSContext *context,
- JSObject **module_out);
+typedef enum {
+ /* This means that the GjsDefineModuleFunc defines the module
+ * name in the parent module, as opposed to the normal process
+ * where the GjsDefineModuleFunc defines module contents. When
+ * importing imports.foo.bar, this flag means the native module is
+ * given foo and defines bar in it, while normally the native
+ * module is given bar and defines stuff in that.
+ *
+ * The purpose of this is to allow a module with lazy properties
+ * by allowing module objects to be custom classes. It's used for
+ * the gobject-introspection module for example.
+ */
+ GJS_NATIVE_SUPPLIES_MODULE_OBJ = 1 << 0
+
+} GjsNativeFlags;
+
+
+typedef JSBool (* GjsDefineModuleFunc) (JSContext *context,
+ JSObject *module_obj);
/* called on context init */
void gjs_register_native_module (const char *module_id,
- GjsDefineModuleFunc func);
+ GjsDefineModuleFunc func,
+ GjsNativeFlags flags);
/* called by importer.c to to check for already loaded modules */
gboolean gjs_is_registered_native_module(JSContext *context,
@@ -46,9 +64,9 @@ gboolean gjs_is_registered_native_module(JSContext *context,
const char *name);
/* called by importer.c to load a statically linked native module */
-JSBool gjs_import_native_module (JSContext *context,
- const char *name,
- JSObject **module_out);
+JSBool gjs_import_native_module (JSContext *context,
+ JSObject *module_obj,
+ const char *name);
G_END_DECLS
diff --git a/modules/cairo-module.h b/modules/cairo-module.h
index 9b5e2d5..beb6a56 100644
--- a/modules/cairo-module.h
+++ b/modules/cairo-module.h
@@ -24,6 +24,6 @@
#define __CAIRO_MODULE_H__
JSBool gjs_js_define_cairo_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *module);
#endif /* __CAIRO_MODULE_H__ */
diff --git a/modules/cairo.c b/modules/cairo.c
index 0565169..d72e39c 100644
--- a/modules/cairo.c
+++ b/modules/cairo.c
@@ -45,14 +45,11 @@ gjs_cairo_check_status(JSContext *context,
JSBool
gjs_js_define_cairo_stuff(JSContext *context,
- JSObject **module_out)
+ JSObject *module)
{
jsval obj;
- JSObject *module;
JSObject *surface_proto, *pattern_proto, *gradient_proto;
- module = JS_NewObject (context, NULL, NULL, NULL);
-
obj = gjs_cairo_context_create_proto(context, module,
"Context", NULL);
if (JSVAL_IS_NULL(obj))
@@ -125,7 +122,5 @@ gjs_js_define_cairo_stuff(JSContext *context,
if (JSVAL_IS_NULL(obj))
return JS_FALSE;
- *module_out = module;
-
return JS_TRUE;
}
diff --git a/modules/console.c b/modules/console.c
index 1424b68..a1805b3 100644
--- a/modules/console.c
+++ b/modules/console.c
@@ -226,19 +226,14 @@ gjs_console_interact(JSContext *context,
}
JSBool
-gjs_define_console_stuff(JSContext *context,
- JSObject **module_out)
+gjs_define_console_stuff(JSContext *context,
+ JSObject *module_obj)
{
- JSObject *module;
-
- module = JS_NewObject (context, NULL, NULL, NULL);
-
- if (!JS_DefineFunction(context, module,
+ if (!JS_DefineFunction(context, module_obj,
"interact",
(JSNative) gjs_console_interact,
1, GJS_MODULE_PROP_FLAGS))
return JS_FALSE;
- *module_out = module;
return JS_TRUE;
}
diff --git a/modules/console.h b/modules/console.h
index bb1e2da..39fae94 100644
--- a/modules/console.h
+++ b/modules/console.h
@@ -31,7 +31,7 @@
G_BEGIN_DECLS
JSBool gjs_define_console_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *in_object);
JSBool gjs_console_interact (JSContext *context,
unsigned argc,
jsval *vp);
diff --git a/modules/modules.c b/modules/modules.c
index aae3569..479fb4c 100644
--- a/modules/modules.c
+++ b/modules/modules.c
@@ -37,8 +37,8 @@ void
gjs_register_static_modules (void)
{
#ifdef ENABLE_CAIRO
- gjs_register_native_module("cairoNative", gjs_js_define_cairo_stuff);
+ gjs_register_native_module("cairoNative", gjs_js_define_cairo_stuff, 0);
#endif
- gjs_register_native_module("system", gjs_js_define_system_stuff);
- gjs_register_native_module("console", gjs_define_console_stuff);
+ gjs_register_native_module("system", gjs_js_define_system_stuff, 0);
+ gjs_register_native_module("console", gjs_define_console_stuff, 0);
}
diff --git a/modules/system.c b/modules/system.c
index 41523c5..6fc1e21 100644
--- a/modules/system.c
+++ b/modules/system.c
@@ -129,16 +129,13 @@ static JSFunctionSpec module_funcs[] = {
};
JSBool
-gjs_js_define_system_stuff(JSContext *context,
- JSObject **module_out)
+gjs_js_define_system_stuff(JSContext *context,
+ JSObject *module)
{
GjsContext *gjs_context;
char *program_name;
jsval value;
JSBool retval;
- JSObject *module;
-
- module = JS_NewObject (context, NULL, NULL, NULL);
if (!JS_DefineFunctions(context, module, &module_funcs[0]))
return JS_FALSE;
@@ -176,7 +173,6 @@ gjs_js_define_system_stuff(JSContext *context,
out:
g_free(program_name);
- *module_out = module;
return retval;
}
diff --git a/modules/system.h b/modules/system.h
index 608de0e..ca093a6 100644
--- a/modules/system.h
+++ b/modules/system.h
@@ -32,7 +32,7 @@
G_BEGIN_DECLS
JSBool gjs_js_define_system_stuff (JSContext *context,
- JSObject **module_out);
+ JSObject *in_object);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]