[gjs/wip/require: 11/11] import compat
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/require: 11/11] import compat
- Date: Wed, 15 Jan 2014 16:58:58 +0000 (UTC)
commit 2177544c823e87881962e91b07a794ec9735f1ee
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Wed Jan 15 11:17:38 2014 -0500
import compat
Makefile.am | 7 +-
gi/boxed.cpp | 2 +-
gi/enumeration.cpp | 2 +-
gi/foreign.cpp | 15 +-
gi/gerror.cpp | 2 +-
gi/ns.cpp | 2 +-
gi/object.cpp | 2 +-
gi/param.cpp | 2 +-
gi/repo.cpp | 760 --------------------------------
gi/union.cpp | 3 +-
gi/util.cpp | 401 +++++++++++++++++
gi/{repo.h => util.h} | 3 -
gjs/byteArray.cpp | 2 +-
gjs/context.cpp | 67 ++-
gjs/context.h | 2 +
gjs/gi.cpp | 39 --
gjs/gi.h | 2 -
gjs/gjs-module.h | 1 -
gjs/importer.cpp | 1172 -------------------------------------------------
gjs/importer.h | 52 ---
gjs/jsapi-util.h | 2 -
modules/bootstrap.js | 132 ++++++
22 files changed, 597 insertions(+), 2075 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index dfd72df..8c8dc94 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,7 +31,6 @@ nobase_gjs_module_include_HEADERS = \
gjs/gjs-module.h \
gjs/compat.h \
gjs/byteArray.h \
- gjs/importer.h \
gjs/jsapi-util.h \
gjs/runtime.h \
gjs/type-module.h \
@@ -41,7 +40,7 @@ nobase_gjs_module_include_HEADERS = \
gi/object.h \
gi/foreign.h \
gi/param.h \
- gi/repo.h \
+ gi/util.h \
gi/union.h \
gi/value.h \
gi/arg.h \
@@ -105,9 +104,7 @@ libgjs_la_SOURCES = \
gjs/byteArray.cpp \
gjs/context.cpp \
gjs/bootstrap.cpp \
- gjs/importer.cpp \
gjs/gi.h \
- gjs/gi.cpp \
gjs/jsapi-private.cpp \
gjs/jsapi-util.cpp \
gjs/jsapi-dynamic-class.cpp \
@@ -142,7 +139,7 @@ libgjs_la_SOURCES += \
gi/foreign.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 4fcda3b..fce45e1 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 0fb0132..c907d92 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 <util/log.h>
diff --git a/gi/foreign.cpp b/gi/foreign.cpp
index efbadfd..bb47ff1 100644
--- a/gi/foreign.cpp
+++ b/gi/foreign.cpp
@@ -69,26 +69,23 @@ gjs_foreign_load_foreign_module(JSContext *context,
if (strcmp(gi_namespace, foreign_modules[i].gi_namespace) != 0)
continue;
- if (foreign_modules[i].loaded) {
+ if (foreign_modules[i].loaded)
return JS_TRUE;
- }
// FIXME: Find a way to check if a module is imported
// and only execute this statement if isn't
- script = g_strdup_printf("imports.%s;", gi_namespace);
- if (!gjs_context_eval((GjsContext*) JS_GetContextPrivate(context), script, strlen(script),
- "<internal>", &code,
- &error)) {
- g_printerr("ERROR: %s\n", error->message);
+ script = g_strdup_printf("require('%s');", gi_namespace);
+ if (!gjs_eval_with_scope(context, NULL, script, -1, "<internal>", NULL)) {
g_free(script);
- g_error_free(error);
return JS_FALSE;
}
+
g_free(script);
foreign_modules[i].loaded = TRUE;
+ return JS_TRUE;
}
- return JS_TRUE;
+ return JS_FALSE;
}
JSBool
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 0856955..917bfd4 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/ns.cpp b/gi/ns.cpp
index 1a55849..2488794 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 c92b169..f8c1d3b 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 3286238..0457615 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 <gjs/gjs-module.h>
#include <gjs/compat.h>
diff --git a/gi/union.cpp b/gi/union.cpp
index 8364473..d3ad5af 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..599b5dc
--- /dev/null
+++ b/gi/util.cpp
@@ -0,0 +1,401 @@
+/* -*- 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 "interface.h"
+#include "gerror.h"
+
+#include <gjs/compat.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)
+{
+#if GJS_VERBOSE_ENABLE_GI_USAGE
+ _gjs_log_info_usage(info);
+#endif
+ 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 {
+ 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:
+ 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("require('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_prototype(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);
+
+ 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 91%
rename from gi/repo.h
rename to gi/util.h
index 60d5be4..c737b08 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/byteArray.cpp b/gjs/byteArray.cpp
index 42d7dc1..e60b303 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -544,7 +544,7 @@ byte_array_get_prototype(JSContext *context)
JSObject *prototype;
if (!gjs_eval_with_scope(context, NULL,
- "imports.byteArray.ByteArray.prototype;", -1,
+ "require('byteArray').ByteArray.prototype;", -1,
"<internal>", &retval))
g_error ("Could not import byte array prototype\n");
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 46f3302..58b829c 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -27,7 +27,6 @@
#include "context.h"
#include "bootstrap.h"
-#include "importer.h"
#include "jsapi-util.h"
#include "native.h"
#include "byteArray.h"
@@ -73,7 +72,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", "_new_internal", "new",
@@ -316,7 +315,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();
}
@@ -461,24 +459,6 @@ gjs_context_constructed(GObject *object)
4, GJS_MODULE_PROP_FLAGS))
g_error("Failed to define printerr function");
- /* 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");
@@ -765,3 +745,48 @@ gjs_context_get_search_path(GjsContext *context)
{
return (const char **) context->search_path;
}
+
+char ** gjs_search_path;
+
+G_CONST_RETURN char * G_CONST_RETURN *
+gjs_get_search_path(void)
+{
+ char **search_path;
+
+ /* not thread safe */
+
+ if (!gjs_search_path) {
+ G_CONST_RETURN gchar* G_CONST_RETURN * system_data_dirs;
+ const char *envstr;
+ GPtrArray *path;
+ gsize i;
+
+ path = g_ptr_array_new();
+
+ /* in order of priority */
+
+ /* $GJS_PATH */
+ envstr = g_getenv("GJS_PATH");
+ if (envstr) {
+ char **dirs, **d;
+ dirs = g_strsplit(envstr, G_SEARCHPATH_SEPARATOR_S, 0);
+ for (d = dirs; *d != NULL; d++)
+ g_ptr_array_add(path, *d);
+ /* we assume the array and strings are allocated separately */
+ g_free(dirs);
+ }
+
+ /* ${datadir}/share/gjs-1.0 */
+ g_ptr_array_add(path, g_strdup("resource:///org/gnome/gjs/modules/"));
+
+ g_ptr_array_add(path, NULL);
+
+ search_path = (char**)g_ptr_array_free(path, FALSE);
+
+ gjs_search_path = search_path;
+ } else {
+ search_path = gjs_search_path;
+ }
+
+ return (G_CONST_RETURN char * G_CONST_RETURN *)search_path;
+}
diff --git a/gjs/context.h b/gjs/context.h
index acd07d1..54969a0 100644
--- a/gjs/context.h
+++ b/gjs/context.h
@@ -79,6 +79,8 @@ void gjs_dumpstack (void);
const char ** gjs_context_get_search_path (GjsContext *context);
+G_CONST_RETURN char * G_CONST_RETURN * gjs_get_search_path (void);
+
G_END_DECLS
#endif /* __GJS_CONTEXT_H__ */
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 32b2d4c..d5a7c3e 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_LAST,
} GjsGlobalSlot;
@@ -408,7 +407,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 31a988d..ef52a15 100644
--- a/modules/bootstrap.js
+++ b/modules/bootstrap.js
@@ -6,6 +6,10 @@
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);
}
@@ -134,4 +138,132 @@
}
require.paths = Importer.getBuiltinSearchPath();
+ function installCompatImports() {
+ // 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 = {};
+ module.__file__ = file.get_parse_name();
+ module.__moduleName__ = name;
+ module.__parentModule__ = parent;
+ importModule(module, file);
+ return module;
+ }
+
+ 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();
+ module.searchPath = searchPath;
+ module.__moduleName__ = name;
+ module.__parentModule__ = parent;
+
+ function runInit() {
+ for (let path of searchPath) {
+ let initFile = Gio.File.new_for_commandline_arg(path + '/__init__.js');
+ if (initFile.query_exists(null)) {
+ importModule(module, initFile);
+ return;
+ }
+ }
+ }
+
+ runInit();
+
+ return module;
+ }
+
+ 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)
+ return importDirectory(proxy, name);
+
+ file = Gio.File.new_for_commandline_arg(path + '.js');
+ if (file.query_exists(null))
+ return importFile(proxy, name, file);
+
+ return null;
+ }
+
+ for (let path of proxy.searchPath) {
+ let modulePath = path + '/' + name;
+ let obj = tryPath(modulePath);
+ if (obj)
+ return obj;
+ }
+ return null;
+ }
+
+ function createSearchPathImporter() {
+ let proxy = new Proxy({}, {
+ get: function(target, name) {
+ if (target[name])
+ return target[name];
+
+ let obj = tryImport(proxy, name);
+ target[obj] = obj;
+ return obj;
+ },
+ });
+ 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;
+ }
+ installCompatImports();
+
})(window, importNativeModule);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]