[gjs/mozjs91: 8/17] Adapt to new module and script APIs




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]