mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 00:05:36 +00:00
Bug 1519140 - Add AddRef/Release hooks for embedding's script or module private value and set this script source object where appropriate r=jandem
This commit is contained in:
parent
42e20bac8f
commit
f731989df0
@ -48,29 +48,40 @@ LoadedScript::LoadedScript(ScriptKind aKind, ScriptFetchOptions* aFetchOptions,
|
||||
LoadedScript::~LoadedScript() { DropJSObjects(this); }
|
||||
|
||||
void LoadedScript::AssociateWithScript(JSScript* aScript) {
|
||||
// Set a JSScript's private value to point to this object and
|
||||
// increment our reference count. This is decremented by
|
||||
// HostFinalizeTopLevelScript() below when the JSScript dies.
|
||||
// Set a JSScript's private value to point to this object. The JS engine will
|
||||
// increment our reference count by calling HostAddRefTopLevelScript(). This
|
||||
// is decremented by HostReleaseTopLevelScript() below when the JSScript dies.
|
||||
|
||||
MOZ_ASSERT(JS::GetScriptPrivate(aScript).isUndefined());
|
||||
JS::SetScriptPrivate(aScript, JS::PrivateValue(this));
|
||||
AddRef();
|
||||
}
|
||||
|
||||
void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate) {
|
||||
// Decrement the reference count of a LoadedScript object that is
|
||||
// pointed to by a dying JSScript. The reference count was
|
||||
// originally incremented by AssociateWithScript() above.
|
||||
|
||||
auto script = static_cast<LoadedScript*>(aPrivate.toPrivate());
|
||||
|
||||
inline void CheckModuleScriptPrivate(LoadedScript* script, const JS::Value& aPrivate) {
|
||||
#ifdef DEBUG
|
||||
if (script->IsModuleScript()) {
|
||||
JSObject* module = script->AsModuleScript()->mModuleRecord.unbarrieredGet();
|
||||
MOZ_ASSERT_IF(module, JS::GetModulePrivate(module) == aPrivate);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void HostAddRefTopLevelScript(const JS::Value& aPrivate) {
|
||||
// Increment the reference count of a LoadedScript object that is now pointed
|
||||
// to by a JSScript. The reference count is decremented by
|
||||
// HostReleaseTopLevelScript() below.
|
||||
|
||||
auto script = static_cast<LoadedScript*>(aPrivate.toPrivate());
|
||||
CheckModuleScriptPrivate(script, aPrivate);
|
||||
script->AddRef();
|
||||
}
|
||||
|
||||
void HostReleaseTopLevelScript(const JS::Value& aPrivate) {
|
||||
// Decrement the reference count of a LoadedScript object that was pointed to
|
||||
// by a JSScript. The reference count was originally incremented by
|
||||
// HostAddRefTopLevelScript() above.
|
||||
|
||||
auto script = static_cast<LoadedScript*>(aPrivate.toPrivate());
|
||||
CheckModuleScriptPrivate(script, aPrivate);
|
||||
script->Release();
|
||||
}
|
||||
|
||||
@ -125,7 +136,6 @@ void ModuleScript::UnlinkModuleRecord() {
|
||||
MOZ_ASSERT(JS::GetModulePrivate(mModuleRecord).toPrivate() == this);
|
||||
JS::SetModulePrivate(mModuleRecord, JS::UndefinedValue());
|
||||
mModuleRecord = nullptr;
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,14 +151,14 @@ void ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord) {
|
||||
|
||||
mModuleRecord = aModuleRecord;
|
||||
|
||||
// Make module's host defined field point to this object and
|
||||
// increment our reference count. This is decremented by
|
||||
// UnlinkModuleRecord() above.
|
||||
// Make module's host defined field point to this object. The JS engine will
|
||||
// increment our reference count by calling HostAddRefTopLevelScript(). This
|
||||
// is decremented when the field is cleared in UnlinkModuleRecord() above or
|
||||
// when the module record dies.
|
||||
MOZ_ASSERT(JS::GetModulePrivate(mModuleRecord).isUndefined());
|
||||
JS::SetModulePrivate(mModuleRecord, JS::PrivateValue(this));
|
||||
|
||||
HoldJSObjects(this);
|
||||
AddRef();
|
||||
}
|
||||
|
||||
void ModuleScript::SetParseError(const JS::Value& aError) {
|
||||
|
@ -19,7 +19,8 @@ namespace dom {
|
||||
|
||||
class ScriptLoader;
|
||||
|
||||
void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate);
|
||||
void HostAddRefTopLevelScript(const JS::Value& aPrivate);
|
||||
void HostReleaseTopLevelScript(const JS::Value& aPrivate);
|
||||
|
||||
class ClassicScript;
|
||||
class ModuleScript;
|
||||
@ -89,7 +90,7 @@ class ModuleScript final : public LoadedScript {
|
||||
|
||||
void UnlinkModuleRecord();
|
||||
|
||||
friend void HostFinalizeTopLevelScript(JSFreeOp*, const JS::Value&);
|
||||
friend void CheckModuleScriptPrivate(LoadedScript*, const JS::Value&);
|
||||
};
|
||||
|
||||
ClassicScript* LoadedScript::AsClassicScript() {
|
||||
|
@ -966,7 +966,9 @@ void ScriptLoader::EnsureModuleHooksInitialized() {
|
||||
|
||||
JS::SetModuleResolveHook(rt, HostResolveImportedModule);
|
||||
JS::SetModuleMetadataHook(rt, HostPopulateImportMeta);
|
||||
JS::SetScriptPrivateFinalizeHook(rt, HostFinalizeTopLevelScript);
|
||||
JS::SetScriptPrivateReferenceHooks(rt,
|
||||
HostAddRefTopLevelScript,
|
||||
HostReleaseTopLevelScript);
|
||||
|
||||
Preferences::RegisterCallbackAndCall(DynamicImportPrefChangedCallback,
|
||||
"javascript.options.dynamicImport",
|
||||
|
@ -145,6 +145,15 @@ class JS_PUBLIC_API TransitiveCompileOptions {
|
||||
virtual JSString* elementAttributeName() const = 0;
|
||||
virtual JSScript* introductionScript() const = 0;
|
||||
|
||||
// For some compilations the spec requires the ScriptOrModule field of the
|
||||
// resulting script to be set to the currently executing script. This can be
|
||||
// achieved by setting this option with setScriptOrModule() below.
|
||||
//
|
||||
// Note that this field doesn't explicitly exist in our implementation;
|
||||
// instead the ScriptSourceObject's private value is set to that associated
|
||||
// with the specified script.
|
||||
virtual JSScript* scriptOrModule() const = 0;
|
||||
|
||||
private:
|
||||
void operator=(const TransitiveCompileOptions&) = delete;
|
||||
};
|
||||
@ -202,9 +211,10 @@ class JS_PUBLIC_API ReadOnlyCompileOptions : public TransitiveCompileOptions {
|
||||
const char* filename() const { return filename_; }
|
||||
const char* introducerFilename() const { return introducerFilename_; }
|
||||
const char16_t* sourceMapURL() const { return sourceMapURL_; }
|
||||
virtual JSObject* element() const override = 0;
|
||||
virtual JSString* elementAttributeName() const override = 0;
|
||||
virtual JSScript* introductionScript() const override = 0;
|
||||
JSObject* element() const override = 0;
|
||||
JSString* elementAttributeName() const override = 0;
|
||||
JSScript* introductionScript() const override = 0;
|
||||
JSScript* scriptOrModule() const override = 0;
|
||||
|
||||
private:
|
||||
void operator=(const ReadOnlyCompileOptions&) = delete;
|
||||
@ -227,6 +237,7 @@ class JS_PUBLIC_API OwningCompileOptions final : public ReadOnlyCompileOptions {
|
||||
PersistentRooted<JSObject*> elementRoot;
|
||||
PersistentRooted<JSString*> elementAttributeNameRoot;
|
||||
PersistentRooted<JSScript*> introductionScriptRoot;
|
||||
PersistentRooted<JSScript*> scriptOrModuleRoot;
|
||||
|
||||
public:
|
||||
// A minimal constructor, for use with OwningCompileOptions::copy.
|
||||
@ -240,6 +251,9 @@ class JS_PUBLIC_API OwningCompileOptions final : public ReadOnlyCompileOptions {
|
||||
JSScript* introductionScript() const override {
|
||||
return introductionScriptRoot;
|
||||
}
|
||||
JSScript* scriptOrModule() const override {
|
||||
return scriptOrModuleRoot;
|
||||
}
|
||||
|
||||
/** Set this to a copy of |rhs|. Return false on OOM. */
|
||||
bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
|
||||
@ -272,6 +286,11 @@ class JS_PUBLIC_API OwningCompileOptions final : public ReadOnlyCompileOptions {
|
||||
return *this;
|
||||
}
|
||||
|
||||
OwningCompileOptions& setScriptOrModule(JSScript* s) {
|
||||
scriptOrModuleRoot = s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OwningCompileOptions& setMutedErrors(bool mute) {
|
||||
mutedErrors_ = mute;
|
||||
return *this;
|
||||
@ -361,6 +380,7 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
Rooted<JSObject*> elementRoot;
|
||||
Rooted<JSString*> elementAttributeNameRoot;
|
||||
Rooted<JSScript*> introductionScriptRoot;
|
||||
Rooted<JSScript*> scriptOrModuleRoot;
|
||||
|
||||
public:
|
||||
explicit CompileOptions(JSContext* cx);
|
||||
@ -369,7 +389,8 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
: ReadOnlyCompileOptions(),
|
||||
elementRoot(cx),
|
||||
elementAttributeNameRoot(cx),
|
||||
introductionScriptRoot(cx) {
|
||||
introductionScriptRoot(cx),
|
||||
scriptOrModuleRoot(cx) {
|
||||
copyPODOptions(rhs);
|
||||
|
||||
filename_ = rhs.filename();
|
||||
@ -378,13 +399,15 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
elementRoot = rhs.element();
|
||||
elementAttributeNameRoot = rhs.elementAttributeName();
|
||||
introductionScriptRoot = rhs.introductionScript();
|
||||
scriptOrModuleRoot = rhs.scriptOrModule();
|
||||
}
|
||||
|
||||
CompileOptions(JSContext* cx, const TransitiveCompileOptions& rhs)
|
||||
: ReadOnlyCompileOptions(),
|
||||
elementRoot(cx),
|
||||
elementAttributeNameRoot(cx),
|
||||
introductionScriptRoot(cx) {
|
||||
introductionScriptRoot(cx),
|
||||
scriptOrModuleRoot(cx) {
|
||||
copyPODTransitiveOptions(rhs);
|
||||
|
||||
filename_ = rhs.filename();
|
||||
@ -393,6 +416,7 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
elementRoot = rhs.element();
|
||||
elementAttributeNameRoot = rhs.elementAttributeName();
|
||||
introductionScriptRoot = rhs.introductionScript();
|
||||
scriptOrModuleRoot = rhs.scriptOrModule();
|
||||
}
|
||||
|
||||
JSObject* element() const override { return elementRoot; }
|
||||
@ -405,6 +429,10 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
return introductionScriptRoot;
|
||||
}
|
||||
|
||||
JSScript* scriptOrModule() const override {
|
||||
return scriptOrModuleRoot;
|
||||
}
|
||||
|
||||
CompileOptions& setFile(const char* f) {
|
||||
filename_ = f;
|
||||
return *this;
|
||||
@ -441,6 +469,11 @@ class MOZ_STACK_CLASS JS_PUBLIC_API CompileOptions final
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompileOptions& setScriptOrModule(JSScript* s) {
|
||||
scriptOrModuleRoot = s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CompileOptions& setMutedErrors(bool mute) {
|
||||
mutedErrors_ = mute;
|
||||
return *this;
|
||||
|
@ -283,7 +283,8 @@ static bool EvalKernel(JSContext* cx, HandleValue v, EvalType evalType,
|
||||
options.setIsRunOnce(true)
|
||||
.setNoScriptRval(false)
|
||||
.setMutedErrors(mutedErrors)
|
||||
.maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc));
|
||||
.maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc))
|
||||
.setScriptOrModule(maybeScript);
|
||||
|
||||
if (introducerFilename) {
|
||||
options.setFileAndLine(filename, 1);
|
||||
@ -310,7 +311,7 @@ static bool EvalKernel(JSContext* cx, HandleValue v, EvalType evalType,
|
||||
}
|
||||
|
||||
frontend::EvalScriptInfo info(cx, options, env, enclosing);
|
||||
JSScript* compiled = frontend::CompileEvalScript(info, srcBuf);
|
||||
RootedScript compiled(cx, frontend::CompileEvalScript(info, srcBuf));
|
||||
if (!compiled) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1679,8 +1679,15 @@ JSObject* js::CallModuleResolveHook(JSContext* cx,
|
||||
}
|
||||
|
||||
JSObject* js::StartDynamicModuleImport(JSContext* cx,
|
||||
HandleValue referencingPrivate,
|
||||
HandleObject referencingScriptSource,
|
||||
HandleValue specifierArg) {
|
||||
RootedValue referencingPrivate(cx);
|
||||
if (referencingScriptSource) {
|
||||
ScriptSourceObject* sso =
|
||||
&UncheckedUnwrap(referencingScriptSource)->as<ScriptSourceObject>();
|
||||
referencingPrivate = sso->canonicalPrivate();
|
||||
}
|
||||
|
||||
RootedObject promiseConstructor(cx, JS::GetPromiseConstructor(cx));
|
||||
if (!promiseConstructor) {
|
||||
return nullptr;
|
||||
|
@ -407,7 +407,7 @@ JSObject* CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate,
|
||||
HandleString specifier);
|
||||
|
||||
JSObject* StartDynamicModuleImport(JSContext* cx,
|
||||
HandleValue referencingPrivate,
|
||||
HandleObject referencingScriptSource,
|
||||
HandleValue specifier);
|
||||
|
||||
bool FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate,
|
||||
|
3
js/src/jit-test/tests/modules/bug-1519140.js
Normal file
3
js/src/jit-test/tests/modules/bug-1519140.js
Normal file
@ -0,0 +1,3 @@
|
||||
// |jit-test| --more-compartments
|
||||
fullcompartmentchecks(true);
|
||||
newGlobal().eval(`import("javascript:")`).catch(() => {});
|
@ -5413,7 +5413,7 @@ bool BaselineCodeGen<Handler>::emit_JSOP_IMPORTMETA() {
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue,
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleObject,
|
||||
HandleValue);
|
||||
static const VMFunction StartDynamicModuleImportInfo =
|
||||
FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
|
||||
@ -5421,15 +5421,14 @@ static const VMFunction StartDynamicModuleImportInfo =
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_DYNAMIC_IMPORT() {
|
||||
RootedValue referencingPrivate(cx,
|
||||
FindScriptOrModulePrivateForScript(script));
|
||||
RootedObject referencingScriptSource(cx, script->sourceObject());
|
||||
|
||||
// Put specifier value in R0.
|
||||
frame.popRegsAndSync(1);
|
||||
|
||||
prepareVMCall();
|
||||
pushArg(R0);
|
||||
pushArg(referencingPrivate);
|
||||
pushArg(ImmGCPtr(referencingScriptSource));
|
||||
if (!callVM(StartDynamicModuleImportInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2982,7 +2982,7 @@ void CodeGenerator::visitModuleMetadata(LModuleMetadata* lir) {
|
||||
callVM(GetOrCreateModuleMetaObjectInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue,
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleObject,
|
||||
HandleValue);
|
||||
static const VMFunction StartDynamicModuleImportInfo =
|
||||
FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
|
||||
@ -2990,7 +2990,7 @@ static const VMFunction StartDynamicModuleImportInfo =
|
||||
|
||||
void CodeGenerator::visitDynamicImport(LDynamicImport* lir) {
|
||||
pushArg(ToValue(lir, LDynamicImport::SpecifierIndex));
|
||||
pushArg(ToValue(lir, LDynamicImport::ReferencingPrivateIndex));
|
||||
pushArg(ImmGCPtr(lir->mir()->referencingScriptSource()));
|
||||
callVM(StartDynamicModuleImportInfo, lir);
|
||||
}
|
||||
|
||||
|
@ -13675,12 +13675,11 @@ AbortReasonOr<Ok> IonBuilder::jsop_importmeta() {
|
||||
}
|
||||
|
||||
AbortReasonOr<Ok> IonBuilder::jsop_dynamic_import() {
|
||||
Value referencingPrivate = FindScriptOrModulePrivateForScript(script());
|
||||
MConstant* ref = constant(referencingPrivate);
|
||||
JSObject* referencingScriptSource = script()->sourceObject();
|
||||
|
||||
MDefinition* specifier = current->pop();
|
||||
|
||||
MDynamicImport* ins = MDynamicImport::New(alloc(), ref, specifier);
|
||||
MDynamicImport* ins = MDynamicImport::New(alloc(), referencingScriptSource, specifier);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins);
|
||||
|
@ -2372,8 +2372,7 @@ void LIRGenerator::visitModuleMetadata(MModuleMetadata* ins) {
|
||||
|
||||
void LIRGenerator::visitDynamicImport(MDynamicImport* ins) {
|
||||
LDynamicImport* lir =
|
||||
new (alloc()) LDynamicImport(useBoxAtStart(ins->referencingPrivate()),
|
||||
useBoxAtStart(ins->specifier()));
|
||||
new (alloc()) LDynamicImport(useBoxAtStart(ins->specifier()));
|
||||
defineReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
@ -6607,18 +6607,26 @@ class MModuleMetadata : public MNullaryInstruction {
|
||||
}
|
||||
};
|
||||
|
||||
class MDynamicImport : public MBinaryInstruction, public BoxInputsPolicy::Data {
|
||||
explicit MDynamicImport(MDefinition* referencingPrivate,
|
||||
class MDynamicImport : public MUnaryInstruction, public BoxInputsPolicy::Data {
|
||||
CompilerObject referencingScriptSource_;
|
||||
|
||||
explicit MDynamicImport(JSObject* referencingScriptSource,
|
||||
MDefinition* specifier)
|
||||
: MBinaryInstruction(classOpcode, referencingPrivate, specifier) {
|
||||
: MUnaryInstruction(classOpcode, specifier),
|
||||
referencingScriptSource_(referencingScriptSource) {
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DynamicImport)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, referencingPrivate))
|
||||
NAMED_OPERANDS((1, specifier))
|
||||
NAMED_OPERANDS((0, specifier))
|
||||
|
||||
JSObject* referencingScriptSource() const { return referencingScriptSource_; }
|
||||
|
||||
bool appendRoots(MRootList& roots) const override {
|
||||
return roots.append(referencingScriptSource_);
|
||||
}
|
||||
};
|
||||
|
||||
struct LambdaFunctionInfo {
|
||||
|
@ -3546,17 +3546,14 @@ class LModuleMetadata : public LCallInstructionHelper<1, 0, 0> {
|
||||
LModuleMetadata() : LCallInstructionHelper(classOpcode) {}
|
||||
};
|
||||
|
||||
class LDynamicImport : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0> {
|
||||
class LDynamicImport : public LCallInstructionHelper<1, BOX_PIECES, 0> {
|
||||
public:
|
||||
LIR_HEADER(DynamicImport)
|
||||
|
||||
static const size_t ReferencingPrivateIndex = 0;
|
||||
static const size_t SpecifierIndex = BOX_PIECES;
|
||||
static const size_t SpecifierIndex = 0;
|
||||
|
||||
explicit LDynamicImport(const LBoxAllocation& referencingPrivate,
|
||||
const LBoxAllocation& specifier)
|
||||
explicit LDynamicImport(const LBoxAllocation& specifier)
|
||||
: LCallInstructionHelper(classOpcode) {
|
||||
setBoxOperand(ReferencingPrivateIndex, referencingPrivate);
|
||||
setBoxOperand(SpecifierIndex, specifier);
|
||||
}
|
||||
|
||||
|
@ -3439,7 +3439,8 @@ JS::OwningCompileOptions::OwningCompileOptions(JSContext* cx)
|
||||
: ReadOnlyCompileOptions(),
|
||||
elementRoot(cx),
|
||||
elementAttributeNameRoot(cx),
|
||||
introductionScriptRoot(cx) {}
|
||||
introductionScriptRoot(cx),
|
||||
scriptOrModuleRoot(cx) {}
|
||||
|
||||
JS::OwningCompileOptions::~OwningCompileOptions() {
|
||||
// OwningCompileOptions always owns these, so these casts are okay.
|
||||
@ -3461,6 +3462,7 @@ bool JS::OwningCompileOptions::copy(JSContext* cx,
|
||||
setElement(rhs.element());
|
||||
setElementAttributeName(rhs.elementAttributeName());
|
||||
setIntroductionScript(rhs.introductionScript());
|
||||
setScriptOrModule(rhs.scriptOrModule());
|
||||
|
||||
return setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
|
||||
setSourceMapURL(cx, rhs.sourceMapURL()) &&
|
||||
@ -3531,7 +3533,8 @@ JS::CompileOptions::CompileOptions(JSContext* cx)
|
||||
: ReadOnlyCompileOptions(),
|
||||
elementRoot(cx),
|
||||
elementAttributeNameRoot(cx),
|
||||
introductionScriptRoot(cx) {
|
||||
introductionScriptRoot(cx),
|
||||
scriptOrModuleRoot(cx) {
|
||||
strictOption = cx->options().strictMode();
|
||||
extraWarningsOption = cx->realm()->behaviors().extraWarnings(cx);
|
||||
isProbablySystemCode = cx->realm()->isProbablySystemCode();
|
||||
@ -3721,7 +3724,8 @@ JS_PUBLIC_API bool JS::CompileModule(JSContext* cx,
|
||||
|
||||
JS_PUBLIC_API void JS::SetModulePrivate(JSObject* module,
|
||||
const JS::Value& value) {
|
||||
module->as<ModuleObject>().scriptSourceObject()->setPrivate(value);
|
||||
JSRuntime* rt = module->zone()->runtimeFromMainThread();
|
||||
module->as<ModuleObject>().scriptSourceObject()->setPrivate(rt, value);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JS::Value JS::GetModulePrivate(JSObject* module) {
|
||||
@ -3730,7 +3734,8 @@ JS_PUBLIC_API JS::Value JS::GetModulePrivate(JSObject* module) {
|
||||
|
||||
JS_PUBLIC_API void JS::SetScriptPrivate(JSScript* script,
|
||||
const JS::Value& value) {
|
||||
script->sourceObject()->setPrivate(value);
|
||||
JSRuntime* rt = script->zone()->runtimeFromMainThread();
|
||||
script->sourceObject()->setPrivate(rt, value);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JS::Value JS::GetScriptPrivate(JSScript* script) {
|
||||
@ -3746,19 +3751,16 @@ JS_PUBLIC_API JS::Value JS::GetScriptedCallerPrivate(JSContext* cx) {
|
||||
return UndefinedValue();
|
||||
}
|
||||
|
||||
return FindScriptOrModulePrivateForScript(iter.script());
|
||||
return iter.script()->sourceObject()->canonicalPrivate();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API JS::ScriptPrivateFinalizeHook JS::GetScriptPrivateFinalizeHook(
|
||||
JSRuntime* rt) {
|
||||
JS_PUBLIC_API void JS::SetScriptPrivateReferenceHooks(
|
||||
JSRuntime* rt,
|
||||
JS::ScriptPrivateReferenceHook addRefHook,
|
||||
JS::ScriptPrivateReferenceHook releaseHook) {
|
||||
AssertHeapIsIdle();
|
||||
return rt->scriptPrivateFinalizeHook;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void JS::SetScriptPrivateFinalizeHook(
|
||||
JSRuntime* rt, JS::ScriptPrivateFinalizeHook func) {
|
||||
AssertHeapIsIdle();
|
||||
rt->scriptPrivateFinalizeHook = func;
|
||||
rt->scriptPrivateAddRefHook = addRefHook;
|
||||
rt->scriptPrivateReleaseHook = releaseHook;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API bool JS::ModuleInstantiate(JSContext* cx,
|
||||
|
@ -2575,24 +2575,19 @@ extern JS_PUBLIC_API JS::Value GetScriptPrivate(JSScript* script);
|
||||
extern JS_PUBLIC_API JS::Value GetScriptedCallerPrivate(JSContext* cx);
|
||||
|
||||
/**
|
||||
* A hook that's called whenever a script or module which has a private value
|
||||
* set with SetScriptPrivate() or SetModulePrivate() is finalized. This can be
|
||||
* used to clean up the private state. The private value is passed as an
|
||||
* argument.
|
||||
* Hooks called when references to a script private value are created or
|
||||
* destroyed. This allows use of a reference counted object as the
|
||||
* script private.
|
||||
*/
|
||||
using ScriptPrivateFinalizeHook = void (*)(JSFreeOp*, const JS::Value&);
|
||||
|
||||
/**
|
||||
* Get the script private finalize hook for the runtime.
|
||||
*/
|
||||
extern JS_PUBLIC_API ScriptPrivateFinalizeHook
|
||||
GetScriptPrivateFinalizeHook(JSRuntime* rt);
|
||||
using ScriptPrivateReferenceHook = void (*)(const JS::Value&);
|
||||
|
||||
/**
|
||||
* Set the script private finalize hook for the runtime to the given function.
|
||||
*/
|
||||
extern JS_PUBLIC_API void SetScriptPrivateFinalizeHook(
|
||||
JSRuntime* rt, ScriptPrivateFinalizeHook func);
|
||||
extern JS_PUBLIC_API void SetScriptPrivateReferenceHooks(
|
||||
JSRuntime* rt,
|
||||
ScriptPrivateReferenceHook addRefHook,
|
||||
ScriptPrivateReferenceHook releaseHook);
|
||||
|
||||
/*
|
||||
* Perform the ModuleInstantiate operation on the given source text module
|
||||
|
@ -3367,23 +3367,6 @@ ModuleObject* js::GetModuleObjectForScript(JSScript* script) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value js::FindScriptOrModulePrivateForScript(JSScript* script) {
|
||||
MOZ_ASSERT(script);
|
||||
ScriptSourceObject* sso = script->sourceObject();
|
||||
while (sso) {
|
||||
Value value = sso->canonicalPrivate();
|
||||
if (!value.isUndefined()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
ScriptSourceObject* parent = sso->unwrappedIntroductionSourceObject();
|
||||
MOZ_ASSERT(parent != sso);
|
||||
sso = parent;
|
||||
}
|
||||
|
||||
return UndefinedValue();
|
||||
}
|
||||
|
||||
bool js::GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx,
|
||||
AbstractFramePtr frame,
|
||||
jsbytecode* pc,
|
||||
|
@ -1149,8 +1149,6 @@ extern bool CreateObjectsForEnvironmentChain(JSContext* cx,
|
||||
|
||||
ModuleObject* GetModuleObjectForScript(JSScript* script);
|
||||
|
||||
Value FindScriptOrModulePrivateForScript(JSScript* script);
|
||||
|
||||
ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
|
||||
|
||||
MOZ_MUST_USE bool GetThisValueForDebuggerMaybeOptimizedOut(
|
||||
|
@ -4259,14 +4259,14 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_CALLER bool Interpret(JSContext* cx,
|
||||
END_CASE(JSOP_IMPORTMETA)
|
||||
|
||||
CASE(JSOP_DYNAMIC_IMPORT) {
|
||||
ReservedRooted<Value> referencingPrivate(&rootValue0);
|
||||
referencingPrivate = FindScriptOrModulePrivateForScript(script);
|
||||
ReservedRooted<JSObject*> referencingScriptSource(&rootObject0);
|
||||
referencingScriptSource = script->sourceObject();
|
||||
|
||||
ReservedRooted<Value> specifier(&rootValue1);
|
||||
POP_COPY_TO(specifier);
|
||||
|
||||
JSObject* promise =
|
||||
StartDynamicModuleImport(cx, referencingPrivate, specifier);
|
||||
StartDynamicModuleImport(cx, referencingScriptSource, specifier);
|
||||
if (!promise) goto error;
|
||||
|
||||
PUSH_OBJECT(*promise);
|
||||
|
@ -1851,7 +1851,8 @@ static bool CreateDynamicFunction(JSContext* cx, const CallArgs& args,
|
||||
.setFileAndLine(filename, 1)
|
||||
.setNoScriptRval(false)
|
||||
.setIntroductionInfo(introducerFilename, introductionType, lineno,
|
||||
maybeScript, pcOffset);
|
||||
maybeScript, pcOffset)
|
||||
.setScriptOrModule(maybeScript);
|
||||
|
||||
StringBuffer sb(cx);
|
||||
|
||||
|
@ -1318,15 +1318,8 @@ void ScriptSourceObject::finalize(FreeOp* fop, JSObject* obj) {
|
||||
ScriptSourceObject* sso = &obj->as<ScriptSourceObject>();
|
||||
sso->source()->decref();
|
||||
|
||||
Value value = sso->canonicalPrivate();
|
||||
if (!value.isUndefined()) {
|
||||
// The embedding may need to dispose of its private data.
|
||||
JS::AutoSuppressGCAnalysis suppressGC;
|
||||
if (JS::ScriptPrivateFinalizeHook hook =
|
||||
fop->runtime()->scriptPrivateFinalizeHook) {
|
||||
hook(fop, value);
|
||||
}
|
||||
}
|
||||
// Clear the private value, calling the release hook if necessary.
|
||||
sso->setPrivate(fop->runtime(), UndefinedValue());
|
||||
}
|
||||
|
||||
void ScriptSourceObject::trace(JSTracer* trc, JSObject* obj) {
|
||||
@ -1382,8 +1375,6 @@ ScriptSourceObject* ScriptSourceObject::createInternal(JSContext* cx,
|
||||
obj->initReservedSlot(ELEMENT_SLOT, MagicValue(JS_GENERIC_MAGIC));
|
||||
obj->initReservedSlot(ELEMENT_PROPERTY_SLOT, MagicValue(JS_GENERIC_MAGIC));
|
||||
obj->initReservedSlot(INTRODUCTION_SCRIPT_SLOT, MagicValue(JS_GENERIC_MAGIC));
|
||||
obj->initReservedSlot(INTRODUCTION_SOURCE_OBJECT_SLOT,
|
||||
MagicValue(JS_GENERIC_MAGIC));
|
||||
|
||||
return obj;
|
||||
}
|
||||
@ -1422,8 +1413,6 @@ ScriptSourceObject* ScriptSourceObject::unwrappedCanonical() const {
|
||||
source->getReservedSlot(ELEMENT_PROPERTY_SLOT).isMagic(JS_GENERIC_MAGIC));
|
||||
MOZ_ASSERT(source->getReservedSlot(INTRODUCTION_SCRIPT_SLOT)
|
||||
.isMagic(JS_GENERIC_MAGIC));
|
||||
MOZ_ASSERT(source->getReservedSlot(INTRODUCTION_SOURCE_OBJECT_SLOT)
|
||||
.isMagic(JS_GENERIC_MAGIC));
|
||||
|
||||
RootedObject element(cx, options.element());
|
||||
RootedString elementAttributeName(cx, options.elementAttributeName());
|
||||
@ -1435,19 +1424,24 @@ ScriptSourceObject* ScriptSourceObject::unwrappedCanonical() const {
|
||||
// introduction script and ScriptSourceObject are in different compartments,
|
||||
// we would be creating a cross-compartment script reference, which is
|
||||
// forbidden. We can still store a CCW to the script source object though.
|
||||
RootedValue introdutionScript(cx);
|
||||
RootedValue introdutionSource(cx);
|
||||
if (options.introductionScript()) {
|
||||
if (options.introductionScript()->compartment() == cx->compartment()) {
|
||||
introdutionScript.setPrivateGCThing(options.introductionScript());
|
||||
RootedValue introductionScript(cx);
|
||||
if (JSScript* script = options.introductionScript()) {
|
||||
if (script->compartment() == cx->compartment()) {
|
||||
introductionScript.setPrivateGCThing(options.introductionScript());
|
||||
}
|
||||
introdutionSource.setObject(*options.introductionScript()->sourceObject());
|
||||
if (!cx->compartment()->wrap(cx, &introdutionSource)) {
|
||||
}
|
||||
source->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, introductionScript);
|
||||
|
||||
// Set the private value to that of the script or module that this source is
|
||||
// part of, if any.
|
||||
RootedValue privateValue(cx);
|
||||
if (JSScript* script = options.scriptOrModule()) {
|
||||
privateValue = script->sourceObject()->canonicalPrivate();
|
||||
if (!JS_WrapValue(cx, &privateValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
source->setReservedSlot(INTRODUCTION_SCRIPT_SLOT, introdutionScript);
|
||||
source->setReservedSlot(INTRODUCTION_SOURCE_OBJECT_SLOT, introdutionSource);
|
||||
source->setPrivate(cx->runtime(), privateValue);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1476,6 +1470,25 @@ ScriptSourceObject* ScriptSourceObject::unwrappedCanonical() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptSourceObject::setPrivate(JSRuntime* rt, const Value& value) {
|
||||
// Update the private value, calling addRef/release hooks if necessary
|
||||
// to allow the embedding to maintain a reference count for the
|
||||
// private data.
|
||||
JS::AutoSuppressGCAnalysis nogc;
|
||||
Value prevValue = getReservedSlot(PRIVATE_SLOT);
|
||||
if (!prevValue.isUndefined()) {
|
||||
if (auto releaseHook = rt->scriptPrivateReleaseHook) {
|
||||
releaseHook(prevValue);
|
||||
}
|
||||
}
|
||||
setReservedSlot(PRIVATE_SLOT, value);
|
||||
if (!value.isUndefined()) {
|
||||
if (auto addRefHook = rt->scriptPrivateAddRefHook) {
|
||||
addRefHook(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool JSScript::loadSource(JSContext* cx, ScriptSource* ss,
|
||||
bool* worked) {
|
||||
MOZ_ASSERT(!ss->hasSourceText());
|
||||
|
@ -1189,19 +1189,8 @@ class ScriptSourceObject : public NativeObject {
|
||||
}
|
||||
return value.toGCThing()->as<JSScript>();
|
||||
}
|
||||
ScriptSourceObject* unwrappedIntroductionSourceObject() const {
|
||||
Value value =
|
||||
unwrappedCanonical()->getReservedSlot(INTRODUCTION_SOURCE_OBJECT_SLOT);
|
||||
if (value.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &UncheckedUnwrap(&value.toObject())->as<ScriptSourceObject>();
|
||||
}
|
||||
|
||||
void setPrivate(const Value& value) {
|
||||
MOZ_ASSERT(isCanonical());
|
||||
setReservedSlot(PRIVATE_SLOT, value);
|
||||
}
|
||||
void setPrivate(JSRuntime* rt, const Value& value);
|
||||
|
||||
Value canonicalPrivate() const {
|
||||
Value value = getReservedSlot(PRIVATE_SLOT);
|
||||
@ -1216,7 +1205,6 @@ class ScriptSourceObject : public NativeObject {
|
||||
ELEMENT_SLOT,
|
||||
ELEMENT_PROPERTY_SLOT,
|
||||
INTRODUCTION_SCRIPT_SLOT,
|
||||
INTRODUCTION_SOURCE_OBJECT_SLOT,
|
||||
PRIVATE_SLOT,
|
||||
RESERVED_SLOTS
|
||||
};
|
||||
|
@ -162,7 +162,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
||||
moduleResolveHook(),
|
||||
moduleMetadataHook(),
|
||||
moduleDynamicImportHook(),
|
||||
scriptPrivateFinalizeHook() {
|
||||
scriptPrivateAddRefHook(),
|
||||
scriptPrivateReleaseHook() {
|
||||
JS_COUNT_CTOR(JSRuntime);
|
||||
liveRuntimesCount++;
|
||||
|
||||
|
@ -968,8 +968,9 @@ struct JSRuntime : public js::MallocProvider<JSRuntime> {
|
||||
// module import and can accessed by off-thread parsing.
|
||||
mozilla::Atomic<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
|
||||
|
||||
// A hook called on script finalization.
|
||||
js::MainThreadData<JS::ScriptPrivateFinalizeHook> scriptPrivateFinalizeHook;
|
||||
// Hooks called when script private references are created and destroyed.
|
||||
js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateAddRefHook;
|
||||
js::MainThreadData<JS::ScriptPrivateReferenceHook> scriptPrivateReleaseHook;
|
||||
|
||||
public:
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
Loading…
Reference in New Issue
Block a user