diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp index 93d2ce11323b..1a0348e03634 100644 --- a/dom/script/ScriptLoader.cpp +++ b/dom/script/ScriptLoader.cpp @@ -769,25 +769,20 @@ ScriptLoader::StartFetchingModuleAndDependencies(ModuleLoadRequest* aParent, } // 8.1.3.8.1 HostResolveImportedModule(referencingModule, specifier) -bool -HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp) +JSObject* +HostResolveImportedModule(JSContext* aCx, JS::Handle aModule, + JS::Handle aSpecifier) { - - MOZ_ASSERT(argc == 2); - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - JS::Rooted module(aCx, &args[0].toObject()); - JS::Rooted specifier(aCx, args[1].toString()); - // Let referencing module script be referencingModule.[[HostDefined]]. - JS::Value value = JS::GetModuleHostDefinedField(module); + JS::Value value = JS::GetModuleHostDefinedField(aModule); auto script = static_cast(value.toPrivate()); - MOZ_ASSERT(script->ModuleRecord() == module); + MOZ_ASSERT(script->ModuleRecord() == aModule); // Let url be the result of resolving a module specifier given referencing // module script and specifier. nsAutoJSString string; - if (!string.init(aCx, specifier)) { - return false; + if (!string.init(aCx, aSpecifier)) { + return nullptr; } nsCOMPtr uri = ResolveModuleSpecifier(script, string); @@ -802,27 +797,20 @@ HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp) MOZ_ASSERT(ms, "Resolved module not found in module map"); MOZ_ASSERT(!ms->HasParseError()); + MOZ_ASSERT(ms->ModuleRecord()); - *vp = JS::ObjectValue(*ms->ModuleRecord()); - return true; + return ms->ModuleRecord(); } -static nsresult +static void EnsureModuleResolveHook(JSContext* aCx) { - if (JS::GetModuleResolveHook(aCx)) { - return NS_OK; + JSRuntime* rt = JS_GetRuntime(aCx); + if (JS::GetModuleResolveHook(rt)) { + return; } - JS::Rooted func(aCx); - func = JS_NewFunction(aCx, HostResolveImportedModule, 2, 0, - "HostResolveImportedModule"); - if (!func) { - return NS_ERROR_FAILURE; - } - - JS::SetModuleResolveHook(aCx, func); - return NS_OK; + JS::SetModuleResolveHook(rt, HostResolveImportedModule); } void @@ -944,8 +932,7 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest) return false; } - nsresult rv = EnsureModuleResolveHook(jsapi.cx()); - NS_ENSURE_SUCCESS(rv, false); + EnsureModuleResolveHook(jsapi.cx()); JS::Rooted module(jsapi.cx(), moduleScript->ModuleRecord()); bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module)); @@ -2231,8 +2218,7 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest) // currentScript is set to null for modules. AutoCurrentScriptUpdater scriptUpdater(this, nullptr); - rv = EnsureModuleResolveHook(cx); - NS_ENSURE_SUCCESS(rv, rv); + EnsureModuleResolveHook(cx); ModuleLoadRequest* request = aRequest->AsModuleRequest(); MOZ_ASSERT(request->mModuleScript); diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h index 0edbc947fb2c..d015c31c1573 100644 --- a/dom/script/ScriptLoader.h +++ b/dom/script/ScriptLoader.h @@ -505,8 +505,9 @@ private: RefPtr WaitForModuleFetch(nsIURI* aURL); ModuleScript* GetFetchedModule(nsIURI* aURL) const; - friend bool - HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp); + friend JSObject* + HostResolveImportedModule(JSContext* aCx, JS::Handle aModule, + JS::Handle aSpecifier); // Returns wether we should save the bytecode of this script after the // execution of the script. diff --git a/js/public/Class.h b/js/public/Class.h index 7420fe1b2162..a4f9d86ab833 100644 --- a/js/public/Class.h +++ b/js/public/Class.h @@ -838,7 +838,7 @@ static const uint32_t JSCLASS_FOREGROUND_FINALIZE = 1 << (JSCLASS_HIGH_FLAGS // application. static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5; static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT = - JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 37; + JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 36; #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \ (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n))) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c785c660908c..72e8fac562fa 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4939,21 +4939,18 @@ JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, return ::Evaluate(cx, optionsArg, filename, rval); } -JS_PUBLIC_API(JSFunction*) -JS::GetModuleResolveHook(JSContext* cx) +JS_PUBLIC_API(JS::ModuleResolveHook) +JS::GetModuleResolveHook(JSRuntime* rt) { AssertHeapIsIdle(); - CHECK_REQUEST(cx); - return cx->global()->moduleResolveHook(); + return rt->moduleResolveHook; } JS_PUBLIC_API(void) -JS::SetModuleResolveHook(JSContext* cx, HandleFunction func) +JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func) { AssertHeapIsIdle(); - CHECK_REQUEST(cx); - assertSameCompartment(cx, func); - cx->global()->setModuleResolveHook(func); + rt->moduleResolveHook = func; } JS_PUBLIC_API(bool) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index e0df398b8a75..efe140737f65 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -4141,17 +4141,19 @@ extern JS_PUBLIC_API(bool) Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename, JS::MutableHandleValue rval); -/** - * Get the HostResolveImportedModule hook for a global. - */ -extern JS_PUBLIC_API(JSFunction*) -GetModuleResolveHook(JSContext* cx); +using ModuleResolveHook = JSObject* (*)(JSContext*, HandleObject, HandleString); /** - * Set the HostResolveImportedModule hook for a global to the given function. + * Get the HostResolveImportedModule hook for the runtime. + */ +extern JS_PUBLIC_API(ModuleResolveHook) +GetModuleResolveHook(JSRuntime* rt); + +/** + * Set the HostResolveImportedModule hook for the runtime to the given function. */ extern JS_PUBLIC_API(void) -SetModuleResolveHook(JSContext* cx, JS::HandleFunction func); +SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func); /** * Parse the given source buffer as a module in the scope of the current global diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 0f4cdefa3f88..d4015847e561 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -610,7 +610,8 @@ ShellContext::ShellContext(JSContext* cx) readLineBufPos(0), errFilePtr(nullptr), outFilePtr(nullptr), - offThreadMonitor(mutexid::ShellOffThreadState) + offThreadMonitor(mutexid::ShellOffThreadState), + moduleResolveHook(cx) {} ShellContext::~ShellContext() @@ -868,6 +869,7 @@ RunBinAST(JSContext* cx, const char* filename, FILE* file) static bool InitModuleLoader(JSContext* cx) { + // Decompress and evaluate the embedded module loader source to initialize // the module loader for the current compartment. @@ -4280,13 +4282,34 @@ SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp) return false; } - RootedFunction hook(cx, &args[0].toObject().as()); - Rooted global(cx, cx->global()); - global->setModuleResolveHook(hook); + ShellContext* sc = GetShellContext(cx); + sc->moduleResolveHook = &args[0].toObject().as(); + args.rval().setUndefined(); return true; } +static JSObject* +CallModuleResolveHook(JSContext* cx, HandleObject module, HandleString specifier) +{ + ShellContext* sc = GetShellContext(cx); + + JS::AutoValueArray<2> args(cx); + args[0].setObject(*module); + args[1].setString(specifier); + + RootedValue result(cx); + if (!JS_CallFunction(cx, nullptr, sc->moduleResolveHook, args, &result)) + return nullptr; + + if (!result.isObject() || !result.toObject().is()) { + JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object"); + return nullptr; + } + + return &result.toObject(); +} + static bool GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp) { @@ -9298,6 +9321,8 @@ main(int argc, char** argv, char** envp) js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback); + JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook); + result = Shell(cx, &op, envp); #ifdef DEBUG diff --git a/js/src/shell/jsshell.h b/js/src/shell/jsshell.h index 0cab342c77d6..f0d6946ed28f 100644 --- a/js/src/shell/jsshell.h +++ b/js/src/shell/jsshell.h @@ -181,6 +181,7 @@ struct ShellContext js::Monitor offThreadMonitor; Vector offThreadJobs; + JS::PersistentRootedFunction moduleResolveHook; }; extern ShellContext* diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index ef044ffea52f..0b241db296c9 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -105,7 +105,6 @@ class GlobalObject : public NativeObject DEBUGGERS, INTRINSICS, FOR_OF_PIC_CHAIN, - MODULE_RESOLVE_HOOK, WINDOW_PROXY, /* Total reserved-slot count for global objects. */ @@ -821,19 +820,6 @@ class GlobalObject : public NativeObject setReservedSlot(WINDOW_PROXY, ObjectValue(*windowProxy)); } - void setModuleResolveHook(HandleFunction hook) { - MOZ_ASSERT(hook); - setSlot(MODULE_RESOLVE_HOOK, ObjectValue(*hook)); - } - - JSFunction* moduleResolveHook() { - Value value = getSlotRef(MODULE_RESOLVE_HOOK); - if (value.isUndefined()) - return nullptr; - - return &value.toObject().as(); - } - // A class used in place of a prototype during off-thread parsing. struct OffThreadPlaceholderObject : public NativeObject { diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 60bfca3ed63e..e34e66da6d0e 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -174,7 +174,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime) performanceMonitoring_(), stackFormat_(parentRuntime ? js::StackFormat::Default : js::StackFormat::SpiderMonkey), - wasmInstances(mutexid::WasmRuntimeInstances) + wasmInstances(mutexid::WasmRuntimeInstances), + moduleResolveHook() { JS_COUNT_CTOR(JSRuntime); liveRuntimesCount++; diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index c1ab328577b4..9d9deb5c51b0 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -937,6 +937,9 @@ struct JSRuntime : public js::MallocProvider // threads for purposes of wasm::InterruptRunningCode(). js::ExclusiveData wasmInstances; + // The implementation-defined abstract operation HostResolveImportedModule. + js::MainThreadData moduleResolveHook; + public: #if defined(JS_BUILD_BINAST) js::BinaryASTSupport& binast() { diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 3db389d4ccca..09d9473640e6 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2146,25 +2146,26 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 2); - MOZ_ASSERT(args[0].toObject().is()); - MOZ_ASSERT(args[1].isString()); + RootedModuleObject module(cx, &args[0].toObject().as()); + RootedString specifier(cx, args[1].toString()); - RootedFunction moduleResolveHook(cx, cx->global()->moduleResolveHook()); + JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook; if (!moduleResolveHook) { JS_ReportErrorASCII(cx, "Module resolve hook not set"); return false; } - RootedValue result(cx); - if (!JS_CallFunction(cx, nullptr, moduleResolveHook, args, &result)) + RootedObject result(cx); + result = moduleResolveHook(cx, module, specifier); + if (!result) return false; - if (!result.isObject() || !result.toObject().is()) { + if (!result->is()) { JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object"); return false; } - args.rval().set(result); + args.rval().setObject(*result); return true; }