[gjs/mozjs91: 8/17] Adapt to new module and script APIs
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/mozjs91: 8/17] Adapt to new module and script APIs
- Date: Sat, 7 Aug 2021 01:32:02 +0000 (UTC)
commit 9f5aabb2e88f55cac40dd9a903934b369e196aa8
Author: Evan Welsh <contact evanwelsh com>
Date: Sat Jul 10 20:28:43 2021 -0700
Adapt to new module and script APIs
- JS::ModuleEvaluate now has an output value in anticipation of TLA
- Script privates are no longer set at compile time
- JS_[Set,Get]ReservedSlot is now JS::[Set,Get]ReservedSlot
- Module resolution is given an object instead of a specifier
- Use the *_NoTLA variants of functions to avoid enabling Top Level Await
- Dynamic imports now have a status that must be set
See https://bugzilla.mozilla.org/show_bug.cgi?id=1702278
gjs/context.cpp | 23 ++++++++++++++-------
gjs/global.cpp | 8 ++++---
gjs/internal.cpp | 5 ++++-
gjs/module.cpp | 63 ++++++++++++++++++++++++++++++++++++--------------------
gjs/module.h | 6 +++---
5 files changed, 69 insertions(+), 36 deletions(-)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 6ed6dd62..ea4dc7d4 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -522,7 +522,8 @@ static void load_context_module(JSContext* cx, const char* uri,
g_error("Failed to instantiate %s module.", debug_identifier);
}
- if (!JS::ModuleEvaluate(cx, loader)) {
+ JS::RootedValue ignore(cx);
+ if (!JS::ModuleEvaluate(cx, loader, &ignore)) {
gjs_log_exception(cx);
g_error("Failed to evaluate %s module.", debug_identifier);
}
@@ -1327,7 +1328,8 @@ bool GjsContextPrivate::eval_module(const char* identifier,
}
bool ok = true;
- if (!JS::ModuleEvaluate(m_cx, obj))
+ JS::RootedValue ignore(m_cx);
+ if (!JS::ModuleEvaluate(m_cx, obj, &ignore))
ok = false;
/* The promise job queue should be drained even on error, to finish
@@ -1419,7 +1421,8 @@ bool gjs_context_eval_module_file(GjsContext* js_context, const char* filename,
* Otherwise, the global definitions are just discarded.
*/
bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
- const char* script, ssize_t script_len,
+ const char* script_source,
+ ssize_t script_source_len,
const char* filename,
JS::MutableHandleValue retval) {
/* log and clear exception if it's set (should not be, normally...) */
@@ -1432,7 +1435,8 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
if (!eval_obj)
eval_obj = JS_NewPlainObject(m_cx);
- std::u16string utf16_string = gjs_utf8_script_to_utf16(script, script_len);
+ std::u16string utf16_string =
+ gjs_utf8_script_to_utf16(script_source, script_source_len);
// COMPAT: This could use JS::SourceText<mozilla::Utf8Unit> directly,
// but that messes up code coverage. See bug
// https://bugzilla.mozilla.org/show_bug.cgi?id=1404784
@@ -1448,7 +1452,8 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
}
JS::CompileOptions options(m_cx);
- options.setFileAndLine(filename, 1);
+ options.setFileAndLine(filename, 1)
+ .setNonSyntacticScope(true);
GjsAutoUnref<GFile> file = g_file_new_for_commandline_arg(filename);
GjsAutoChar uri = g_file_get_uri(file);
@@ -1456,9 +1461,13 @@ bool GjsContextPrivate::eval_with_scope(JS::HandleObject scope_object,
if (!priv)
return false;
- options.setPrivateValue(JS::ObjectValue(*priv));
+ JS::RootedScript script(m_cx);
+ script.set(JS::Compile(m_cx, options, buf));
+ if (!script)
+ return false;
- if (!JS::Evaluate(m_cx, scope_chain, options, buf, retval))
+ JS::SetScriptPrivate(script, JS::ObjectValue(*priv));
+ if (!JS_ExecuteScript(m_cx, scope_chain, script, retval))
return false;
schedule_gc_if_needed();
diff --git a/gjs/global.cpp b/gjs/global.cpp
index 1883c445..5b5ef860 100644
--- a/gjs/global.cpp
+++ b/gjs/global.cpp
@@ -17,6 +17,7 @@
#include <js/CompilationAndEvaluation.h>
#include <js/CompileOptions.h>
#include <js/Id.h>
+#include <js/Object.h>
#include <js/PropertyDescriptor.h> // for JSPROP_PERMANENT, JSPROP_RE...
#include <js/PropertySpec.h>
#include <js/Realm.h> // for GetObjectRealmOrNull, SetRealmPrivate
@@ -98,7 +99,8 @@ class GjsBaseGlobal {
JS::SourceOwnership::TakeOwnership))
return false;
- JS::RootedScript compiled_script(cx, JS::Compile(cx, options, source));
+ JS::RootedScript compiled_script(cx);
+ compiled_script.set(JS::Compile(cx, options, source));
if (!compiled_script)
return false;
@@ -521,11 +523,11 @@ bool gjs_define_global_properties(JSContext* cx, JS::HandleObject global,
}
void detail::set_global_slot(JSObject* global, uint32_t slot, JS::Value value) {
- JS_SetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot, value);
+ JS::SetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot, value);
}
JS::Value detail::get_global_slot(JSObject* global, uint32_t slot) {
- return JS_GetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot);
+ return JS::GetReservedSlot(global, JSCLASS_GLOBAL_SLOT_COUNT + slot);
}
decltype(GjsGlobal::klass) constexpr GjsGlobal::klass;
diff --git a/gjs/internal.cpp b/gjs/internal.cpp
index fea6e71e..304c2b1e 100644
--- a/gjs/internal.cpp
+++ b/gjs/internal.cpp
@@ -102,8 +102,11 @@ bool gjs_load_internal_module(JSContext* cx, const char* identifier) {
JS::RootedId key(cx, gjs_intern_string_to_id(cx, full_path));
+ // TODO(ewlsh): This is the value returned for TLA (top-level await)
+ JS::RootedValue ignore(cx);
if (!gjs_global_registry_set(cx, registry, key, module) ||
- !JS::ModuleInstantiate(cx, module) || !JS::ModuleEvaluate(cx, module)) {
+ !JS::ModuleInstantiate(cx, module) ||
+ !JS::ModuleEvaluate(cx, module, &ignore)) {
return false;
}
diff --git a/gjs/module.cpp b/gjs/module.cpp
index b831cfcd..7cc7b644 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -26,6 +26,7 @@
#include <js/PropertyDescriptor.h>
#include <js/RootingAPI.h>
#include <js/SourceText.h>
+#include <js/String.h>
#include <js/TypeDecls.h>
#include <js/Utility.h> // for UniqueChars
#include <js/Value.h>
@@ -94,10 +95,10 @@ class GjsScriptModule {
/* Carries out the actual execution of the module code */
GJS_JSAPI_RETURN_CONVENTION
bool evaluate_import(JSContext* cx, JS::HandleObject module,
- const char* script, ssize_t script_len,
+ const char* script_, ssize_t script_len,
const char* filename, const char* uri) {
std::u16string utf16_string =
- gjs_utf8_script_to_utf16(script, script_len);
+ gjs_utf8_script_to_utf16(script_, script_len);
// COMPAT: This could use JS::SourceText<mozilla::Utf8Unit> directly,
// but that messes up code coverage. See bug
// https://bugzilla.mozilla.org/show_bug.cgi?id=1404784
@@ -113,13 +114,21 @@ class GjsScriptModule {
}
JS::CompileOptions options(cx);
- options.setFileAndLine(filename, 1);
+ options.setFileAndLine(filename, 1)
+ .setNonSyntacticScope(true);
JS::RootedObject priv(cx, build_private(cx, uri));
- options.setPrivateValue(JS::ObjectValue(*priv));
+ if (!priv)
+ return false;
+
+ JS::RootedScript script(cx);
+ script.set(JS::Compile(cx, options, buf));
+ if (!script)
+ return false;
+ JS::SetScriptPrivate(script, JS::ObjectValue(*priv));
JS::RootedValue ignored_retval(cx);
- if (!JS::Evaluate(cx, scope_chain, options, buf, &ignored_retval))
+ if (!JS_ExecuteScript(cx, scope_chain, script, &ignored_retval))
return false;
GjsContextPrivate* gjs = GjsContextPrivate::from_cx(cx);
@@ -221,7 +230,8 @@ class GjsScriptModule {
public:
/*
- * Creates a JS object to pass to JS::CompileOptions as a script's private.
+ * Creates a JS object to pass to JS::SetScriptPrivate as a script's
+ * private.
*/
GJS_JSAPI_RETURN_CONVENTION
static JSObject* build_private(JSContext* cx, const char* script_uri) {
@@ -492,7 +502,7 @@ bool gjs_populate_module_meta(JSContext* cx, JS::HandleValue private_ref,
* @returns whether an error occurred while resolving the specifier.
*/
JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue importingModulePriv,
- JS::HandleString specifier) {
+ JS::HandleObject moduleRequest) {
g_assert((gjs_global_is_type(cx, GjsGlobalType::DEFAULT) ||
gjs_global_is_type(cx, GjsGlobalType::INTERNAL)) &&
"gjs_module_resolve can only be called from module-enabled "
@@ -500,6 +510,8 @@ JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue importingModulePriv,
g_assert(importingModulePriv.isObject() &&
"the importing module can't be null, don't add import to the "
"bootstrap script");
+ JS::RootedString specifier(
+ cx, JS::GetModuleRequestSpecifier(cx, moduleRequest));
JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
JS::RootedValue v_loader(
@@ -528,29 +540,31 @@ JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue importingModulePriv,
// Can fail in JS::FinishDynamicModuleImport(), but will assert if anything
// fails in fetching the stashed values, since that would be a serious GJS bug.
GJS_JSAPI_RETURN_CONVENTION
-static bool finish_import(JSContext* cx, const JS::CallArgs& args) {
+static bool finish_import(JSContext* cx, JS::DynamicImportStatus status,
+ const JS::CallArgs& args) {
JS::Value callback_priv = js::GetFunctionNativeReserved(&args.callee(), 0);
g_assert(callback_priv.isObject() && "Wrong private value");
JS::RootedObject callback_data(cx, &callback_priv.toObject());
JS::RootedValue importing_module_priv(cx);
- JS::RootedValue v_specifier(cx);
+ JS::RootedValue v_module_request(cx);
JS::RootedValue v_internal_promise(cx);
bool ok GJS_USED_ASSERT =
JS_GetProperty(cx, callback_data, "priv", &importing_module_priv) &&
JS_GetProperty(cx, callback_data, "promise", &v_internal_promise) &&
- JS_GetProperty(cx, callback_data, "specifier", &v_specifier);
+ JS_GetProperty(cx, callback_data, "moduleRequest", &v_module_request);
g_assert(ok && "Wrong properties on private value");
- g_assert(v_specifier.isString() && "Wrong type for specifier");
+ g_assert(v_module_request.isObject() && "Wrong type for module request");
g_assert(v_internal_promise.isObject() && "Wrong type for promise");
- JS::RootedString specifier(cx, v_specifier.toString());
+ JS::RootedObject moduleRequest(cx, &v_module_request.toObject());
JS::RootedObject internal_promise(cx, &v_internal_promise.toObject());
args.rval().setUndefined();
- return JS::FinishDynamicModuleImport(cx, importing_module_priv, specifier,
- internal_promise);
+
+ return JS::FinishDynamicModuleImport_NoTLA(
+ cx, status, importing_module_priv, moduleRequest, internal_promise);
}
// Failing a JSAPI function may result either in an exception pending on the
@@ -560,7 +574,7 @@ static bool finish_import(JSContext* cx, const JS::CallArgs& args) {
GJS_JSAPI_RETURN_CONVENTION
static bool fail_import(JSContext* cx, const JS::CallArgs& args) {
if (JS_IsExceptionPending(cx))
- return finish_import(cx, args);
+ return finish_import(cx, JS::DynamicImportStatus::Failed, args);
return false;
}
@@ -575,7 +589,7 @@ static bool import_rejected(JSContext* cx, unsigned argc, JS::Value* vp) {
JS_SetPendingException(cx, args.get(0),
JS::ExceptionStackBehavior::DoNotCapture);
- return finish_import(cx, args);
+ return finish_import(cx, JS::DynamicImportStatus::Failed, args);
}
GJS_JSAPI_RETURN_CONVENTION
@@ -590,15 +604,17 @@ static bool import_resolved(JSContext* cx, unsigned argc, JS::Value* vp) {
g_assert(args[0].isObject());
JS::RootedObject module(cx, &args[0].toObject());
- if (!JS::ModuleInstantiate(cx, module) || !JS::ModuleEvaluate(cx, module))
+ JS::RootedValue ignore(cx);
+ if (!JS::ModuleInstantiate(cx, module) ||
+ !JS::ModuleEvaluate(cx, module, &ignore))
return fail_import(cx, args);
- return finish_import(cx, args);
+ return finish_import(cx, JS::DynamicImportStatus::Ok, args);
}
bool gjs_dynamic_module_resolve(JSContext* cx,
JS::HandleValue importing_module_priv,
- JS::HandleString specifier,
+ JS::Handle<JSObject*> moduleRequest,
JS::HandleObject internal_promise) {
g_assert(gjs_global_is_type(cx, GjsGlobalType::DEFAULT) &&
"gjs_dynamic_module_resolve can only be called from the default "
@@ -611,10 +627,12 @@ bool gjs_dynamic_module_resolve(JSContext* cx,
cx, gjs_get_global_slot(global, GjsGlobalSlot::MODULE_LOADER));
g_assert(v_loader.isObject());
JS::RootedObject loader(cx, &v_loader.toObject());
+ JS::RootedString specifier(
+ cx, JS::GetModuleRequestSpecifier(cx, moduleRequest));
JS::RootedObject callback_data(cx, JS_NewPlainObject(cx));
if (!callback_data ||
- !JS_DefineProperty(cx, callback_data, "specifier", specifier,
+ !JS_DefineProperty(cx, callback_data, "moduleRequest", moduleRequest,
JSPROP_PERMANENT) ||
!JS_DefineProperty(cx, callback_data, "promise", internal_promise,
JSPROP_PERMANENT) ||
@@ -634,8 +652,9 @@ bool gjs_dynamic_module_resolve(JSContext* cx,
JS::RootedValue result(cx);
if (!JS::Call(cx, loader, "moduleResolveAsyncHook", args, &result))
- return JS::FinishDynamicModuleImport(cx, importing_module_priv,
- specifier, internal_promise);
+ return JS::FinishDynamicModuleImport_NoTLA(
+ cx, JS::DynamicImportStatus::Failed, importing_module_priv,
+ moduleRequest, internal_promise);
JS::RootedObject resolved(
cx, JS_GetFunctionObject(js::NewFunctionWithReserved(
diff --git a/gjs/module.h b/gjs/module.h
index 39d550b4..f50d6eda 100644
--- a/gjs/module.h
+++ b/gjs/module.h
@@ -35,8 +35,8 @@ JSObject* gjs_module_load(JSContext* cx, const char* identifier,
const char* uri);
GJS_JSAPI_RETURN_CONVENTION
-JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue mod_val,
- JS::HandleString specifier);
+JSObject* gjs_module_resolve(JSContext* cx, JS::HandleValue importingModulePriv,
+ JS::HandleObject moduleRequest);
GJS_JSAPI_RETURN_CONVENTION
bool gjs_populate_module_meta(JSContext* cx, JS::HandleValue private_ref,
@@ -45,7 +45,7 @@ bool gjs_populate_module_meta(JSContext* cx, JS::HandleValue private_ref,
GJS_JSAPI_RETURN_CONVENTION
bool gjs_dynamic_module_resolve(JSContext* cx,
JS::HandleValue importing_module_priv,
- JS::HandleString specifier,
+ JS::Handle<JSObject*> moduleRequest,
JS::HandleObject internal_promise);
#endif // GJS_MODULE_H_
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]