[gjs/wip/require: 1/7] bootstrap: Add the skeleton of a new imports system
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/require: 1/7] bootstrap: Add the skeleton of a new imports system
- Date: Wed, 17 Jun 2015 23:32:13 +0000 (UTC)
commit 6aa6e1fe89a9a21d57edcfb639ecbee378021e5b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Thu Jan 2 15:59:16 2014 -0500
bootstrap: Add the skeleton of a new imports system
Get the base features implemented, which lets us import a native
module. We also add a new private module, '_importer', which will
contain all the native functionality we need for a new imports
system.
Makefile-modules.am | 7 ++-
gjs/bootstrap.cpp | 42 ++++++++++++
gjs/console.cpp | 2 +-
gjs/context.cpp | 6 ++
gjs/context.h | 2 +
gjs/importer.cpp | 2 +-
gjs/importer.h | 2 +
libgjs-private/gjs-util.h | 4 +-
modules/bootstrap.js | 57 ++++++++++++++++-
modules/importer.cpp | 153 +++++++++++++++++++++++++++++++++++++++++++++
modules/importer.h | 38 +++++++++++
modules/modules.cpp | 2 +
12 files changed, 308 insertions(+), 9 deletions(-)
---
diff --git a/Makefile-modules.am b/Makefile-modules.am
index 4b6e356..4151c5d 100644
--- a/Makefile-modules.am
+++ b/Makefile-modules.am
@@ -1,6 +1,5 @@
-NATIVE_MODULES = libconsole.la libsystem.la libmodules_resources.la
-
+NATIVE_MODULES = libconsole.la libsystem.la libmodules_resources.la libimporter.la
if ENABLE_CAIRO
NATIVE_MODULES += libcairoNative.la
endif
@@ -56,3 +55,7 @@ libsystem_la_SOURCES = modules/system.h modules/system.cpp
libconsole_la_CPPFLAGS = $(JS_NATIVE_MODULE_CFLAGS)
libconsole_la_LIBADD = $(JS_NATIVE_MODULE_LIBADD) $(READLINE_LIBS)
libconsole_la_SOURCES = modules/console.h modules/console.cpp
+
+libimporter_la_CPPFLAGS = $(JS_NATIVE_MODULE_CFLAGS)
+libimporter_la_LIBADD = $(JS_NATIVE_MODULE_LIBADD)
+libimporter_la_SOURCES = modules/importer.h modules/importer.cpp
diff --git a/gjs/bootstrap.cpp b/gjs/bootstrap.cpp
index b049ec4..406c26f 100644
--- a/gjs/bootstrap.cpp
+++ b/gjs/bootstrap.cpp
@@ -26,9 +26,48 @@
#include <gjs/gjs.h>
#include "bootstrap.h"
+#include "native.h"
#include <gio/gio.h>
+/* The bootstrap process is the thing that sets up the import system.
+ * As such, we give it a hook to import any native modules it may need.
+ *
+ * The rest of the functionality that the bootstrap code needs should be
+ * in independent native modules which can be imported by this API,
+ * rather than in the bootstrap environment.
+ */
+
+static JSBool
+import_native_module(JSContext *context,
+ unsigned argc,
+ jsval *vp)
+{
+ JSBool ret = JS_FALSE;
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ char *module_name = NULL;
+ JSObject *module_obj;
+
+ if (!gjs_parse_call_args(context, "importNativeModule", "s", args,
+ "moduleName", &module_name))
+ goto out;
+
+ if (!gjs_import_native_module(context, module_name, &module_obj))
+ goto out;
+
+ ret = JS_TRUE;
+ args.rval().setObjectOrNull(module_obj);
+
+ out:
+ g_free(module_name);
+ return ret;
+}
+
+static JSFunctionSpec environment_funcs[] = {
+ { "importNativeModule", JSOP_WRAPPER (import_native_module), 1, GJS_MODULE_PROP_FLAGS },
+ { NULL },
+};
+
static gboolean
define_bootstrap_environment(JSContext *context,
JSObject **environment_out)
@@ -38,6 +77,9 @@ define_bootstrap_environment(JSContext *context,
if (!environment)
return FALSE;
+ if (!JS_DefineFunctions(context, environment, &environment_funcs[0]))
+ return FALSE;
+
*environment_out = environment;
return TRUE;
}
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 50adca8..2320e55 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -96,7 +96,7 @@ main(int argc, char **argv)
filename = "<command line>";
program_name = argv[0];
} else if (argc <= 1) {
- script = g_strdup("const Console = imports.console; Console.interact();");
+ script = g_strdup("const Console = require('console'); Console.interact();");
len = strlen(script);
filename = "<stdin>";
program_name = argv[0];
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 6564440..ed11882 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -792,3 +792,9 @@ gjs_get_import_global(JSContext *context)
GjsContext *gjs_context = (GjsContext *) JS_GetContextPrivate(context);
return gjs_context->global;
}
+
+const char **
+gjs_context_get_search_path(GjsContext *context)
+{
+ return (const char **) context->search_path;
+}
diff --git a/gjs/context.h b/gjs/context.h
index ccd8bc6..acd07d1 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -77,6 +77,8 @@ void gjs_context_gc (GjsContext *context);
void gjs_dumpstack (void);
+const char ** gjs_context_get_search_path (GjsContext *context);
+
G_END_DECLS
#endif /* __GJS_CONTEXT_H__ */
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 3b163e3..e421dda 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -997,7 +997,7 @@ importer_new(JSContext *context,
return importer;
}
-static G_CONST_RETURN char * G_CONST_RETURN *
+G_CONST_RETURN char * G_CONST_RETURN *
gjs_get_search_path(void)
{
char **search_path;
diff --git a/gjs/importer.h b/gjs/importer.h
index afd4ab1..8f11fb8 100644
--- a/gjs/importer.h
+++ b/gjs/importer.h
@@ -29,6 +29,7 @@
#endif
#include <glib.h>
+#include <gio/gio.h>
#include "gjs/jsapi-util.h"
G_BEGIN_DECLS
@@ -44,6 +45,7 @@ JSObject* gjs_define_importer (JSContext *context,
const char **initial_search_path,
gboolean add_standard_search_path);
+G_CONST_RETURN char * G_CONST_RETURN * gjs_get_search_path (void);
G_END_DECLS
diff --git a/libgjs-private/gjs-util.h b/libgjs-private/gjs-util.h
index 18ca87e..aef6594 100644
--- a/libgjs-private/gjs-util.h
+++ b/libgjs-private/gjs-util.h
@@ -28,10 +28,10 @@
G_BEGIN_DECLS
-/* For imports.format */
+/* For 'format' */
char * gjs_format_int_alternative_output (int n);
-/* For imports.gettext */
+/* For 'gettext' */
void gjs_textdomain (const char *domain);
void gjs_bindtextdomain (const char *domain,
const char *location);
diff --git a/modules/bootstrap.js b/modules/bootstrap.js
index 45ab533..5f62330 100644
--- a/modules/bootstrap.js
+++ b/modules/bootstrap.js
@@ -1,6 +1,57 @@
-(function(exports) {
+(function(exports, importNativeModule) {
"use strict";
- // Do early initialization here.
+ const Importer = importNativeModule('_importer');
-})(window);
+ let _exports = {};
+
+ // This is where "unknown namespace" classes live, where we don't
+ // have info for them. One common example is GLocalFile.
+ _exports['gi/__gjsPrivateNS'] = {};
+
+ function loadNativeModule(moduleID) {
+ _exports[moduleID] = importNativeModule(moduleID);
+ }
+
+ function runOverridesForGIModule(module, moduleID) {
+ let overridesModuleName = ('overrides/' + moduleID);
+ loadJSModule(overridesModuleName);
+ let overridesModule = _exports[overridesModuleName];
+ if (!overridesModule)
+ return;
+
+ let initFunc = overridesModule._init;
+ if (!initFunc)
+ return;
+
+ initFunc.call(module);
+ }
+
+ function importGIModuleWithOverrides(moduleID, moduleVersion) {
+ let exportedID = 'gi/' + moduleID;
+ if (_exports[exportedID])
+ return _exports[exportedID];
+
+ let module = Importer.importGIModule(moduleID, moduleVersion);
+ _exports[exportedID] = module;
+ _exports[exportedID + '/' + moduleVersion] = module;
+ runOverridesForGIModule(module, moduleID);
+ return module;
+ }
+
+ function loadGIModule(moduleID) {
+ if (!moduleID.startsWith('gi/'))
+ return;
+
+ let giModuleID = moduleID.slice(3);
+
+ let moduleVersion;
+ if (giModuleID.indexOf('/') >= 0)
+ [giModuleID, moduleVersion] = giModuleID.split('/', 2);
+ else
+ moduleVersion = null;
+
+ importGIModuleWithOverrides(giModuleID, moduleVersion);
+ }
+
+})(window, importNativeModule);
diff --git a/modules/importer.cpp b/modules/importer.cpp
new file mode 100644
index 0000000..10b3ed8
--- /dev/null
+++ b/modules/importer.cpp
@@ -0,0 +1,153 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <config.h>
+
+#include "importer.h"
+#include <gjs/gjs-module.h>
+#include <gjs/byteArray.h>
+#include "gi/ns.h"
+
+static JSBool
+import_gi_module(JSContext *context,
+ unsigned argc,
+ jsval *vp)
+{
+ JSBool ret = JS_FALSE;
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ jsval retval = JSVAL_VOID;
+ char *module_name = NULL;
+ char *module_version = NULL;
+ JSObject *module_obj;
+
+ if (!gjs_parse_call_args(context, "importGIModule", "s?s", args,
+ "moduleName", &module_name,
+ "moduleVersion", &module_version))
+ goto out;
+
+ if (!gjs_import_gi_module(context, module_name, module_version, &module_obj))
+ goto out;
+
+ ret = JS_TRUE;
+ args.rval().setObject(*module_obj);
+
+ out:
+ g_free(module_name);
+ g_free(module_version);
+ return ret;
+}
+
+static JSBool
+eval_with_scope(JSContext *context,
+ unsigned argc,
+ jsval *vp)
+{
+ JSBool ret = JS_FALSE;
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ JSObject *scope;
+ JSObject *script_obj;
+ guint8 *script;
+ gsize script_len;
+ char *filename = NULL;
+ jsval retval;
+
+ if (!gjs_parse_call_args(context, "evalWithScope", "oos", args,
+ "scope", &scope,
+ "script", &script_obj,
+ "filename", &filename))
+ goto out;
+
+ gjs_byte_array_peek_data (context, script_obj, &script, &script_len);
+
+ if (!gjs_eval_with_scope(context, scope, (const char *) script, script_len, filename, &retval))
+ goto out;
+
+ ret = JS_TRUE;
+ args.rval().set(retval);
+
+ out:
+ g_free(filename);
+ return ret;
+}
+
+static JSBool
+get_builtin_search_path(JSContext *context,
+ unsigned argc,
+ jsval *vp)
+{
+ GjsContext *gjs_context = GJS_CONTEXT(JS_GetContextPrivate(context));
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ const char **context_search_path;
+ int context_search_path_length;
+ const char **global_search_path;
+ int global_search_path_length;
+ GArray *elems;
+ JSObject *search_path_obj;
+ int i;
+
+ context_search_path = gjs_context_get_search_path(gjs_context);
+ context_search_path_length = context_search_path ? g_strv_length((char **) context_search_path) : 0;
+ global_search_path = (const char **) gjs_get_search_path();
+ global_search_path_length = global_search_path ? g_strv_length((char **) global_search_path) : 0;
+
+ elems = g_array_sized_new(FALSE, FALSE, sizeof(jsval),
+ context_search_path_length + global_search_path_length);
+
+ for (i = 0; i < context_search_path_length; i++) {
+ jsval element = STRING_TO_JSVAL(JS_NewStringCopyZ(context, context_search_path[i]));
+ g_array_append_val(elems, element);
+ }
+
+ for (i = 0; i < global_search_path_length; i++) {
+ jsval element = STRING_TO_JSVAL(JS_NewStringCopyZ(context, global_search_path[i]));
+ g_array_append_val(elems, element);
+ }
+
+ search_path_obj = JS_NewArrayObject(context, elems->len, (jsval *)elems->data);
+ g_array_free(elems, TRUE);
+
+ args.rval().setObject(*search_path_obj);
+ return JS_TRUE;
+}
+
+static JSFunctionSpec module_funcs[] = {
+ { "importGIModule", JSOP_WRAPPER (import_gi_module), 2, GJS_MODULE_PROP_FLAGS },
+ { "evalWithScope", JSOP_WRAPPER (eval_with_scope), 3, GJS_MODULE_PROP_FLAGS },
+ { "getBuiltinSearchPath", JSOP_WRAPPER (get_builtin_search_path), 0, GJS_MODULE_PROP_FLAGS },
+ { NULL },
+};
+
+JSBool
+gjs_js_define_importer_stuff(JSContext *context,
+ JSObject **module_out)
+{
+ JSObject *module;
+
+ module = JS_NewObject(context, NULL, NULL, NULL);
+
+ if (!JS_DefineFunctions(context, module, &module_funcs[0]))
+ return JS_FALSE;
+
+ *module_out = module;
+ return JS_TRUE;
+}
diff --git a/modules/importer.h b/modules/importer.h
new file mode 100644
index 0000000..5fa25b0
--- /dev/null
+++ b/modules/importer.h
@@ -0,0 +1,38 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright 2013 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __GJS_MODULE_IMPORTER_H__
+#define __GJS_MODULE_IMPORTER_H__
+
+#include <config.h>
+#include <glib.h>
+#include "gjs/jsapi-util.h"
+
+G_BEGIN_DECLS
+
+JSBool gjs_js_define_importer_stuff (JSContext *context,
+ JSObject **module_out);
+
+G_END_DECLS
+
+#endif /* __GJS_MODULE_IMPORTER_H__ */
diff --git a/modules/modules.cpp b/modules/modules.cpp
index aae3569..0ccc432 100644
--- a/modules/modules.cpp
+++ b/modules/modules.cpp
@@ -32,6 +32,7 @@
#include "system.h"
#include "console.h"
+#include "importer.h"
void
gjs_register_static_modules (void)
@@ -40,5 +41,6 @@ gjs_register_static_modules (void)
gjs_register_native_module("cairoNative", gjs_js_define_cairo_stuff);
#endif
gjs_register_native_module("system", gjs_js_define_system_stuff);
+ gjs_register_native_module("_importer", gjs_js_define_importer_stuff);
gjs_register_native_module("console", gjs_define_console_stuff);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]