Skip to content

Commit 5af53ec

Browse files
devsnekV8 LUCI CQ
authored andcommitted
[top-level-await] fix async evaluation with errored async parent
Updates a CHECK to support EVALUATING-ASYNC modules. Updates GatherAvailableAncestors to check kErrored before calling AsyncEvaluationOrdinalCompare to prevent hitting DCHECK. Change-Id: If561751092010a36706c8c15fa977953facd5c3e Bug: 361615555 Bug: 361603701 Bug: 361611791 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5807477 Reviewed-by: Shu-yu Guo <[email protected]> Commit-Queue: snek <[email protected]> Cr-Commit-Position: refs/heads/main@{#95823}
1 parent d43a3ca commit 5af53ec

8 files changed

Lines changed: 61 additions & 31 deletions

src/d8/d8.cc

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,34 +1269,30 @@ struct DynamicImportData {
12691269
};
12701270

12711271
namespace {
1272-
struct ModuleResolutionData {
1273-
ModuleResolutionData(Isolate* isolate_, Local<Value> module_namespace_,
1274-
Local<Promise::Resolver> resolver_)
1275-
: isolate(isolate_) {
1276-
module_namespace.Reset(isolate, module_namespace_);
1277-
resolver.Reset(isolate, resolver_);
1278-
}
12791272

1280-
Isolate* isolate;
1281-
Global<Value> module_namespace;
1282-
Global<Promise::Resolver> resolver;
1273+
enum ModuleResolutionDataIndex : uint32_t {
1274+
kResolver = 0,
1275+
kNamespace = 1,
12831276
};
12841277

12851278
} // namespace
12861279

12871280
void Shell::ModuleResolutionSuccessCallback(
12881281
const FunctionCallbackInfo<Value>& info) {
12891282
DCHECK(i::ValidateCallbackInfo(info));
1290-
std::unique_ptr<ModuleResolutionData> module_resolution_data(
1291-
static_cast<ModuleResolutionData*>(
1292-
info.Data().As<v8::External>()->Value()));
1293-
Isolate* isolate(module_resolution_data->isolate);
1283+
Isolate* isolate(info.GetIsolate());
12941284
HandleScope handle_scope(isolate);
1285+
Local<Array> module_resolution_data(info.Data().As<Array>());
1286+
Local<Context> context(isolate->GetCurrentContext());
12951287

12961288
Local<Promise::Resolver> resolver(
1297-
module_resolution_data->resolver.Get(isolate));
1289+
module_resolution_data->Get(context, ModuleResolutionDataIndex::kResolver)
1290+
.ToLocalChecked()
1291+
.As<Promise::Resolver>());
12981292
Local<Value> module_namespace(
1299-
module_resolution_data->module_namespace.Get(isolate));
1293+
module_resolution_data
1294+
->Get(context, ModuleResolutionDataIndex::kNamespace)
1295+
.ToLocalChecked());
13001296

13011297
PerIsolateData* data = PerIsolateData::Get(isolate);
13021298
Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
@@ -1308,14 +1304,15 @@ void Shell::ModuleResolutionSuccessCallback(
13081304
void Shell::ModuleResolutionFailureCallback(
13091305
const FunctionCallbackInfo<Value>& info) {
13101306
DCHECK(i::ValidateCallbackInfo(info));
1311-
std::unique_ptr<ModuleResolutionData> module_resolution_data(
1312-
static_cast<ModuleResolutionData*>(
1313-
info.Data().As<v8::External>()->Value()));
1314-
Isolate* isolate(module_resolution_data->isolate);
1307+
Isolate* isolate(info.GetIsolate());
13151308
HandleScope handle_scope(isolate);
1309+
Local<Array> module_resolution_data(info.Data().As<Array>());
1310+
Local<Context> context(isolate->GetCurrentContext());
13161311

13171312
Local<Promise::Resolver> resolver(
1318-
module_resolution_data->resolver.Get(isolate));
1313+
module_resolution_data->Get(context, ModuleResolutionDataIndex::kResolver)
1314+
.ToLocalChecked()
1315+
.As<Promise::Resolver>());
13191316

13201317
PerIsolateData* data = PerIsolateData::Get(isolate);
13211318
Local<Context> realm = data->realms_[data->realm_current_].Get(isolate);
@@ -1493,15 +1490,20 @@ void Shell::DoHostImportModuleDynamically(void* import_data) {
14931490
Local<Promise> result_promise = result.As<Promise>();
14941491

14951492
// Setup callbacks, and then chain them to the result promise.
1496-
// ModuleResolutionData will be deleted by the callbacks.
1497-
auto module_resolution_data =
1498-
new ModuleResolutionData(isolate, module_namespace, resolver);
1499-
Local<v8::External> edata = External::New(isolate, module_resolution_data);
1493+
Local<Array> module_resolution_data = v8::Array::New(isolate);
1494+
module_resolution_data
1495+
->Set(realm, ModuleResolutionDataIndex::kResolver, resolver)
1496+
.ToChecked();
1497+
module_resolution_data
1498+
->Set(realm, ModuleResolutionDataIndex::kNamespace, module_namespace)
1499+
.ToChecked();
15001500
Local<Function> callback_success;
1501-
CHECK(Function::New(realm, ModuleResolutionSuccessCallback, edata)
1501+
CHECK(Function::New(realm, ModuleResolutionSuccessCallback,
1502+
module_resolution_data)
15021503
.ToLocal(&callback_success));
15031504
Local<Function> callback_failure;
1504-
CHECK(Function::New(realm, ModuleResolutionFailureCallback, edata)
1505+
CHECK(Function::New(realm, ModuleResolutionFailureCallback,
1506+
module_resolution_data)
15051507
.ToLocal(&callback_failure));
15061508
result_promise->Then(realm, callback_success, callback_failure)
15071509
.ToLocalChecked();

src/objects/module.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ bool Module::Instantiate(Isolate* isolate, Handle<Module> module,
218218
return false;
219219
}
220220
DCHECK(module->status() == kLinked || module->status() == kEvaluated ||
221-
module->status() == kErrored);
221+
module->status() == kEvaluatingAsync || module->status() == kErrored);
222222
DCHECK(stack.empty());
223223
return true;
224224
}

src/objects/source-text-module.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -682,8 +682,8 @@ void SourceTextModule::GatherAvailableAncestors(
682682

683683
// a. If execList does not contain m and
684684
// m.[[CycleRoot]].[[EvaluationError]] is empty, then
685-
if (exec_list->find(m) == exec_list->end() &&
686-
m->GetCycleRoot(isolate)->status() != kErrored) {
685+
if (m->GetCycleRoot(isolate)->status() != kErrored &&
686+
exec_list->find(m) == exec_list->end()) {
687687
// i. Assert: m.[[Status]] is EVALUATING-ASYNC.
688688
// ii. Assert: m.[[EvaluationError]] is empty.
689689
DCHECK_EQ(m->status(), kEvaluatingAsync);
@@ -769,7 +769,8 @@ bool SourceTextModule::MaybeHandleEvaluationException(
769769
// ES#sec-moduleevaluation
770770
MaybeHandle<Object> SourceTextModule::Evaluate(
771771
Isolate* isolate, Handle<SourceTextModule> module) {
772-
CHECK(module->status() == kLinked || module->status() == kEvaluated);
772+
CHECK(module->status() == kLinked || module->status() == kEvaluatingAsync ||
773+
module->status() == kEvaluated);
773774

774775
// 5. Let stack be a new empty List.
775776
Zone zone(isolate->allocator(), ZONE_NAME);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright 2024 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
assertThrowsAsync(import('./modules-skip-async-error-parent.mjs'));

test/mjsunit/harmony/modules-skip-async-error-parent-dynamic.mjs

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2024 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
await import('./modules-skip-async-error-parent-dynamic.mjs');
6+
import('./modules-skip-async-error-parent.mjs').catch(() => {});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright 2024 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import('./modules-skip-async-error-parent-static1.mjs');
6+
await import('./modules-skip-async-error-parent-dynamic.mjs');
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2024 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import './modules-skip-async-error-parent-static1.mjs';
6+
import './modules-skip-async-error-parent-static2.mjs';
7+
8+
await {};
9+
10+
throw new Error('aaa');

0 commit comments

Comments
 (0)