summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/ModuleObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/ModuleObject.cpp')
-rw-r--r--js/src/builtin/ModuleObject.cpp121
1 files changed, 67 insertions, 54 deletions
diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
index 30e7120c0..728929e8c 100644
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -18,10 +18,10 @@
using namespace js;
using namespace js::frontend;
-static_assert(MODULE_STATUS_ERRORED < MODULE_STATUS_UNINSTANTIATED &&
- MODULE_STATUS_UNINSTANTIATED < MODULE_STATUS_INSTANTIATING &&
+static_assert(MODULE_STATUS_UNINSTANTIATED < MODULE_STATUS_INSTANTIATING &&
MODULE_STATUS_INSTANTIATING < MODULE_STATUS_INSTANTIATED &&
- MODULE_STATUS_INSTANTIATED < MODULE_STATUS_EVALUATED,
+ MODULE_STATUS_INSTANTIATED < MODULE_STATUS_EVALUATED &&
+ MODULE_STATUS_EVALUATED < MODULE_STATUS_EVALUATED_ERROR,
"Module statuses are ordered incorrectly");
template<typename T, Value ValueGetter(const T* obj)>
@@ -248,21 +248,13 @@ IndirectBindingMap::Binding::Binding(ModuleEnvironmentObject* environment, Shape
: environment(environment), shape(shape)
{}
-IndirectBindingMap::IndirectBindingMap(Zone* zone)
- : map_(ZoneAllocPolicy(zone))
-{
-}
-
-bool
-IndirectBindingMap::init()
-{
- return map_.init();
-}
-
void
IndirectBindingMap::trace(JSTracer* trc)
{
- for (Map::Enum e(map_); !e.empty(); e.popFront()) {
+ if (!map_)
+ return;
+
+ for (Map::Enum e(*map_); !e.empty(); e.popFront()) {
Binding& b = e.front().value();
TraceEdge(trc, &b.environment, "module bindings environment");
TraceEdge(trc, &b.shape, "module bindings shape");
@@ -273,12 +265,25 @@ IndirectBindingMap::trace(JSTracer* trc)
}
bool
-IndirectBindingMap::putNew(JSContext* cx, HandleId name,
- HandleModuleEnvironmentObject environment, HandleId localName)
-{
+IndirectBindingMap::put(JSContext* cx, HandleId name,
+ HandleModuleEnvironmentObject environment, HandleId localName)
+{
+ // This object might have been allocated on the background parsing thread in
+ // different zone to the final module. Lazily allocate the map so we don't
+ // have to switch its zone when merging compartments.
+ if (!map_) {
+ MOZ_ASSERT(!cx->zone()->usedByExclusiveThread);
+ map_.emplace(cx->zone());
+ if (!map_->init()) {
+ map_.reset();
+ ReportOutOfMemory(cx);
+ return false;
+ }
+ }
+
RootedShape shape(cx, environment->lookup(cx, localName));
MOZ_ASSERT(shape);
- if (!map_.putNew(name, Binding(environment, shape))) {
+ if (!map_->put(name, Binding(environment, shape))) {
ReportOutOfMemory(cx);
return false;
}
@@ -289,7 +294,10 @@ IndirectBindingMap::putNew(JSContext* cx, HandleId name,
bool
IndirectBindingMap::lookup(jsid name, ModuleEnvironmentObject** envOut, Shape** shapeOut) const
{
- auto ptr = map_.lookup(name);
+ if (!map_)
+ return false;
+
+ auto ptr = map_->lookup(name);
if (!ptr)
return false;
@@ -359,7 +367,7 @@ ModuleNamespaceObject::addBinding(JSContext* cx, HandleAtom exportedName,
RootedModuleEnvironmentObject environment(cx, &targetModule->initialEnvironment());
RootedId exportedNameId(cx, AtomToId(exportedName));
RootedId localNameId(cx, AtomToId(localName));
- return bindings->putNew(cx, exportedNameId, environment, localNameId);
+ return bindings->put(cx, exportedNameId, environment, localNameId);
}
const char ModuleNamespaceObject::ProxyHandler::family = 0;
@@ -625,10 +633,9 @@ ModuleObject::create(ExclusiveContext* cx)
RootedModuleObject self(cx, &obj->as<ModuleObject>());
Zone* zone = cx->zone();
- IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
- if (!bindings || !bindings->init()) {
+ IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>();
+ if (!bindings) {
ReportOutOfMemory(cx);
- js_delete<IndirectBindingMap>(bindings);
return nullptr;
}
@@ -657,14 +664,24 @@ ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
fop->delete_(funDecls);
}
+ModuleEnvironmentObject&
+ModuleObject::initialEnvironment() const
+{
+ Value value = getReservedSlot(EnvironmentSlot);
+ return value.toObject().as<ModuleEnvironmentObject>();
+}
+
ModuleEnvironmentObject*
ModuleObject::environment() const
{
- Value value = getReservedSlot(EnvironmentSlot);
- if (value.isUndefined())
+ MOZ_ASSERT(!hadEvaluationError());
+
+ // According to the spec the environment record is created during
+ // instantiation, but we create it earlier than that.
+ if (status() < MODULE_STATUS_INSTANTIATED)
return nullptr;
- return &value.toObject().as<ModuleEnvironmentObject>();
+ return &initialEnvironment();
}
bool
@@ -723,13 +740,13 @@ void
ModuleObject::init(HandleScript script)
{
initReservedSlot(ScriptSlot, PrivateValue(script));
- initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_ERRORED));
+ initReservedSlot(StatusSlot, Int32Value(MODULE_STATUS_UNINSTANTIATED));
}
void
ModuleObject::setInitialEnvironment(HandleModuleEnvironmentObject initialEnvironment)
{
- initReservedSlot(InitialEnvironmentSlot, ObjectValue(*initialEnvironment));
+ initReservedSlot(EnvironmentSlot, ObjectValue(*initialEnvironment));
}
void
@@ -827,7 +844,8 @@ ModuleObject::script() const
static inline void
AssertValidModuleStatus(ModuleStatus status)
{
- MOZ_ASSERT(status >= MODULE_STATUS_ERRORED && status <= MODULE_STATUS_EVALUATED);
+ MOZ_ASSERT(status >= MODULE_STATUS_UNINSTANTIATED &&
+ status <= MODULE_STATUS_EVALUATED_ERROR);
}
ModuleStatus
@@ -838,11 +856,17 @@ ModuleObject::status() const
return status;
}
+bool
+ModuleObject::hadEvaluationError() const
+{
+ return status() == MODULE_STATUS_EVALUATED_ERROR;
+}
+
Value
-ModuleObject::error() const
+ModuleObject::evaluationError() const
{
- MOZ_ASSERT(status() == MODULE_STATUS_ERRORED);
- return getReservedSlot(ErrorSlot);
+ MOZ_ASSERT(hadEvaluationError());
+ return getReservedSlot(EvaluationErrorSlot);
}
Value
@@ -857,12 +881,6 @@ ModuleObject::setHostDefinedField(const JS::Value& value)
setReservedSlot(HostDefinedSlot, value);
}
-ModuleEnvironmentObject&
-ModuleObject::initialEnvironment() const
-{
- return getReservedSlot(InitialEnvironmentSlot).toObject().as<ModuleEnvironmentObject>();
-}
-
Scope*
ModuleObject::enclosingScope() const
{
@@ -888,16 +906,6 @@ ModuleObject::trace(JSTracer* trc, JSObject* obj)
funDecls->trace(trc);
}
-void
-ModuleObject::createEnvironment()
-{
- // The environment has already been created, we just neet to set it in the
- // right slot.
- MOZ_ASSERT(!getReservedSlot(InitialEnvironmentSlot).isUndefined());
- MOZ_ASSERT(getReservedSlot(EnvironmentSlot).isUndefined());
- setReservedSlot(EnvironmentSlot, getReservedSlot(InitialEnvironmentSlot));
-}
-
bool
ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, HandleFunction fun)
{
@@ -913,7 +921,10 @@ ModuleObject::noteFunctionDeclaration(ExclusiveContext* cx, HandleAtom name, Han
/* static */ bool
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
{
+#ifdef DEBUG
+ MOZ_ASSERT(self->status() == MODULE_STATUS_INSTANTIATING);
MOZ_ASSERT(IsFrozen(cx, self));
+#endif
FunctionDeclarationVector* funDecls = self->functionDeclarations();
if (!funDecls) {
@@ -944,7 +955,10 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
/* static */ bool
ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
{
+#ifdef DEBUG
+ MOZ_ASSERT(self->status() == MODULE_STATUS_EVALUATING);
MOZ_ASSERT(IsFrozen(cx, self));
+#endif
RootedScript script(cx, self->script());
RootedModuleEnvironmentObject scope(cx, self->environment());
@@ -967,10 +981,9 @@ ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleObje
return nullptr;
Zone* zone = cx->zone();
- IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
- if (!bindings || !bindings->init()) {
+ IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>();
+ if (!bindings) {
ReportOutOfMemory(cx);
- js_delete<IndirectBindingMap>(bindings);
return nullptr;
}
@@ -1005,7 +1018,7 @@ ModuleObject::Evaluate(JSContext* cx, HandleModuleObject self)
DEFINE_GETTER_FUNCTIONS(ModuleObject, namespace_, NamespaceSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, status, StatusSlot)
-DEFINE_GETTER_FUNCTIONS(ModuleObject, error, ErrorSlot)
+DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluationError, EvaluationErrorSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
@@ -1020,7 +1033,7 @@ GlobalObject::initModuleProto(JSContext* cx, Handle<GlobalObject*> global)
static const JSPropertySpec protoAccessors[] = {
JS_PSG("namespace", ModuleObject_namespace_Getter, 0),
JS_PSG("status", ModuleObject_statusGetter, 0),
- JS_PSG("error", ModuleObject_errorGetter, 0),
+ JS_PSG("evaluationError", ModuleObject_evaluationErrorGetter, 0),
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),