diff options
Diffstat (limited to 'js/src/builtin/ModuleObject.cpp')
-rw-r--r-- | js/src/builtin/ModuleObject.cpp | 121 |
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), |