Backed out 3 changesets (bug 1777972) for causing failures at ModuleObject.cpp. CLOSED TREE

Backed out changeset 2517efe4191b (bug 1777972)
Backed out changeset 8580c5c39eec (bug 1777972)
Backed out changeset a3211c84154b (bug 1777972)
This commit is contained in:
Butkovits Atila 2022-07-12 00:20:15 +03:00
Родитель fe050dd2ed
Коммит 6cf54cee68
5 изменённых файлов: 50 добавлений и 94 удалений

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

@ -45,9 +45,7 @@ using mozilla::Some;
static_assert(ModuleStatus::Unlinked < ModuleStatus::Linking && static_assert(ModuleStatus::Unlinked < ModuleStatus::Linking &&
ModuleStatus::Linking < ModuleStatus::Linked && ModuleStatus::Linking < ModuleStatus::Linked &&
ModuleStatus::Linked < ModuleStatus::Evaluating && ModuleStatus::Linked < ModuleStatus::Evaluated &&
ModuleStatus::Evaluating < ModuleStatus::EvaluatingAsync &&
ModuleStatus::EvaluatingAsync < ModuleStatus::Evaluated &&
ModuleStatus::Evaluated < ModuleStatus::Evaluated_Error, ModuleStatus::Evaluated < ModuleStatus::Evaluated_Error,
"Module statuses are ordered incorrectly"); "Module statuses are ordered incorrectly");
@ -947,9 +945,6 @@ static inline void AssertValidModuleStatus(ModuleStatus status) {
ModuleStatus ModuleObject::status() const { ModuleStatus ModuleObject::status() const {
ModuleStatus status = ModuleStatus(getReservedSlot(StatusSlot).toInt32()); ModuleStatus status = ModuleStatus(getReservedSlot(StatusSlot).toInt32());
AssertValidModuleStatus(status); AssertValidModuleStatus(status);
if (status == ModuleStatus::Evaluated_Error) {
return ModuleStatus::Evaluated;
}
return status; return status;
} }
@ -1030,17 +1025,17 @@ void ModuleObject::clearDfsIndexes() {
setReservedSlot(DFSAncestorIndexSlot, UndefinedValue()); setReservedSlot(DFSAncestorIndexSlot, UndefinedValue());
} }
PromiseObject* ModuleObject::maybeTopLevelCapability() const { JSObject* ModuleObject::maybeTopLevelCapability() const {
Value value = getReservedSlot(TopLevelCapabilitySlot); Value value = getReservedSlot(TopLevelCapabilitySlot);
if (value.isUndefined()) { if (value.isUndefined()) {
return nullptr; return nullptr;
} }
return &value.toObject().as<PromiseObject>(); return &value.toObject();
} }
PromiseObject* ModuleObject::topLevelCapability() const { JSObject* ModuleObject::topLevelCapability() const {
PromiseObject* capability = maybeTopLevelCapability(); JSObject* capability = maybeTopLevelCapability();
MOZ_RELEASE_ASSERT(capability); MOZ_RELEASE_ASSERT(capability);
return capability; return capability;
} }
@ -1056,9 +1051,8 @@ PromiseObject* ModuleObject::createTopLevelCapability(
return resultPromise; return resultPromise;
} }
void ModuleObject::setInitialTopLevelCapability( void ModuleObject::setInitialTopLevelCapability(HandleObject promiseObj) {
Handle<PromiseObject*> capability) { initReservedSlot(TopLevelCapabilitySlot, ObjectValue(*promiseObj));
initReservedSlot(TopLevelCapabilitySlot, ObjectValue(*capability));
} }
ListObject* ModuleObject::asyncParentModules() const { ListObject* ModuleObject::asyncParentModules() const {
@ -1118,19 +1112,12 @@ bool ModuleObject::hasTopLevelCapability() const {
} }
bool ModuleObject::hadEvaluationError() const { bool ModuleObject::hadEvaluationError() const {
ModuleStatus fullStatus = ModuleStatus(getReservedSlot(StatusSlot).toInt32()); return status() == ModuleStatus::Evaluated_Error;
return fullStatus == ModuleStatus::Evaluated_Error;
} }
void ModuleObject::setEvaluationError(HandleValue newValue) { void ModuleObject::setEvaluationError(HandleValue newValue) {
MOZ_ASSERT(status() != ModuleStatus::Unlinked);
MOZ_ASSERT(!hadEvaluationError());
setReservedSlot(StatusSlot, ModuleStatusValue(ModuleStatus::Evaluated_Error)); setReservedSlot(StatusSlot, ModuleStatusValue(ModuleStatus::Evaluated_Error));
setReservedSlot(EvaluationErrorSlot, newValue); return setReservedSlot(EvaluationErrorSlot, newValue);
MOZ_ASSERT(status() == ModuleStatus::Evaluated);
MOZ_ASSERT(hadEvaluationError());
} }
Value ModuleObject::maybeEvaluationError() const { Value ModuleObject::maybeEvaluationError() const {
@ -1216,9 +1203,7 @@ bool ModuleObject::instantiateFunctionDeclarations(JSContext* cx,
bool ModuleObject::execute(JSContext* cx, Handle<ModuleObject*> self) { bool ModuleObject::execute(JSContext* cx, Handle<ModuleObject*> self) {
#ifdef DEBUG #ifdef DEBUG
MOZ_ASSERT(self->status() == ModuleStatus::Evaluating || MOZ_ASSERT(self->status() == ModuleStatus::Evaluating ||
self->status() == ModuleStatus::EvaluatingAsync ||
self->status() == ModuleStatus::Evaluated); self->status() == ModuleStatus::Evaluated);
MOZ_ASSERT(!self->hadEvaluationError());
if (!AssertFrozen(cx, self)) { if (!AssertFrozen(cx, self)) {
return false; return false;
} }
@ -2395,8 +2380,7 @@ static bool OnResolvedDynamicModule(JSContext* cx, unsigned argc, Value* vp) {
} }
Rooted<ModuleObject*> module(cx, &result->as<ModuleObject>()); Rooted<ModuleObject*> module(cx, &result->as<ModuleObject>());
if (module->status() != ModuleStatus::EvaluatingAsync && if (module->status() != ModuleStatus::Evaluated) {
module->status() != ModuleStatus::Evaluated) {
JS_ReportErrorASCII( JS_ReportErrorASCII(
cx, "Unevaluated or errored module returned by module resolve hook"); cx, "Unevaluated or errored module returned by module resolve hook");
return RejectPromiseWithPendingError(cx, promise); return RejectPromiseWithPendingError(cx, promise);

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

@ -255,14 +255,8 @@ enum class ModuleStatus : int32_t {
Linking, Linking,
Linked, Linked,
Evaluating, Evaluating,
EvaluatingAsync,
Evaluated, Evaluated,
Evaluated_Error // Sub-state of Evaluated with error value set.
// Sub-state of Evaluated with error value set.
//
// This is not returned from ModuleObject::status(); use hadEvaluationError()
// to check this.
Evaluated_Error
}; };
// Special values for ModuleObject's AsyncEvaluatingPostOrderSlot slot, which is // Special values for ModuleObject's AsyncEvaluatingPostOrderSlot slot, which is
@ -374,10 +368,10 @@ class ModuleObject : public NativeObject {
void setAsyncEvaluatingFalse(); void setAsyncEvaluatingFalse();
void setEvaluationError(HandleValue newValue); void setEvaluationError(HandleValue newValue);
void setPendingAsyncDependencies(uint32_t newValue); void setPendingAsyncDependencies(uint32_t newValue);
void setInitialTopLevelCapability(Handle<PromiseObject*> capability); void setInitialTopLevelCapability(HandleObject promiseObj);
bool hasTopLevelCapability() const; bool hasTopLevelCapability() const;
PromiseObject* maybeTopLevelCapability() const; JSObject* maybeTopLevelCapability() const;
PromiseObject* topLevelCapability() const; JSObject* topLevelCapability() const;
ListObject* asyncParentModules() const; ListObject* asyncParentModules() const;
mozilla::Maybe<uint32_t> maybePendingAsyncDependencies() const; mozilla::Maybe<uint32_t> maybePendingAsyncDependencies() const;
uint32_t pendingAsyncDependencies() const; uint32_t pendingAsyncDependencies() const;

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

@ -1,4 +0,0 @@
let a = parseModule(`throw new Error`);
moduleLink(a);
moduleEvaluate(a).catch(e => {});
moduleEvaluate(a).catch(e => {});

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

@ -33,7 +33,7 @@ testGetter(a, "namespace");
// ==== status getter ==== // ==== status getter ====
const MODULE_STATUS_UNLINKED = 0; const MODULE_STATUS_UNLINKED = 0;
const MODULE_STATUS_LINKED = 2; const MODULE_STATUS_LINKED = 2;
const MODULE_STATUS_EVALUATED = 5; const MODULE_STATUS_EVALUATED = 4;
const c = registerModule('c', parseModule(` const c = registerModule('c', parseModule(`
`)); `));

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

@ -1075,8 +1075,8 @@ bool js::ModuleLink(JSContext* cx, Handle<ModuleObject*> module) {
// Step 5. Assert: module.[[Status]] is linked, evaluating-async, or // Step 5. Assert: module.[[Status]] is linked, evaluating-async, or
// evaluated. // evaluated.
MOZ_ASSERT(module->status() == ModuleStatus::Linked || MOZ_ASSERT(module->status() == ModuleStatus::Linked ||
module->status() == ModuleStatus::EvaluatingAsync || module->status() == ModuleStatus::Evaluated ||
module->status() == ModuleStatus::Evaluated); module->status() == ModuleStatus::Evaluated_Error);
// Step 6. Assert: stack is empty. // Step 6. Assert: stack is empty.
MOZ_ASSERT(stack.empty()); MOZ_ASSERT(stack.empty());
@ -1094,8 +1094,8 @@ static bool InnerModuleLinking(JSContext* cx, Handle<ModuleObject*> module,
// evaluated, then: // evaluated, then:
if (module->status() == ModuleStatus::Linking || if (module->status() == ModuleStatus::Linking ||
module->status() == ModuleStatus::Linked || module->status() == ModuleStatus::Linked ||
module->status() == ModuleStatus::EvaluatingAsync || module->status() == ModuleStatus::Evaluated ||
module->status() == ModuleStatus::Evaluated) { module->status() == ModuleStatus::Evaluated_Error) {
// Step 2.a. Return index. // Step 2.a. Return index.
*indexOut = index; *indexOut = index;
return true; return true;
@ -1157,8 +1157,8 @@ static bool InnerModuleLinking(JSContext* cx, Handle<ModuleObject*> module,
// evaluating-async, or evaluated. // evaluating-async, or evaluated.
MOZ_ASSERT(requiredModule->status() == ModuleStatus::Linking || MOZ_ASSERT(requiredModule->status() == ModuleStatus::Linking ||
requiredModule->status() == ModuleStatus::Linked || requiredModule->status() == ModuleStatus::Linked ||
requiredModule->status() == ModuleStatus::EvaluatingAsync || requiredModule->status() == ModuleStatus::Evaluated ||
requiredModule->status() == ModuleStatus::Evaluated); requiredModule->status() == ModuleStatus::Evaluated_Error);
// Step 9.c.ii. Assert: requiredModule.[[Status]] is linking if and only if // Step 9.c.ii. Assert: requiredModule.[[Status]] is linking if and only if
// requiredModule is in stack. // requiredModule is in stack.
@ -1220,27 +1220,16 @@ bool js::ModuleEvaluate(JSContext* cx, Handle<ModuleObject*> moduleArg,
// Step 2. Assert: module.[[Status]] is linked, evaluating-async, or // Step 2. Assert: module.[[Status]] is linked, evaluating-async, or
// evaluated. // evaluated.
if (module->status() != ModuleStatus::Linked && if (module->status() != ModuleStatus::Linked &&
module->status() != ModuleStatus::EvaluatingAsync && module->status() != ModuleStatus::Evaluated &&
module->status() != ModuleStatus::Evaluated) { module->status() != ModuleStatus::Evaluated_Error) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_BAD_MODULE_STATUS); JSMSG_BAD_MODULE_STATUS);
return false; return false;
} }
// Note: we return early in the error case, as the spec assumes we can get the
// cycle root of |module| which may not be available.
if (module->hadEvaluationError()) {
Rooted<PromiseObject*> promise(cx, module->topLevelCapability());
MOZ_ASSERT(JS::GetPromiseState(promise) == JS::PromiseState::Rejected);
MOZ_ASSERT(JS::GetPromiseResult(promise) == module->evaluationError());
result.set(ObjectValue(*promise));
return true;
}
// Step 3. If module.[[Status]] is evaluating-async or evaluated, set module // Step 3. If module.[[Status]] is evaluating-async or evaluated, set module
// to module.[[CycleRoot]]. // to module.[[CycleRoot]].
if (module->status() == ModuleStatus::EvaluatingAsync || if (module->status() == ModuleStatus::Evaluated) {
module->status() == ModuleStatus::Evaluated) {
module = module->getCycleRoot(); module = module->getCycleRoot();
} }
@ -1295,7 +1284,7 @@ bool js::ModuleEvaluate(JSContext* cx, Handle<ModuleObject*> moduleArg,
} }
// Step 9.b. Assert: module.[[Status]] is evaluated. // Step 9.b. Assert: module.[[Status]] is evaluated.
MOZ_ASSERT(module->status() == ModuleStatus::Evaluated); MOZ_ASSERT(module->status() == ModuleStatus::Evaluated_Error);
// Step 9.c. Assert: module.[[EvaluationError]] is result. // Step 9.c. Assert: module.[[EvaluationError]] is result.
MOZ_ASSERT(module->evaluationError() == error); MOZ_ASSERT(module->evaluationError() == error);
@ -1308,11 +1297,9 @@ bool js::ModuleEvaluate(JSContext* cx, Handle<ModuleObject*> moduleArg,
} else { } else {
// Step 10. Else: // Step 10. Else:
// Step 10.a. Assert: module.[[Status]] is evaluating-async or evaluated. // Step 10.a. Assert: module.[[Status]] is evaluating-async or evaluated.
MOZ_ASSERT(module->status() == ModuleStatus::EvaluatingAsync ||
module->status() == ModuleStatus::Evaluated);
// Step 10.b. Assert: module.[[EvaluationError]] is empty. // Step 10.b. Assert: module.[[EvaluationError]] is empty.
MOZ_ASSERT(!module->hadEvaluationError()); MOZ_ASSERT(module->status() == ModuleStatus::Evaluating ||
module->status() == ModuleStatus::Evaluated);
// Step 10.c. If module.[[AsyncEvaluation]] is false, then: // Step 10.c. If module.[[AsyncEvaluation]] is false, then:
if (!module->isAsyncEvaluating()) { if (!module->isAsyncEvaluating()) {
@ -1341,22 +1328,19 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
MutableHandle<ModuleVector> stack, MutableHandle<ModuleVector> stack,
size_t index, size_t* indexOut) { size_t index, size_t* indexOut) {
// Step 2. If module.[[Status]] is evaluating-async or evaluated, then: // Step 2. If module.[[Status]] is evaluating-async or evaluated, then:
if (module->status() == ModuleStatus::EvaluatingAsync || // Step 2.a. If module.[[EvaluationError]] is empty, return index.
module->status() == ModuleStatus::Evaluated) { // Step 2.b. Otherwise, return ? module.[[EvaluationError]].
// Step 2.a. If module.[[EvaluationError]] is empty, return index. // Step 3. If module.[[Status]] is evaluating, return index.
if (!module->hadEvaluationError()) {
*indexOut = index;
return true;
}
// Step 2.b. Otherwise, return ? module.[[EvaluationError]]. // This section is rearranged since we don't have an evaluating-async state
// but we do have an 'evaluation produced an error' state.
if (module->hadEvaluationError()) {
Rooted<Value> error(cx, module->evaluationError()); Rooted<Value> error(cx, module->evaluationError());
cx->setPendingException(error, ShouldCaptureStack::Maybe); cx->setPendingException(error, ShouldCaptureStack::Maybe);
return false; return false;
} }
if (module->status() == ModuleStatus::Evaluating ||
// Step 3. If module.[[Status]] is evaluating, return index. module->status() == ModuleStatus::Evaluated) {
if (module->status() == ModuleStatus::Evaluating) {
*indexOut = index; *indexOut = index;
return true; return true;
} }
@ -1417,7 +1401,6 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
// Step 11.d.i. Assert: requiredModule.[[Status]] is either evaluating, // Step 11.d.i. Assert: requiredModule.[[Status]] is either evaluating,
// evaluating-async, or evaluated. // evaluating-async, or evaluated.
MOZ_ASSERT(requiredModule->status() == ModuleStatus::Evaluating || MOZ_ASSERT(requiredModule->status() == ModuleStatus::Evaluating ||
requiredModule->status() == ModuleStatus::EvaluatingAsync ||
requiredModule->status() == ModuleStatus::Evaluated); requiredModule->status() == ModuleStatus::Evaluated);
// Step 11.d.ii. Assert: requiredModule.[[Status]] is evaluating if and only // Step 11.d.ii. Assert: requiredModule.[[Status]] is evaluating if and only
@ -1439,12 +1422,11 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
// Step 11.d.iv.2. Assert: requiredModule.[[Status]] is evaluating-async // Step 11.d.iv.2. Assert: requiredModule.[[Status]] is evaluating-async
// or evaluated. // or evaluated.
MOZ_ASSERT(requiredModule->status() >= ModuleStatus::EvaluatingAsync || MOZ_ASSERT(requiredModule->status() >= ModuleStatus::Evaluated);
requiredModule->status() == ModuleStatus::Evaluated);
// Step 11.d.iv.3. If requiredModule.[[EvaluationError]] is not empty, // Step 11.d.iv.3. If requiredModule.[[EvaluationError]] is not empty,
// return ? requiredModule.[[EvaluationError]]. // return ? requiredModule.[[EvaluationError]].
if (requiredModule->hadEvaluationError()) { if (requiredModule->status() == ModuleStatus::Evaluated_Error) {
Rooted<Value> error(cx, requiredModule->evaluationError()); Rooted<Value> error(cx, requiredModule->evaluationError());
cx->setPendingException(error, ShouldCaptureStack::Maybe); cx->setPendingException(error, ShouldCaptureStack::Maybe);
return false; return false;
@ -1511,13 +1493,11 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
// Step 16.b.iv. If requiredModule.[[AsyncEvaluation]] is false, set // Step 16.b.iv. If requiredModule.[[AsyncEvaluation]] is false, set
// requiredModule.[[Status]] to evaluated. // requiredModule.[[Status]] to evaluated.
if (!requiredModule->isAsyncEvaluating()) { // Step 16.b.v. Otherwise, set requiredModule.[[Status]] to
requiredModule->setStatus(ModuleStatus::Evaluated); // evaluating-async.
} else {
// Step 16.b.v. Otherwise, set requiredModule.[[Status]] to // Bug 1777972: We don't have a separate evaluating-async state.
// evaluating-async. requiredModule->setStatus(ModuleStatus::Evaluated);
requiredModule->setStatus(ModuleStatus::EvaluatingAsync);
}
// Step 16.b.vi. If requiredModule and module are the same Module Record, // Step 16.b.vi. If requiredModule and module are the same Module Record,
// set done to true. // set done to true.
@ -1538,7 +1518,7 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
static bool ExecuteAsyncModule(JSContext* cx, Handle<ModuleObject*> module) { static bool ExecuteAsyncModule(JSContext* cx, Handle<ModuleObject*> module) {
// Step 1. Assert: module.[[Status]] is evaluating or evaluating-async. // Step 1. Assert: module.[[Status]] is evaluating or evaluating-async.
MOZ_ASSERT(module->status() == ModuleStatus::Evaluating || MOZ_ASSERT(module->status() == ModuleStatus::Evaluating ||
module->status() == ModuleStatus::EvaluatingAsync); module->status() == ModuleStatus::Evaluated);
// Step 2. Assert: module.[[HasTLA]] is true. // Step 2. Assert: module.[[HasTLA]] is true.
MOZ_ASSERT(module->hasTopLevelAwait()); MOZ_ASSERT(module->hasTopLevelAwait());
@ -1559,11 +1539,10 @@ struct EvalOrderComparator {
} }
}; };
// 16.2.1.5.2.3 GatherAvailableAncestors
bool js::GatherAvailableModuleAncestors( bool js::GatherAvailableModuleAncestors(
JSContext* cx, Handle<ModuleObject*> module, JSContext* cx, Handle<ModuleObject*> module,
MutableHandle<ModuleVector> sortedList) { MutableHandle<ModuleVector> sortedList) {
MOZ_ASSERT(module->status() == ModuleStatus::EvaluatingAsync); MOZ_ASSERT(module->status() == ModuleStatus::Evaluated);
MOZ_ASSERT(sortedList.empty()); MOZ_ASSERT(sortedList.empty());
if (!::GatherAvailableModuleAncestors(cx, module, sortedList)) { if (!::GatherAvailableModuleAncestors(cx, module, sortedList)) {
@ -1604,7 +1583,9 @@ static bool GatherAvailableModuleAncestors(
if (!m->getCycleRoot()->hadEvaluationError() && if (!m->getCycleRoot()->hadEvaluationError() &&
!ContainsElement(execList, m)) { !ContainsElement(execList, m)) {
// Step 1.a.i. Assert: m.[[Status]] is evaluating-async. // Step 1.a.i. Assert: m.[[Status]] is evaluating-async.
MOZ_ASSERT(m->status() == ModuleStatus::EvaluatingAsync);
// Bug 1777972: We don't have a separate evaluating-async state.
MOZ_ASSERT(m->status() == ModuleStatus::Evaluated);
// Step 1.a.ii. Assert: m.[[EvaluationError]] is empty. // Step 1.a.ii. Assert: m.[[EvaluationError]] is empty.
MOZ_ASSERT(!m->hadEvaluationError()); MOZ_ASSERT(!m->hadEvaluationError());
@ -1644,7 +1625,7 @@ static bool GatherAvailableModuleAncestors(
void js::AsyncModuleExecutionFulfilled(JSContext* cx, void js::AsyncModuleExecutionFulfilled(JSContext* cx,
Handle<ModuleObject*> module) { Handle<ModuleObject*> module) {
// Step 1. // Step 1.
MOZ_ASSERT(module->status() == ModuleStatus::EvaluatingAsync); MOZ_ASSERT(module->status() == ModuleStatus::Evaluated);
// Step 2. // Step 2.
MOZ_ASSERT(module->isAsyncEvaluating()); MOZ_ASSERT(module->isAsyncEvaluating());
@ -1723,7 +1704,8 @@ void js::AsyncModuleExecutionRejected(JSContext* cx,
Handle<ModuleObject*> module, Handle<ModuleObject*> module,
HandleValue error) { HandleValue error) {
// Step 1. // Step 1.
MOZ_ASSERT(module->status() == ModuleStatus::EvaluatingAsync); MOZ_ASSERT(module->status() == ModuleStatus::Evaluated ||
module->status() == ModuleStatus::Evaluated_Error);
// Step 2. // Step 2.
if (!module->isAsyncEvaluating()) { if (!module->isAsyncEvaluating()) {