1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-26 13:58:49 +00:00

Issue #618 - Simplify module resolve hook to be a function pointer

This is an ahead-of time port to try and address #1624.
This is based on BZ 1461751 and Jon Coppeard's work in it.
This commit is contained in:
Moonchild
2020-08-06 18:31:36 +00:00
committed by Roy Tam
parent 976239c8d0
commit 34db761758
10 changed files with 78 additions and 76 deletions
+16 -29
View File
@@ -787,24 +787,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<JSObject*> aModule,
JS::Handle<JSString*> aSpecifier)
{
MOZ_ASSERT(argc == 2);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> module(aCx, &args[0].toObject());
JS::Rooted<JSString*> 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<ModuleScript*>(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<nsIURI> uri = ResolveModuleSpecifier(script, string);
@@ -820,27 +816,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<JSFunction*> 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
@@ -928,8 +917,7 @@ ScriptLoader::InstantiateModuleTree(ModuleLoadRequest* aRequest)
return false;
}
nsresult rv = EnsureModuleResolveHook(jsapi.cx());
NS_ENSURE_SUCCESS(rv, false);
EnsureModuleResolveHook(jsapi.cx());
JS::Rooted<JSObject*> module(jsapi.cx(), moduleScript->ModuleRecord());
bool ok = NS_SUCCEEDED(nsJSUtils::ModuleInstantiate(jsapi.cx(), module));
@@ -1963,8 +1951,7 @@ ScriptLoader::EvaluateScript(ScriptLoadRequest* aRequest)
}
if (aRequest->IsModuleRequest()) {
rv = EnsureModuleResolveHook(cx);
NS_ENSURE_SUCCESS(rv, rv);
EnsureModuleResolveHook(cx);
ModuleLoadRequest* request = aRequest->AsModuleRequest();
MOZ_ASSERT(request->mModuleScript);
+3 -2
View File
@@ -579,8 +579,9 @@ private:
RefPtr<mozilla::GenericPromise> 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<JSObject*> aModule,
JS::Handle<JSString*> aSpecifier);
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
+1 -1
View File
@@ -779,7 +779,7 @@ struct JSClass {
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 46)
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
+5 -10
View File
@@ -4667,21 +4667,16 @@ 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(cx);
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(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, func);
cx->global()->setModuleResolveHook(func);
rt->moduleResolveHook = func;
}
JS_PUBLIC_API(bool)
+9 -7
View File
@@ -4325,17 +4325,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
+29 -4
View File
@@ -274,6 +274,7 @@ struct ShellContext
JS::PersistentRooted<JobQueue> jobQueue;
ExclusiveData<ShellAsyncTasks> asyncTasks;
bool drainingJobQueue;
JS::PersistentRootedFunction moduleResolveHook;
/*
* Watchdog thread state.
@@ -439,7 +440,8 @@ ShellContext::ShellContext(JSContext* cx)
exitCode(0),
quitting(false),
readLineBufPos(0),
spsProfilingStackSize(0)
spsProfilingStackSize(0),
moduleResolveHook(cx)
{}
static ShellContext*
@@ -4030,13 +4032,34 @@ SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp)
return false;
}
RootedFunction hook(cx, &args[0].toObject().as<JSFunction>());
Rooted<GlobalObject*> global(cx, cx->global());
global->setModuleResolveHook(hook);
ShellContext* sc = GetShellContext(cx);
sc->moduleResolveHook = &args[0].toObject().as<JSFunction>();
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<ModuleObject>()) {
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)
{
@@ -7962,6 +7985,8 @@ main(int argc, char** argv, char** envp)
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
result = Shell(cx, &op, envp);
#ifdef DEBUG
-14
View File
@@ -119,7 +119,6 @@ class GlobalObject : public NativeObject
DEBUGGERS,
INTRINSICS,
FOR_OF_PIC_CHAIN,
MODULE_RESOLVE_HOOK,
WINDOW_PROXY,
GLOBAL_THIS_RESOLVED,
@@ -879,19 +878,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<JSFunction>();
}
// Returns either this global's star-generator function prototype, or null
// if that object was never created. Dodgy; for use only in also-dodgy
// GlobalHelperThreadState::mergeParseTaskCompartment().
+4 -2
View File
@@ -241,8 +241,10 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
lastAnimationTime(0),
performanceMonitoring(thisFromCtor()),
ionLazyLinkListSize_(0),
stackFormat_(parentRuntime ? js::StackFormat::Default
: js::StackFormat::SpiderMonkey)
stackFormat_(parentRuntime ?
js::StackFormat::Default :
js::StackFormat::SpiderMonkey),
moduleResolveHook()
{
setGCStoreBufferPtr(&gc.storeBuffer);
+3
View File
@@ -1294,6 +1294,9 @@ struct JSRuntime : public JS::shadow::Runtime,
// For inherited heap state accessors.
friend class js::gc::AutoTraceSession;
friend class JS::AutoEnterCycleCollection;
// The implementation-defined abstract operation HostResolveImportedModule.
JS::ModuleResolveHook moduleResolveHook;
};
namespace js {
+8 -7
View File
@@ -2026,25 +2026,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<ModuleObject>());
MOZ_ASSERT(args[1].isString());
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
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<ModuleObject>()) {
if (!result->is<ModuleObject>()) {
JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
return false;
}
args.rval().set(result);
args.rval().setObject(*result);
return true;
}