[gjs/esm/dynamic-imports: 4/6] WIP - add dynamic import support to scripts
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/esm/dynamic-imports: 4/6] WIP - add dynamic import support to scripts
- Date: Sun, 7 Feb 2021 18:41:35 +0000 (UTC)
commit a6c5ff345556bf914f85460685c7e1eeb5600b1f
Author: Evan Welsh <contact evanwelsh com>
Date: Fri Feb 5 21:51:41 2021 -0800
WIP - add dynamic import support to scripts
To allow import() from scripts we must set script privates
with a object similar to the ModulePrivate class.
gjs/context.cpp | 8 ++++++++
gjs/module.cpp | 38 +++++++++++++++++++++++++++++++++++--
gjs/module.h | 3 +++
installed-tests/js/testESModules.js | 19 +++++++++----------
4 files changed, 56 insertions(+), 12 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 1a85f6c6..01565595 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -1249,6 +1249,14 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
JS::CompileOptions options(m_cx);
options.setFileAndLine(filename, 1);
+ GjsAutoUnref<GFile> file = g_file_new_for_commandline_arg(filename);
+ GjsAutoChar uri = g_file_get_uri(file);
+ JS::RootedObject priv(m_cx, gjs_script_module_build_private(m_cx, uri));
+ if (!priv)
+ return false;
+
+ options.setPrivateValue(JS::ObjectValue(*priv));
+
if (!JS::Evaluate(m_cx, scope_chain, options, buf, retval))
return false;
diff --git a/gjs/module.cpp b/gjs/module.cpp
index 9645e134..ed6b97de 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -92,7 +92,7 @@ class GjsScriptModule {
GJS_JSAPI_RETURN_CONVENTION
bool evaluate_import(JSContext* cx, JS::HandleObject module,
const char* script, ssize_t script_len,
- const char* filename) {
+ const char* filename, const char* uri) {
std::u16string utf16_string =
gjs_utf8_script_to_utf16(script, script_len);
// COMPAT: This could use JS::SourceText<mozilla::Utf8Unit> directly,
@@ -112,6 +112,9 @@ class GjsScriptModule {
JS::CompileOptions options(cx);
options.setFileAndLine(filename, 1);
+ JS::RootedObject priv(cx, build_private(cx, uri));
+ options.setPrivateValue(JS::ObjectValue(*priv));
+
JS::RootedValue ignored_retval(cx);
if (!JS::Evaluate(cx, scope_chain, options, buf, &ignored_retval))
return false;
@@ -143,7 +146,8 @@ class GjsScriptModule {
g_assert(script);
GjsAutoChar full_path = g_file_get_parse_name(file);
- return evaluate_import(cx, module, script, script_len, full_path);
+ GjsAutoChar uri = g_file_get_uri(file);
+ return evaluate_import(cx, module, script, script_len, full_path, uri);
}
/* JSClass operations */
@@ -213,6 +217,21 @@ class GjsScriptModule {
};
public:
+ /*
+ * Creates a JS object to pass to JS::CompileOptions as a script's private.
+ */
+ [[nodiscard]] static JSObject* build_private(JSContext* cx, const char* script_uri) {
+ JS::RootedObject priv(cx, JS_NewPlainObject(cx));
+ const GjsAtoms& atoms = GjsContextPrivate::atoms(cx);
+
+ JS::RootedValue val(cx);
+ if (!gjs_string_from_utf8(cx, script_uri, &val) ||
+ !JS_SetPropertyById(cx, priv, atoms.uri(), val))
+ return nullptr;
+
+ return priv;
+ }
+
/* Carries out the import operation */
GJS_JSAPI_RETURN_CONVENTION
static JSObject *
@@ -232,6 +251,21 @@ class GjsScriptModule {
}
};
+/**
+ * gjs_script_module_build_private:
+ * @param cx the #JSContext
+ * @param uri the URI this script module is loaded from
+ *
+ * @brief To support dynamic imports from scripts, we need to provide private
+ * data when we compile scripts which is compatible with our module resolution
+ * hooks in modules/internal/loader.js
+ *
+ * @returns a JSObject which can be used for a JSScript's private data.
+ */
+JSObject* gjs_script_module_build_private(JSContext* cx, const char* uri) {
+ return GjsScriptModule::build_private(cx, uri);
+}
+
/**
* gjs_module_import:
* @cx: the JS context
diff --git a/gjs/module.h b/gjs/module.h
index d303530f..dbe088ec 100644
--- a/gjs/module.h
+++ b/gjs/module.h
@@ -21,6 +21,9 @@ gjs_module_import(JSContext *cx,
const char *name,
GFile *file);
+GJS_JSAPI_RETURN_CONVENTION
+JSObject* gjs_script_module_build_private(JSContext* cx, const char* uri);
+
GJS_JSAPI_RETURN_CONVENTION
JSObject* gjs_get_native_registry(JSObject* global);
diff --git a/installed-tests/js/testESModules.js b/installed-tests/js/testESModules.js
index 6b5afa40..bdc1a89f 100644
--- a/installed-tests/js/testESModules.js
+++ b/installed-tests/js/testESModules.js
@@ -80,21 +80,20 @@ describe('Builtin ES modules', function () {
describe('Dynamic imports', function () {
let module;
- beforeEach(function (done) {
- import('resource:///org/gjs/jsunit/modules/say.js')
- .then(m => (module = m))
- .catch(err => {
- logError(err);
- fail();
- })
- .finally(done);
+ beforeEach(async function () {
+ try {
+ module = await import('resource:///org/gjs/jsunit/modules/say.js')
+ } catch(err) {
+ logError(err);
+ fail();
+ }
});
- it('default import', function () {
+ it('default import', async function () {
expect(module.default()).toEqual('default export');
});
- it('named import', function () {
+ it('named import', async function () {
expect(module.say('hi')).toEqual('<( hi )');
});
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]