Bug 1482153 - Replace ModuleObject's host defined field with one on top-level JSScripts r=jandem r=hsivonen

This commit is contained in:
Jon Coppeard 2018-08-13 16:39:11 +01:00
Родитель 07a423be37
Коммит 623032e1f0
10 изменённых файлов: 97 добавлений и 43 удалений

Просмотреть файл

@ -56,9 +56,8 @@ ModuleScript::UnlinkScript()
{
// Remove module's back reference to this object request if present.
if (mScript) {
MOZ_ASSERT(JS::GetModuleHostDefinedField(mScript).toPrivate() ==
this);
JS::SetModuleHostDefinedField(mScript, JS::UndefinedValue());
MOZ_ASSERT(JS::GetTopLevelScriptPrivate(mScript) == this);
JS::SetTopLevelScriptPrivate(mScript, nullptr);
mScript = nullptr;
}
}
@ -81,7 +80,7 @@ ModuleScript::SetScript(JS::Handle<JSScript*> aScript)
// Make module's host defined field point to this module script object.
// This is cleared in the UnlinkScript().
JS::SetModuleHostDefinedField(mScript, JS::PrivateValue(this));
JS::SetTopLevelScriptPrivate(mScript, this);
HoldJSObjects(this);
}

Просмотреть файл

