[gjs/wip/require: 6/7] bootstrap: Add a JS implementation of the imports system
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/require: 6/7] bootstrap: Add a JS implementation of the imports system
- Date: Wed, 17 Jun 2015 23:32:39 +0000 (UTC)
commit 2a6735ece3324325f96700560d317b72f35f7f88
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Jan 15 11:17:38 2014 -0500
bootstrap: Add a JS implementation of the imports system
Re-implement the old importer with a Proxy in bootstrap.js, reducing the
footprint and making the code significantly easier to understand.
Makefile.am | 9 +-
gi/boxed.cpp | 2 +-
gi/enumeration.cpp | 2 +-
gi/fundamental.cpp | 14 +-
gi/gerror.cpp | 2 +-
gi/interface.cpp | 2 +-
gi/ns.cpp | 2 +-
gi/object.cpp | 2 +-
gi/param.cpp | 2 +-
gi/repo.cpp | 796 -----------------------------------
gi/union.cpp | 3 +-
gi/util.cpp | 438 +++++++++++++++++++
gi/{repo.h => util.h} | 3 -
gjs/context.cpp | 22 +-
gjs/gi.cpp | 39 --
gjs/gi.h | 2 -
gjs/gjs-module.h | 1 -
gjs/importer.cpp | 1118 -------------------------------------------------
gjs/importer.h | 50 ---
gjs/jsapi-util.h | 2 -
modules/bootstrap.js | 134 ++++++-
21 files changed, 578 insertions(+), 2067 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 835bb86..09eeed9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,7 +35,6 @@ nobase_gjs_module_include_HEADERS = \
gjs/compat.h \
gjs/coverage.h \
gjs/byteArray.h \
- gjs/importer.h \
gjs/jsapi-util.h \
gjs/runtime.h \
gjs/type-module.h \
@@ -46,7 +45,7 @@ nobase_gjs_module_include_HEADERS = \
gi/foreign.h \
gi/fundamental.h \
gi/param.h \
- gi/repo.h \
+ gi/util.h \
gi/union.h \
gi/value.h \
gi/arg.h \
@@ -112,10 +111,8 @@ libgjs_la_SOURCES = \
gjs/byteArray.cpp \
gjs/context.cpp \
gjs/bootstrap.cpp \
- gjs/importer.cpp \
gjs/gi.h \
- gjs/gi.cpp \
- gjs/coverage.cpp \
+ gjs/coverage.cpp \
gjs/jsapi-private.cpp \
gjs/jsapi-util.cpp \
gjs/jsapi-dynamic-class.cpp \
@@ -151,7 +148,7 @@ libgjs_la_SOURCES += \
gi/fundamental.cpp \
gi/param.cpp \
gi/proxyutils.cpp \
- gi/repo.cpp \
+ gi/util.cpp \
gi/union.cpp \
gi/value.cpp \
gi/interface.cpp \
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 7584525..658f578 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -30,7 +30,7 @@
#include "object.h"
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
-#include "repo.h"
+#include "util.h"
#include "proxyutils.h"
#include "function.h"
#include "gtype.h"
diff --git a/gi/enumeration.cpp b/gi/enumeration.cpp
index 598a11a..8593bea 100644
--- a/gi/enumeration.cpp
+++ b/gi/enumeration.cpp
@@ -27,7 +27,7 @@
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
-#include "repo.h"
+#include "util.h"
#include "gtype.h"
#include "function.h"
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 0e1908f..f1b0d23 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -24,25 +24,19 @@
#include <config.h>
-#include <string.h>
-
-#include <gjs/gi.h>
-
#include "fundamental.h"
+
#include "arg.h"
#include "object.h"
#include "boxed.h"
-#include "repo.h"
#include "function.h"
#include "gtype.h"
#include "proxyutils.h"
+#include "util.h"
-#include <gjs/gjs.h>
-
+#include <gjs/gjs-module.h>
+#include <gjs/compat.h>
#include <util/log.h>
-
-#include <jsapi.h>
-
#include <girepository.h>
/*
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index f183ca3..af84bbe 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -29,7 +29,7 @@
#include <gjs/compat.h>
#include "boxed.h"
#include "enumeration.h"
-#include "repo.h"
+#include "util.h"
#include "gerror.h"
#include <util/log.h>
diff --git a/gi/interface.cpp b/gi/interface.cpp
index 96c7230..767184d 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -27,7 +27,7 @@
#include "function.h"
#include "gtype.h"
#include "interface.h"
-#include "repo.h"
+#include "util.h"
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
diff --git a/gi/ns.cpp b/gi/ns.cpp
index ef73826..229a9f8 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -24,7 +24,7 @@
#include <config.h>
#include "ns.h"
-#include "repo.h"
+#include "util.h"
#include "param.h"
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
diff --git a/gi/object.cpp b/gi/object.cpp
index 376dd85..44b10bf 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -29,7 +29,7 @@
#include "object.h"
#include "gtype.h"
#include "arg.h"
-#include "repo.h"
+#include "util.h"
#include "gtype.h"
#include "function.h"
#include "proxyutils.h"
diff --git a/gi/param.cpp b/gi/param.cpp
index 27918b2..596268e 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -28,7 +28,7 @@
#include "param.h"
#include "arg.h"
#include "object.h"
-#include "repo.h"
+#include "util.h"
#include "gtype.h"
#include "function.h"
#include <gjs/gjs-module.h>
diff --git a/gi/union.cpp b/gi/union.cpp
index 23ca458..5533af5 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -25,7 +25,6 @@
#include <string.h>
-/* include first for logging related #define used in repo.h */
#include <util/log.h>
#include "union.h"
@@ -33,7 +32,7 @@
#include "object.h"
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
-#include "repo.h"
+#include "util.h"
#include "proxyutils.h"
#include "function.h"
#include "gtype.h"
diff --git a/gi/util.cpp b/gi/util.cpp
new file mode 100644
index 0000000..055d6a6
--- /dev/null
+++ b/gi/util.cpp
@@ -0,0 +1,438 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2008 litl, LLC
+ *
+ * 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 "util.h"
+#include "ns.h"
+#include "function.h"
+#include "object.h"
+#include "param.h"
+#include "boxed.h"
+#include "union.h"
+#include "enumeration.h"
+#include "arg.h"
+#include "foreign.h"
+#include "fundamental.h"
+#include "interface.h"
+#include "gerror.h"
+
+#include <gjs/compat.h>
+#include <gjs/jsapi-private.h>
+#include <gjs/runtime.h>
+
+#include <util/log.h>
+#include <util/misc.h>
+
+#include <girepository.h>
+#include <string.h>
+
+static JSBool
+gjs_define_constant(JSContext *context,
+ JSObject *in_object,
+ GIConstantInfo *info)
+{
+ jsval value;
+ GArgument garg = { 0, };
+ GITypeInfo *type_info;
+ const char *name;
+ JSBool ret = JS_FALSE;
+
+ type_info = g_constant_info_get_type(info);
+ g_constant_info_get_value(info, &garg);
+
+ if (!gjs_value_from_g_argument(context, &value, type_info, &garg, TRUE))
+ goto out;
+
+ name = g_base_info_get_name((GIBaseInfo*) info);
+
+ if (JS_DefineProperty(context, in_object,
+ name, value,
+ NULL, NULL,
+ GJS_MODULE_PROP_FLAGS))
+ ret = JS_TRUE;
+
+ out:
+ g_constant_info_free_value (info, &garg);
+ g_base_info_unref((GIBaseInfo*) type_info);
+ return ret;
+}
+
+#if GJS_VERBOSE_ENABLE_GI_USAGE
+void
+_gjs_log_info_usage(GIBaseInfo *info)
+{
+#define DIRECTION_STRING(d) ( ((d) == GI_DIRECTION_IN) ? "IN" : ((d) == GI_DIRECTION_OUT) ? "OUT" : "INOUT" )
+#define TRANSFER_STRING(t) ( ((t) == GI_TRANSFER_NOTHING) ? "NOTHING" : ((t) == GI_TRANSFER_CONTAINER) ?
"CONTAINER" : "EVERYTHING" )
+
+ {
+ char *details;
+ GIInfoType info_type;
+ GIBaseInfo *container;
+
+ info_type = g_base_info_get_type(info);
+
+ if (info_type == GI_INFO_TYPE_FUNCTION) {
+ GString *args;
+ int n_args;
+ int i;
+ GITransfer retval_transfer;
+
+ args = g_string_new("{ ");
+
+ n_args = g_callable_info_get_n_args((GICallableInfo*) info);
+ for (i = 0; i < n_args; ++i) {
+ GIArgInfo *arg;
+ GIDirection direction;
+ GITransfer transfer;
+
+ arg = g_callable_info_get_arg((GICallableInfo*)info, i);
+ direction = g_arg_info_get_direction(arg);
+ transfer = g_arg_info_get_ownership_transfer(arg);
+
+ g_string_append_printf(args,
+ "{ GI_DIRECTION_%s, GI_TRANSFER_%s }, ",
+ DIRECTION_STRING(direction),
+ TRANSFER_STRING(transfer));
+
+ g_base_info_unref((GIBaseInfo*) arg);
+ }
+ if (args->len > 2)
+ g_string_truncate(args, args->len - 2); /* chop comma */
+
+ g_string_append(args, " }");
+
+ retval_transfer = g_callable_info_get_caller_owns((GICallableInfo*) info);
+
+ details = g_strdup_printf(".details = { .func = { .retval_transfer = GI_TRANSFER_%s, .n_args =
%d, .args = %s } }",
+ TRANSFER_STRING(retval_transfer), n_args, args->str);
+ g_string_free(args, TRUE);
+ } else {
+ details = g_strdup_printf(".details = { .nothing = {} }");
+ }
+
+ container = g_base_info_get_container(info);
+
+ gjs_debug_gi_usage("{ GI_INFO_TYPE_%s, \"%s\", \"%s\", \"%s\", %s },",
+ gjs_info_type_name(info_type),
+ g_base_info_get_namespace(info),
+ container ? g_base_info_get_name(container) : "",
+ g_base_info_get_name(info),
+ details);
+ g_free(details);
+ }
+}
+#endif /* GJS_VERBOSE_ENABLE_GI_USAGE */
+
+JSBool
+gjs_define_info(JSContext *context,
+ JSObject *in_object,
+ GIBaseInfo *info,
+ gboolean *defined)
+{
+#if GJS_VERBOSE_ENABLE_GI_USAGE
+ _gjs_log_info_usage(info);
+#endif
+
+ *defined = TRUE;
+
+ switch (g_base_info_get_type(info)) {
+ case GI_INFO_TYPE_FUNCTION:
+ {
+ JSObject *f;
+ f = gjs_define_function(context, in_object, 0, (GICallableInfo*) info);
+ if (f == NULL)
+ return JS_FALSE;
+ }
+ break;
+ case GI_INFO_TYPE_OBJECT:
+ {
+ GType gtype;
+ gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)info);
+
+ if (g_type_is_a (gtype, G_TYPE_PARAM)) {
+ gjs_define_param_class(context, in_object);
+ } else if (g_type_is_a (gtype, G_TYPE_OBJECT)) {
+ gjs_define_object_class(context, in_object, (GIObjectInfo*) info, gtype, NULL);
+ } else if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
+ if (!gjs_define_fundamental_class(context, in_object, (GIObjectInfo*)info, NULL, NULL)) {
+ gjs_throw (context,
+ "Unsupported fundamental class creation for type %s",
+ g_type_name(gtype));
+ return JS_FALSE;
+ }
+ } else {
+ gjs_throw (context,
+ "Unsupported type %s, deriving from fundamental %s",
+ g_type_name(gtype), g_type_name(g_type_fundamental(gtype)));
+ return JS_FALSE;
+ }
+ }
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ /* We don't want GType structures in the namespace,
+ we expose their fields as vfuncs and their methods
+ as static methods
+ */
+ if (g_struct_info_is_gtype_struct((GIStructInfo*) info)) {
+ *defined = FALSE;
+ break;
+ }
+ /* Fall through */
+
+ case GI_INFO_TYPE_BOXED:
+ gjs_define_boxed_class(context, in_object, (GIBoxedInfo*) info);
+ break;
+ case GI_INFO_TYPE_UNION:
+ if (!gjs_define_union_class(context, in_object, (GIUnionInfo*) info))
+ return JS_FALSE;
+ break;
+ case GI_INFO_TYPE_ENUM:
+ if (g_enum_info_get_error_domain((GIEnumInfo*) info)) {
+ /* define as GError subclass */
+ gjs_define_error_class(context, in_object, (GIEnumInfo*) info);
+ break;
+ }
+ /* fall through */
+
+ case GI_INFO_TYPE_FLAGS:
+ if (!gjs_define_enumeration(context, in_object, (GIEnumInfo*) info))
+ return JS_FALSE;
+ break;
+ case GI_INFO_TYPE_CONSTANT:
+ if (!gjs_define_constant(context, in_object, (GIConstantInfo*) info))
+ return JS_FALSE;
+ break;
+ case GI_INFO_TYPE_INTERFACE:
+ gjs_define_interface_class(context, in_object, (GIInterfaceInfo*) info);
+ break;
+ default:
+ gjs_throw(context, "API of type %s not implemented, cannot define %s.%s",
+ gjs_info_type_name(g_base_info_get_type(info)),
+ g_base_info_get_namespace(info),
+ g_base_info_get_name(info));
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/* Get the "unknown namespace", which should be used for unnamespaced types */
+JSObject*
+gjs_lookup_private_namespace(JSContext *context)
+{
+ jsid ns_name;
+ ns_name = gjs_context_get_const_string(context, GJS_STRING_PRIVATE_NS_MARKER);
+ return gjs_lookup_namespace_object_by_name(context, ns_name);
+}
+
+/* Get the namespace object that the GIBaseInfo should be inside */
+JSObject*
+gjs_lookup_namespace_object(JSContext *context,
+ GIBaseInfo *info)
+{
+ const char *ns;
+ jsid ns_name;
+
+ ns = g_base_info_get_namespace(info);
+ if (ns == NULL) {
+ gjs_throw(context, "%s '%s' does not have a namespace",
+ gjs_info_type_name(g_base_info_get_type(info)),
+ g_base_info_get_name(info));
+
+ return NULL;
+ }
+
+ ns_name = gjs_intern_string_to_id(context, ns);
+ return gjs_lookup_namespace_object_by_name(context, ns_name);
+}
+
+JSObject*
+gjs_lookup_namespace_object_by_name(JSContext *context,
+ jsid ns_name)
+{
+ char *name;
+ char *script;
+ jsval ns_val;
+ JSObject *ns_obj = NULL;
+
+ JS_BeginRequest(context);
+
+ if (!gjs_get_string_id(context, ns_name, &name))
+ goto out;
+
+ script = g_strdup_printf("imports.gi.%s;", name);
+ if (!gjs_eval_with_scope(context, NULL, script, -1, "<internal>", &ns_val))
+ goto out;
+
+ ns_obj = JSVAL_TO_OBJECT(ns_val);
+
+ out:
+ JS_EndRequest(context);
+ return ns_obj;
+}
+
+const char*
+gjs_info_type_name(GIInfoType type)
+{
+ switch (type) {
+ case GI_INFO_TYPE_INVALID:
+ return "INVALID";
+ case GI_INFO_TYPE_FUNCTION:
+ return "FUNCTION";
+ case GI_INFO_TYPE_CALLBACK:
+ return "CALLBACK";
+ case GI_INFO_TYPE_STRUCT:
+ return "STRUCT";
+ case GI_INFO_TYPE_BOXED:
+ return "BOXED";
+ case GI_INFO_TYPE_ENUM:
+ return "ENUM";
+ case GI_INFO_TYPE_FLAGS:
+ return "FLAGS";
+ case GI_INFO_TYPE_OBJECT:
+ return "OBJECT";
+ case GI_INFO_TYPE_INTERFACE:
+ return "INTERFACE";
+ case GI_INFO_TYPE_CONSTANT:
+ return "CONSTANT";
+ case GI_INFO_TYPE_UNION:
+ return "UNION";
+ case GI_INFO_TYPE_VALUE:
+ return "VALUE";
+ case GI_INFO_TYPE_SIGNAL:
+ return "SIGNAL";
+ case GI_INFO_TYPE_VFUNC:
+ return "VFUNC";
+ case GI_INFO_TYPE_PROPERTY:
+ return "PROPERTY";
+ case GI_INFO_TYPE_FIELD:
+ return "FIELD";
+ case GI_INFO_TYPE_ARG:
+ return "ARG";
+ case GI_INFO_TYPE_TYPE:
+ return "TYPE";
+ case GI_INFO_TYPE_UNRESOLVED:
+ return "UNRESOLVED";
+ case GI_INFO_TYPE_INVALID_0:
+ g_assert_not_reached();
+ break;
+ }
+
+ return "???";
+}
+
+char*
+gjs_camel_from_hyphen(const char *hyphen_name)
+{
+ GString *s;
+ const char *p;
+ gboolean next_upper;
+
+ s = g_string_sized_new(strlen(hyphen_name) + 1);
+
+ next_upper = FALSE;
+ for (p = hyphen_name; *p; ++p) {
+ if (*p == '-' || *p == '_') {
+ next_upper = TRUE;
+ } else {
+ if (next_upper) {
+ g_string_append_c(s, g_ascii_toupper(*p));
+ next_upper = FALSE;
+ } else {
+ g_string_append_c(s, *p);
+ }
+ }
+ }
+
+ return g_string_free(s, FALSE);
+}
+
+char*
+gjs_hyphen_from_camel(const char *camel_name)
+{
+ GString *s;
+ const char *p;
+
+ /* four hyphens should be reasonable guess */
+ s = g_string_sized_new(strlen(camel_name) + 4 + 1);
+
+ for (p = camel_name; *p; ++p) {
+ if (g_ascii_isupper(*p)) {
+ g_string_append_c(s, '-');
+ g_string_append_c(s, g_ascii_tolower(*p));
+ } else {
+ g_string_append_c(s, *p);
+ }
+ }
+
+ return g_string_free(s, FALSE);
+}
+
+JSObject *
+gjs_lookup_generic_constructor(JSContext *context,
+ GIBaseInfo *info)
+{
+ JSObject *in_object;
+ JSObject *constructor;
+ const char *constructor_name;
+ jsval value;
+
+ in_object = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
+ constructor_name = g_base_info_get_name((GIBaseInfo*) info);
+
+ if (G_UNLIKELY (!in_object))
+ return NULL;
+
+ if (!JS_GetProperty(context, in_object, constructor_name, &value))
+ return NULL;
+
+ if (G_UNLIKELY (!JSVAL_IS_OBJECT(value) || JSVAL_IS_NULL(value)))
+ return NULL;
+
+ constructor = JSVAL_TO_OBJECT(value);
+ g_assert(constructor != NULL);
+
+ return constructor;
+}
+
+JSObject *
+gjs_lookup_generic_prototype(JSContext *context,
+ GIBaseInfo *info)
+{
+ JSObject *constructor;
+ jsval value;
+
+ constructor = gjs_lookup_generic_constructor(context, info);
+ if (G_UNLIKELY (constructor == NULL))
+ return NULL;
+
+ if (!gjs_object_get_property_const(context, constructor,
+ GJS_STRING_PROTOTYPE, &value))
+ return NULL;
+
+ if (G_UNLIKELY (!JSVAL_IS_OBJECT(value)))
+ return NULL;
+
+ return JSVAL_TO_OBJECT(value);
+}
diff --git a/gi/repo.h b/gi/util.h
similarity index 92%
rename from gi/repo.h
rename to gi/util.h
index ba1fd90..c2b277e 100644
--- a/gi/repo.h
+++ b/gi/util.h
@@ -32,9 +32,6 @@
G_BEGIN_DECLS
-JSBool gjs_define_repo (JSContext *context,
- JSObject **module_out,
- const char *name);
const char* gjs_info_type_name (GIInfoType type);
JSObject* gjs_lookup_private_namespace (JSContext *context);
JSObject* gjs_lookup_namespace_object (JSContext *context,
diff --git a/gjs/context.cpp b/gjs/context.cpp
index aaedb6f..3f0be36 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -27,7 +27,6 @@
#include "context-private.h"
#include "bootstrap.h"
-#include "importer.h"
#include "jsapi-private.h"
#include "jsapi-util.h"
#include "native.h"
@@ -78,7 +77,7 @@ struct _GjsContext {
/* Keep this consistent with GjsConstString */
static const char *const_strings[] = {
"constructor", "prototype", "length",
- "imports", "__parentModule__", "__init__", "searchPath",
+ "__parentModule__", "__init__", "searchPath",
"__gjsKeepAlive", "__gjsPrivateNS",
"gi", "versions", "overrides",
"_init", "_instance_init", "_new_internal", "new",
@@ -321,7 +320,6 @@ gjs_context_class_init(GjsContextClass *klass)
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_static_modules();
}
@@ -443,24 +441,6 @@ gjs_context_constructed(GObject *object)
if (!JS_DefineFunctions(js_context->context, js_context->global, &global_funcs[0]))
g_error("Failed to define properties on the global object");
- /* We create the global-to-runtime root importer with the
- * passed-in search path. If someone else already created
- * the root importer, this is a no-op.
- */
- if (!gjs_create_root_importer(js_context->context,
- js_context->search_path ?
- (const char**) js_context->search_path :
- NULL,
- TRUE))
- g_error("Failed to create root importer");
-
- /* Now copy the global root importer (which we just created,
- * if it didn't exist) to our global object
- */
- if (!gjs_define_root_importer(js_context->context,
- js_context->global))
- g_error("Failed to point 'imports' property at root importer");
-
if (!gjs_run_bootstrap(js_context->context))
g_error("Failed to bootstrap GJS context");
diff --git a/gjs/gi.h b/gjs/gi.h
index 837d03d..786fc61 100644
--- a/gjs/gi.h
+++ b/gjs/gi.h
@@ -30,8 +30,6 @@
G_BEGIN_DECLS
-JSBool gjs_define_gi_stuff (JSContext *context,
- JSObject **module_out);
JSBool gjs_define_private_gi_stuff (JSContext *context,
JSObject **module_out);
diff --git a/gjs/gjs-module.h b/gjs/gjs-module.h
index f85f89b..f644139 100644
--- a/gjs/gjs-module.h
+++ b/gjs/gjs-module.h
@@ -27,7 +27,6 @@
#include <gjs/gjs.h>
#include <gjs/native.h>
#include <gjs/mem.h>
-#include <gjs/importer.h>
#include <gjs/runtime.h>
#include <gjs/jsapi-util.h>
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 6e98713..49770d4 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -46,7 +46,6 @@ enum {
};
typedef enum {
- GJS_GLOBAL_SLOT_IMPORTS,
GJS_GLOBAL_SLOT_KEEP_ALIVE,
GJS_GLOBAL_SLOT_BYTE_ARRAY_PROTOTYPE,
GJS_GLOBAL_SLOT_LAST,
@@ -407,7 +406,6 @@ typedef enum {
GJS_STRING_CONSTRUCTOR,
GJS_STRING_PROTOTYPE,
GJS_STRING_LENGTH,
- GJS_STRING_IMPORTS,
GJS_STRING_PARENT_MODULE,
GJS_STRING_MODULE_INIT,
GJS_STRING_SEARCH_PATH,
diff --git a/modules/bootstrap.js b/modules/bootstrap.js
index 3f1ee3d..2292ef5 100644
--- a/modules/bootstrap.js
+++ b/modules/bootstrap.js
@@ -15,18 +15,10 @@
}
const Importer = importNativeModule('_importer');
+ const Gio = Importer.importGIModule('Gio', '2.0');
function loadNativeModule(moduleID) {
- // _exports[moduleID] = importNativeModule(moduleID);
-
- // XXX: In order to not double-register modules, we need
- // to do this. As soon as we implement the importer on
- // top of the new system, revert this.
-
- try {
- _exports[moduleID] = imports[moduleID];
- } catch(e) {
- }
+ _exports[moduleID] = importNativeModule(moduleID);
}
function runOverridesForGIModule(module, moduleID) {
@@ -70,4 +62,126 @@
importGIModuleWithOverrides(giModuleID, moduleVersion);
}
+
+ function installImports() {
+ // Implement the global "imports" object.
+
+ // imports.gi
+ let gi = new Proxy({
+ versions: {},
+ }, {
+ get: function(target, name) {
+ if (target[name])
+ return target[name];
+
+ let version = target.versions[name] || null;
+ return importGIModuleWithOverrides(name, version);
+ },
+ });
+
+ function importModule(module, file) {
+ let success, script;
+ try {
+ [success, script] = file.load_contents(null);
+ } catch(e) {
+ return null;
+ }
+
+ // Don't catch errors for the eval, as those should propagate
+ // back up to the user...
+ Importer.evalWithScope(module, script, file.get_parse_name());
+ return module;
+ }
+
+ function importFile(parent, name, file) {
+ let module = {};
+ parent[name] = module;
+ module.__file__ = file.get_parse_name();
+ module.__moduleName__ = name;
+ module.__parentModule__ = parent;
+ importModule(module, file);
+ }
+
+ function importDirectory(parent, name) {
+ let searchPath = parent.searchPath.map(function(path) {
+ return path + '/' + name;
+ }).filter(function(path) {
+ let file = Gio.File.new_for_commandline_arg(path);
+ let type = file.query_file_type(Gio.FileQueryInfoFlags.NONE, null);
+ return (type == Gio.FileType.DIRECTORY);
+ });
+
+ let module = createSearchPathImporter();
+ parent[name] = module;
+ module.searchPath = searchPath;
+ module.__moduleName__ = name;
+ module.__parentModule__ = parent;
+
+ tryImport(module, '__init__');
+ }
+
+ function tryImport(proxy, name) {
+ function tryPath(path) {
+ let file, type;
+ file = Gio.File.new_for_commandline_arg(path);
+ type = file.query_file_type(Gio.FileQueryInfoFlags.NONE, null);
+ if (type == Gio.FileType.DIRECTORY) {
+ importDirectory(proxy, name);
+ return true;
+ } else {
+ file = Gio.File.new_for_commandline_arg(path + '.js');
+ if (file.query_exists(null)) {
+ importFile(proxy, name, file);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ for (let path of proxy.searchPath) {
+ let modulePath = path + '/' + name;
+ if (tryPath(modulePath))
+ return;
+ }
+ }
+
+ function createSearchPathImporter() {
+ let proxy = new Proxy({ __init__: {} }, {
+ get: function(target, name) {
+ if (target.__init__[name])
+ return target.__init__[name];
+
+ if (!target[name])
+ tryImport(proxy, name);
+
+ return target[name];
+ },
+ });
+ return proxy;
+ }
+
+ let rootDirectoryImporter = createSearchPathImporter();
+ rootDirectoryImporter.searchPath = Importer.getBuiltinSearchPath();
+
+ // root importer, checks for native modules
+ let rootImporter = new Proxy(rootDirectoryImporter, {
+ get: function(target, name) {
+ if (target[name])
+ return target[name];
+
+ let nativeModule = importNativeModule(name);
+ if (nativeModule) {
+ target[name] = nativeModule;
+ return nativeModule;
+ }
+
+ return rootDirectoryImporter[name];
+ },
+ });
+ rootImporter.gi = gi;
+
+ exports.imports = rootImporter;
+ }
+ installImports();
+
})(window, importNativeModule);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]