[gjs] importer: Useful toString for importer and module objects
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] importer: Useful toString for importer and module objects
- Date: Fri, 6 Jan 2017 04:06:17 +0000 (UTC)
commit 4c74e71f38f245184ecaa7d6761d9f049c72dad0
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Dec 3 12:51:09 2010 -0500
importer: Useful toString for importer and module objects
SpiderMonkey doesn't have a useful default toString(): [object Object].
When debugging, it's useful to have information like the imported path of
a module, which we previously didn't display.
Original patch by Jasper St. Pierre; rewritten for current GJS by Philip
Chimento.
https://bugzilla.gnome.org/show_bug.cgi?id=636283
gjs/context.cpp | 2 +-
gjs/importer.cpp | 91 +++++++++++++++++++++++++++++++++--
gjs/jsapi-util.h | 1 +
installed-tests/js/testImporter.js | 10 ++++
4 files changed, 97 insertions(+), 7 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index f75f742..1c3b829 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -86,7 +86,7 @@ static const char *const_strings[] = {
"gi", "versions", "overrides",
"_init", "_instance_init", "_new_internal", "new",
"message", "code", "stack", "fileName", "lineNumber", "name",
- "x", "y", "width", "height",
+ "x", "y", "width", "height", "__modulePath__"
};
G_STATIC_ASSERT(G_N_ELEMENTS(const_strings) == GJS_STRING_LAST);
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index ce6ee14..2f54be8 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -53,6 +53,33 @@ extern struct JSClass gjs_importer_class;
GJS_DEFINE_PRIV_FROM_JS(Importer, gjs_importer_class)
static bool
+importer_to_string(JSContext *cx,
+ unsigned argc,
+ JS::Value *vp)
+{
+ GJS_GET_THIS(cx, argc, vp, args, importer);
+ const JSClass *klass = JS_GetClass(importer);
+
+ JS::RootedValue module_path(cx);
+ if (!gjs_object_get_property_const(cx, importer, GJS_STRING_MODULE_PATH,
+ &module_path))
+ return false;
+
+ g_autofree char *path = NULL;
+ if (module_path.isNull()) {
+ path = g_strdup("root");
+ } else {
+ if (!gjs_string_to_utf8(cx, module_path, &path))
+ return false;
+ }
+
+ g_autofree char *output = g_strdup_printf("[%s %s]", klass->name, path);
+
+ args.rval().setString(JS_NewStringCopyZ(cx, output));
+ return true;
+}
+
+static bool
define_meta_properties(JSContext *context,
JS::HandleObject module_obj,
const char *full_path,
@@ -80,26 +107,46 @@ define_meta_properties(JSContext *context,
return false;
}
+ /* Null is used instead of undefined to make sure we don't try to invoke
+ * a "resolve" operation. */
JS::RootedValue module_name_val(context, JS::NullValue());
JS::RootedValue parent_module_val(context, JS::NullValue());
+ JS::RootedValue module_path(context, JS::NullValue());
if (parent_is_module) {
module_name_val.setString(JS_NewStringCopyZ(context, module_name));
parent_module_val.setObject(*parent);
+
+ JS::RootedValue parent_module_path(context);
+ if (!gjs_object_get_property_const(context, parent,
+ GJS_STRING_MODULE_PATH,
+ &parent_module_path))
+ return false;
+
+ g_autofree char *module_path_buf = NULL;
+ if (parent_module_path.isNull()) {
+ module_path_buf = g_strdup(module_name);
+ } else {
+ g_autofree char *parent_path = NULL;
+ if (!gjs_string_to_utf8(context, parent_module_path, &parent_path))
+ return false;
+ module_path_buf = g_strdup_printf("%s.%s", parent_path, module_name);
+ }
+ module_path.setString(JS_NewStringCopyZ(context, module_path_buf));
}
+ /* don't set ENUMERATE since we wouldn't want to copy these symbols to any
+ * other object for example. */
if (!JS_DefineProperty(context, module_obj,
"__moduleName__", module_name_val,
- /* don't set ENUMERATE since we wouldn't want to copy
- * this symbol to any other object for example.
- */
JSPROP_READONLY | JSPROP_PERMANENT))
return false;
if (!JS_DefineProperty(context, module_obj,
"__parentModule__", parent_module_val,
- /* don't set ENUMERATE since we wouldn't want to copy
- * this symbol to any other object for example.
- */
+ JSPROP_READONLY | JSPROP_PERMANENT))
+ return false;
+
+ if (!JS_DefineProperty(context, module_obj, "__modulePath__", module_path,
JSPROP_READONLY | JSPROP_PERMANENT))
return false;
@@ -211,6 +258,29 @@ cancel_import(JSContext *context,
}
static bool
+module_to_string(JSContext *cx,
+ unsigned argc,
+ JS::Value *vp)
+{
+ GJS_GET_THIS(cx, argc, vp, args, module);
+
+ JS::RootedValue module_path(cx);
+ if (!gjs_object_get_property_const(cx, module, GJS_STRING_MODULE_PATH,
+ &module_path))
+ return false;
+
+ g_assert(!module_path.isNull());
+
+ g_autofree char *path = NULL;
+ if (!gjs_string_to_utf8(cx, module_path, &path))
+ return false;
+ g_autofree char *output = g_strdup_printf("[GjsModule %s]", path);
+
+ args.rval().setString(JS_NewStringCopyZ(cx, output));
+ return true;
+}
+
+static bool
import_native_file(JSContext *context,
JS::HandleObject obj,
const char *name)
@@ -225,6 +295,10 @@ import_native_file(JSContext *context,
if (!define_meta_properties(context, module_obj, NULL, name, obj))
return false;
+ if (!JS_DefineFunction(context, module_obj, "toString", module_to_string,
+ 0, 0))
+ return false;
+
if (JS_IsExceptionPending(context)) {
/* I am not sure whether this can happen, but if it does we want to trap it.
*/
@@ -382,6 +456,10 @@ import_file_on_module(JSContext *context,
if (!define_meta_properties(context, module_obj, full_path, name, obj))
goto out;
+ if (!JS_DefineFunction(context, module_obj, "toString", module_to_string,
+ 0, 0))
+ goto out;
+
if (!seal_import(context, obj, name))
goto out;
@@ -889,6 +967,7 @@ JSPropertySpec gjs_importer_proto_props[] = {
};
JSFunctionSpec gjs_importer_proto_funcs[] = {
+ JS_FS("toString", importer_to_string, 0, 0),
JS_FS_END
};
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 79d64fb..7564865 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -473,6 +473,7 @@ typedef enum {
GJS_STRING_Y,
GJS_STRING_WIDTH,
GJS_STRING_HEIGHT,
+ GJS_STRING_MODULE_PATH,
GJS_STRING_LAST
} GjsConstString;
diff --git a/installed-tests/js/testImporter.js b/installed-tests/js/testImporter.js
index 26be7ed..0f01019 100644
--- a/installed-tests/js/testImporter.js
+++ b/installed-tests/js/testImporter.js
@@ -57,6 +57,11 @@ describe('Importer', function () {
expect(imports).toBeDefined();
});
+ it('has a toString representation', function () {
+ expect(imports.toString()).toEqual('[GjsFileImporter root]');
+ expect(subA.toString()).toEqual('[GjsFileImporter subA]');
+ });
+
it('throws an import error when trying to import a nonexistent module', function () {
expect(() => imports.nonexistentModuleName)
.toThrow(jasmine.objectContaining({ name: 'ImportError' }));
@@ -92,6 +97,11 @@ describe('Importer', function () {
expect(subFoobar.bar).toEqual('This is bar');
});
+ it('imports modules with a toString representation', function () {
+ expect(foobar.toString()).toEqual('[GjsModule foobar]');
+ expect(subFoobar.toString()).toEqual('[GjsModule subA.subB.foobar]');
+ });
+
it('does not share the same object for a module on a different path', function () {
foobar.somethingElse = 'Should remain';
expect(subFoobar.somethingElse).not.toBeDefined();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]