@ -760,8 +760,13 @@ HostResolveImportedModule(JSContext* aCx, JS::Handle<JSScript*> aScript,
JS::Handle<JSString*> aSpecifier)
{
// Let referencing module script be referencingModule.[[HostDefined]].
JS::Value value = JS::GetModuleHostDefinedField(aScript);
auto script = static_cast<ModuleScript*>(value.toPrivate());
void* value = JS::GetTopLevelScriptPrivate(aScript);
if (!value) {
JS_ReportErrorASCII(aCx, "Module script not found");
return nullptr;
}
auto script = static_cast<ModuleScript*>(value);
MOZ_ASSERT(script->Script() == aScript);
// Let url be the result of resolving a module specifier given referencing
@ -794,13 +799,13 @@ HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSScript*> aScript,
{
MOZ_DIAGNOSTIC_ASSERT(aScript);
JS::Value value = JS::GetModuleHostDefinedField(aScript);
if (value.isUndefined()) {
void* value = JS::GetTopLevelScriptPrivate(aScript);
if (!value) {
JS_ReportErrorASCII(aCx, "Module script not found");
return false;
}
auto script = static_cast<ModuleScript*>(value.toPrivate());
auto script = static_cast<ModuleScript*>(value);
MOZ_DIAGNOSTIC_ASSERT(script->Script() == aScript);
nsAutoCString url;

Просмотреть файл

@ -1010,18 +1010,6 @@ ModuleObject::setMetaObject(JSObject* obj)
setReservedSlot(MetaObjectSlot, ObjectValue(*obj));
}
Value
ModuleObject::hostDefinedField() const
{
return getReservedSlot(HostDefinedSlot);
}
void
ModuleObject::setHostDefinedField(const JS::Value& value)
{
setReservedSlot(HostDefinedSlot, value);
}
Scope*
ModuleObject::enclosingScope() const
{

Просмотреть файл

@ -255,7 +255,6 @@ class ModuleObject : public NativeObject
StatusSlot,
EvaluationErrorSlot,
MetaObjectSlot,
HostDefinedSlot,
RequestedModulesSlot,
ImportEntriesSlot,
LocalExportEntriesSlot,
@ -306,7 +305,6 @@ class ModuleObject : public NativeObject
bool hadEvaluationError() const;
Value evaluationError() const;
JSObject* metaObject() const;
Value hostDefinedField() const;
ArrayObject& requestedModules() const;
ArrayObject& importEntries() const;
ArrayObject& localExportEntries() const;
@ -319,8 +317,6 @@ class ModuleObject : public NativeObject
void setMetaObject(JSObject* obj);
void setHostDefinedField(const JS::Value& value);
// For BytecodeEmitter.
bool noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun);

Просмотреть файл

@ -99,8 +99,8 @@
#define MODULE_OBJECT_ENVIRONMENT_SLOT 1
#define MODULE_OBJECT_STATUS_SLOT 3
#define MODULE_OBJECT_EVALUATION_ERROR_SLOT 4
#define MODULE_OBJECT_DFS_INDEX_SLOT 14
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 15
#define MODULE_OBJECT_DFS_INDEX_SLOT 13
#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 14
#define MODULE_STATUS_UNINSTANTIATED 0
#define MODULE_STATUS_INSTANTIATING 1

Просмотреть файл

@ -4869,17 +4869,17 @@ JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
}
JS_PUBLIC_API(void)
JS::SetModuleHostDefinedField(JSScript* script, const JS::Value& value)
JS::SetTopLevelScriptPrivate(JSScript* script, void* value)
{
MOZ_ASSERT(script->module());
script->module()->setHostDefinedField(value);
MOZ_ASSERT(script);
script->setTopLevelPrivate(value);
}
JS_PUBLIC_API(JS::Value)
JS::GetModuleHostDefinedField(JSScript* script)
JS_PUBLIC_API(void*)
JS::GetTopLevelScriptPrivate(JSScript* script)
{
MOZ_ASSERT(script->module());
return script->module()->hostDefinedField();
MOZ_ASSERT(script);
return script->maybeTopLevelPrivate();
}
JS_PUBLIC_API(bool)

Просмотреть файл

@ -3915,17 +3915,16 @@ CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
/**
* Set the [[HostDefined]] field of a source text module record to the given
* value.
* Set the [[HostDefined]] field of a classic script or module script.
*/
extern JS_PUBLIC_API(void)
SetModuleHostDefinedField(JSScript* module, const JS::Value& value);
SetTopLevelScriptPrivate(JSScript* script, void* value);
/**
* Get the [[HostDefined]] field of a source text module record.
* Get the [[HostDefined]] field of a classic script or module script.
*/
extern JS_PUBLIC_API(JS::Value)
GetModuleHostDefinedField(JSScript* script);
extern JS_PUBLIC_API(void*)
GetTopLevelScriptPrivate(JSScript* script);
/*
* Perform the ModuleInstantiate operation on the given source text module

Просмотреть файл

@ -4491,6 +4491,35 @@ JSScript::AutoDelazify::dropScript()
script_ = nullptr;
}
void
JSScript::setTopLevelPrivate(void* value)
{
MOZ_ASSERT(module() || isGlobalCode());
Scope* scope = bodyScope();
if (scope->is<GlobalScope>())
scope->as<GlobalScope>().setTopLevelPrivate(value);
else if (scope->is<ModuleScope>())
scope->as<ModuleScope>().setTopLevelPrivate(value);
else
MOZ_CRASH("Unexpected scope kind");
}
void*
JSScript::maybeTopLevelPrivate() const
{
if (!module() || !isGlobalCode())
return nullptr;
Scope* scope = bodyScope();
if (scope->is<GlobalScope>())
return scope->as<GlobalScope>().topLevelPrivate();
else if (scope->is<ModuleScope>())
return scope->as<ModuleScope>().topLevelPrivate();
MOZ_CRASH("Unexpected scope kind");
}
JS::ubi::Node::Size
JS::ubi::Concrete<JSScript>::size(mozilla::MallocSizeOf mallocSizeOf) const
{

Просмотреть файл

@ -1760,8 +1760,13 @@ class JSScript : public js::gc::TenuredCell
*
* If this script has a function associated to it, then it is not the
* top-level of a file.
*
* Note that this can returns true for eval scripts as well as global
* scripts and modules.
*/
bool isTopLevel() { return code() && !functionNonDelazifying(); }
bool isTopLevel() const {
return code() && !functionNonDelazifying();
}
/* Ensure the script has a TypeScript. */
inline bool ensureHasTypes(JSContext* cx, js::AutoKeepTypeScripts&);
@ -2084,6 +2089,12 @@ class JSScript : public js::gc::TenuredCell
uint32_t stepModeCount() { return bitFields_.hasDebugScript_ ? debugScript()->stepMode : 0; }
#endif
// Set/get a embedding pointer that can be associated with top-level (global
// or module) scripts. Note that although isTopLevel() can return true for
// eval scripts, these are not supported.
void setTopLevelPrivate(void* value);
void* maybeTopLevelPrivate() const;
void finalize(js::FreeOp* fop);
static const JS::TraceKind TraceKind = JS::TraceKind::Script;

Просмотреть файл

@ -419,6 +419,17 @@ class Scope : public js::gc::TenuredCell
class BaseScopeData
{};
/*
* Scope for a top level script: either a global (classic) script or a module
* script.
*/
class TopLevelScopeData : public BaseScopeData
{
public:
// Private data for use by the embedding.
void* privateData = nullptr;
};
template<class Data>
inline size_t
SizeOfData(uint32_t numBindings)
@ -772,7 +783,7 @@ class GlobalScope : public Scope
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newGlobalScopeData.
struct Data : BaseScopeData
struct Data : public TopLevelScopeData
{
// Bindings are sorted by kind.
// `vars` includes top-level functions which is distinguished by a bit
@ -826,6 +837,14 @@ class GlobalScope : public Scope
bool hasBindings() const {
return data().length > 0;
}
void setTopLevelPrivate(void* value) {
data().privateData = value;
}
void* topLevelPrivate() const {
return data().privateData;
}
};
template <>
@ -964,7 +983,7 @@ class ModuleScope : public Scope
public:
// Data is public because it is created by the frontend. See
// Parser<FullParseHandler>::newModuleScopeData.
struct Data : BaseScopeData
struct Data : public TopLevelScopeData
{
// The module of the scope.
GCPtr<ModuleObject*> module = {};
@ -1021,6 +1040,14 @@ class ModuleScope : public Scope
JSScript* script() const;
void setTopLevelPrivate(void* value) {
data().privateData = value;
}
void* topLevelPrivate() const {
return data().privateData;
}
static Shape* getEmptyEnvironmentShape(JSContext* cx);
};