mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-23 23:57:31 +09:00
Issue #1691 - Part 5b: Stop modules from entraining the top-level JSScript. https://bugzilla.mozilla.org/show_bug.cgi?id=1489477
(cherry picked from commit 6ce0af856186e65fb4987daf4e06dc68fb3f7483)
This commit is contained in:
parent
c965fbdd10
commit
5c09a3b3cc
4 changed files with 71 additions and 21 deletions
|
|
@ -835,18 +835,22 @@ ModuleObject::fixEnvironmentsAfterCompartmentMerge()
|
||||||
AssertModuleScopesMatch(this);
|
AssertModuleScopesMatch(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
JSScript*
|
||||||
ModuleObject::hasScript() const
|
ModuleObject::maybeScript() const
|
||||||
{
|
{
|
||||||
// When modules are parsed via the Reflect.parse() API, the module object
|
Value value = getReservedSlot(ScriptSlot);
|
||||||
// doesn't have a script.
|
if (value.isUndefined())
|
||||||
return !getReservedSlot(ScriptSlot).isUndefined();
|
return nullptr;
|
||||||
|
|
||||||
|
return value.toGCThing()->as<JSScript>();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSScript*
|
JSScript*
|
||||||
ModuleObject::script() const
|
ModuleObject::script() const
|
||||||
{
|
{
|
||||||
return static_cast<JSScript*>(getReservedSlot(ScriptSlot).toPrivate());
|
JSScript* ptr = maybeScript();
|
||||||
|
MOZ_RELEASE_ASSERT(ptr);
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
@ -906,8 +910,8 @@ ModuleObject::enclosingScope() const
|
||||||
ModuleObject::trace(JSTracer* trc, JSObject* obj)
|
ModuleObject::trace(JSTracer* trc, JSObject* obj)
|
||||||
{
|
{
|
||||||
ModuleObject& module = obj->as<ModuleObject>();
|
ModuleObject& module = obj->as<ModuleObject>();
|
||||||
if (module.hasScript()) {
|
JSScript* script = module.maybeScript();
|
||||||
JSScript* script = module.script();
|
if (script) {
|
||||||
TraceManuallyBarrieredEdge(trc, &script, "Module script");
|
TraceManuallyBarrieredEdge(trc, &script, "Module script");
|
||||||
module.setReservedSlot(ScriptSlot, PrivateValue(script));
|
module.setReservedSlot(ScriptSlot, PrivateValue(script));
|
||||||
}
|
}
|
||||||
|
|
@ -976,6 +980,11 @@ ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RootedScript script(cx, self->script());
|
RootedScript script(cx, self->script());
|
||||||
|
|
||||||
|
// The top-level script if a module is only ever executed once. Clear the
|
||||||
|
// reference to prevent us keeping this alive unnecessarily.
|
||||||
|
self->setReservedSlot(ScriptSlot, UndefinedValue());
|
||||||
|
|
||||||
RootedModuleEnvironmentObject scope(cx, self->environment());
|
RootedModuleEnvironmentObject scope(cx, self->environment());
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
JS_ReportErrorASCII(cx, "Module declarations have not yet been instantiated");
|
JS_ReportErrorASCII(cx, "Module declarations have not yet been instantiated");
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,7 @@ class ModuleObject : public NativeObject
|
||||||
#endif
|
#endif
|
||||||
void fixEnvironmentsAfterCompartmentMerge();
|
void fixEnvironmentsAfterCompartmentMerge();
|
||||||
|
|
||||||
|
JSScript* maybeScript() const;
|
||||||
JSScript* script() const;
|
JSScript* script() const;
|
||||||
Scope* enclosingScope() const;
|
Scope* enclosingScope() const;
|
||||||
ModuleEnvironmentObject& initialEnvironment() const;
|
ModuleEnvironmentObject& initialEnvironment() const;
|
||||||
|
|
@ -312,7 +313,6 @@ class ModuleObject : public NativeObject
|
||||||
static void trace(JSTracer* trc, JSObject* obj);
|
static void trace(JSTracer* trc, JSObject* obj);
|
||||||
static void finalize(js::FreeOp* fop, JSObject* obj);
|
static void finalize(js::FreeOp* fop, JSObject* obj);
|
||||||
|
|
||||||
bool hasScript() const;
|
|
||||||
bool hasImportBindings() const;
|
bool hasImportBindings() const;
|
||||||
FunctionDeclarationVector* functionDeclarations();
|
FunctionDeclarationVector* functionDeclarations();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,18 @@ Reflect.Loader = new class {
|
||||||
module.declarationInstantiation();
|
module.declarationInstantiation();
|
||||||
return module.evaluation();
|
return module.evaluation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
populateImportMeta(module, metaObject) {
|
||||||
|
// For the shell, use the script's filename as the base URL.
|
||||||
|
|
||||||
|
let path;
|
||||||
|
if (ReflectApply(MapPrototypeHas, this.modulePaths, [module])) {
|
||||||
|
path = ReflectApply(MapPrototypeGet, this.modulePaths, [module]);
|
||||||
|
} else {
|
||||||
|
path = "(unknown)";
|
||||||
|
}
|
||||||
|
metaObject.url = path;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setModuleResolveHook((referencingInfo, requestName) => {
|
setModuleResolveHook((referencingInfo, requestName) => {
|
||||||
|
|
|
||||||
|
|
@ -2830,7 +2830,7 @@ DisassembleToSprinter(JSContext* cx, unsigned argc, Value* vp, Sprinter* sprinte
|
||||||
RootedScript script(cx);
|
RootedScript script(cx);
|
||||||
RootedValue value(cx, p.argv[i]);
|
RootedValue value(cx, p.argv[i]);
|
||||||
if (value.isObject() && value.toObject().is<ModuleObject>())
|
if (value.isObject() && value.toObject().is<ModuleObject>())
|
||||||
script = value.toObject().as<ModuleObject>().script();
|
script = value.toObject().as<ModuleObject>().maybeScript();
|
||||||
else
|
else
|
||||||
script = ValueToScript(cx, value, fun.address());
|
script = ValueToScript(cx, value, fun.address());
|
||||||
if (!script)
|
if (!script)
|
||||||
|
|
@ -4132,23 +4132,48 @@ ShellGetModulePrivate(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
|
static bool
|
||||||
|
SetModuleMetadataHook(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
// For the shell, just use the script's filename as the base URL.
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
RootedScript script(cx, module->as<ModuleObject>().script());
|
if (args.length() != 1) {
|
||||||
const char* filename = script->scriptSource()->filename();
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||||
MOZ_ASSERT(filename);
|
"setModuleMetadataHook", "0", "s");
|
||||||
|
|
||||||
RootedString url(cx, NewStringCopyZ<CanGC>(cx, filename));
|
|
||||||
if (!url)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!JS_DefineProperty(cx, metaObject, "url", url, JSPROP_ENUMERATE))
|
if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
|
||||||
|
const char* typeName = InformalValueTypeName(args[0]);
|
||||||
|
JS_ReportErrorASCII(cx, "expected hook function, got %s", typeName);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<GlobalObject*> global = cx->global();
|
||||||
|
global->setReservedSlot(GlobalAppSlotModuleMetadataHook, args[0]);
|
||||||
|
|
||||||
|
args.rval().setUndefined();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
CallModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
|
||||||
|
{
|
||||||
|
Handle<GlobalObject*> global = cx->global();
|
||||||
|
RootedValue hookValue(cx, global->getReservedSlot(GlobalAppSlotModuleMetadataHook));
|
||||||
|
if (hookValue.isUndefined()) {
|
||||||
|
JS_ReportErrorASCII(cx, "Module metadata hook not set");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(hookValue.toObject().is<JSFunction>());
|
||||||
|
|
||||||
|
JS::AutoValueArray<2> args(cx);
|
||||||
|
args[0].setObject(*module);
|
||||||
|
args[1].setObject(*metaObject);
|
||||||
|
|
||||||
|
RootedValue dummy(cx);
|
||||||
|
return JS_CallFunctionValue(cx, nullptr, hookValue, args, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
SetModuleDynamicImportHook(JSContext* cx, unsigned argc, Value* vp)
|
SetModuleDynamicImportHook(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -5616,7 +5641,11 @@ DumpScopeChain(JSContext* cx, unsigned argc, Value* vp)
|
||||||
}
|
}
|
||||||
script = JSFunction::getOrCreateScript(cx, fun);
|
script = JSFunction::getOrCreateScript(cx, fun);
|
||||||
} else {
|
} else {
|
||||||
script = obj->as<ModuleObject>().script();
|
script = obj->as<ModuleObject>().maybeScript();
|
||||||
|
if (!script) {
|
||||||
|
JS_ReportErrorASCII(cx, "module does not have an associated script");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script->bodyScope()->dump();
|
script->bodyScope()->dump();
|
||||||
|
|
@ -7451,7 +7480,7 @@ ProcessArgs(JSContext* cx, OptionParser* op)
|
||||||
if (const char* path = op->getStringOption("module-load-path"))
|
if (const char* path = op->getStringOption("module-load-path"))
|
||||||
moduleLoadPath = path;
|
moduleLoadPath = path;
|
||||||
|
|
||||||
if (!modulePaths.empty() && !InitModuleLoader(cx))
|
if (!InitModuleLoader(cx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (!filePaths.empty() || !codeChunks.empty() || !modulePaths.empty()) {
|
while (!filePaths.empty() || !codeChunks.empty() || !modulePaths.empty()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue