Skip to content

Commit fe5e2e3

Browse files
committed
deps: v8 backport 9689b17687b
[top-level-await] Implement spec fix for cycle root detection Refs: http://github.com/v8/v8/commit/9689b17687b21c800c3f7400df4255c55b9c6ec0 PR-URL: #37865 Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent cb9ec6d commit fe5e2e3

13 files changed

+109
-62
lines changed

common.gypi

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
# Reset this number to 0 on major V8 upgrades.
3838
# Increment by one for each non-official patch applied to deps/v8.
39-
'v8_embedder_string': '-node.19',
39+
'v8_embedder_string': '-node.20',
4040

4141
##### V8 defaults for Node.js #####
4242

deps/v8/src/diagnostics/objects-printer.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,7 @@ void SourceTextModule::SourceTextModulePrint(std::ostream& os) { // NOLINT
16211621
os << "\n - requested_modules: " << Brief(requested_modules());
16221622
os << "\n - script: " << Brief(script());
16231623
os << "\n - import_meta: " << Brief(import_meta());
1624+
os << "\n - cycle_root: " << Brief(cycle_root());
16241625
os << "\n";
16251626
}
16261627

deps/v8/src/heap/factory.cc

+1
Original file line numberDiff line numberDiff line change
@@ -2486,6 +2486,7 @@ Handle<SourceTextModule> Factory::NewSourceTextModule(
24862486
module->set_flags(0);
24872487
module->set_async(IsAsyncModule(code->kind()));
24882488
module->set_async_evaluating(false);
2489+
module->set_cycle_root(roots.the_hole_value());
24892490
module->set_async_parent_modules(*async_parent_modules);
24902491
module->set_pending_async_dependencies(0);
24912492
return module;

deps/v8/src/objects/module-inl.h

+8
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ class UnorderedModuleSet
111111
ZoneAllocator<Handle<Module>>(zone)) {}
112112
};
113113

114+
Handle<SourceTextModule> SourceTextModule::GetCycleRoot(
115+
Isolate* isolate) const {
116+
CHECK_GE(status(), kEvaluated);
117+
DCHECK(!cycle_root().IsTheHole(isolate));
118+
Handle<SourceTextModule> root(SourceTextModule::cast(cycle_root()), isolate);
119+
return root;
120+
}
121+
114122
void SourceTextModule::AddAsyncParentModule(Isolate* isolate,
115123
Handle<SourceTextModule> module,
116124
Handle<SourceTextModule> parent) {

deps/v8/src/objects/source-text-module.cc

+14-57
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ bool SourceTextModule::MaybeTransitionComponent(
398398
DCHECK_LE(module->dfs_ancestor_index(), module->dfs_index());
399399
if (module->dfs_ancestor_index() == module->dfs_index()) {
400400
// This is the root of its strongly connected component.
401+
Handle<SourceTextModule> cycle_root = module;
401402
Handle<SourceTextModule> ancestor;
402403
do {
403404
ancestor = stack->front();
@@ -407,6 +408,9 @@ bool SourceTextModule::MaybeTransitionComponent(
407408
if (new_status == kInstantiated) {
408409
if (!SourceTextModule::RunInitializationCode(isolate, ancestor))
409410
return false;
411+
} else if (new_status == kEvaluated) {
412+
DCHECK(ancestor->cycle_root().IsTheHole(isolate));
413+
ancestor->set_cycle_root(*cycle_root);
410414
}
411415
ancestor->SetStatus(new_status);
412416
} while (*ancestor != *module);
@@ -617,9 +621,9 @@ MaybeHandle<Object> SourceTextModule::EvaluateMaybeAsync(
617621
CHECK(module->status() == kInstantiated || module->status() == kEvaluated);
618622

619623
// 3. If module.[[Status]] is "evaluated", set module to
620-
// GetAsyncCycleRoot(module).
624+
// module.[[CycleRoot]].
621625
if (module->status() == kEvaluated) {
622-
module = GetAsyncCycleRoot(isolate, module);
626+
module = module->GetCycleRoot(isolate);
623627
}
624628

625629
// 4. If module.[[TopLevelCapability]] is not undefined, then
@@ -734,37 +738,27 @@ void SourceTextModule::AsyncModuleExecutionFulfilled(
734738
for (int i = 0; i < module->AsyncParentModuleCount(); i++) {
735739
Handle<SourceTextModule> m = module->GetAsyncParentModule(isolate, i);
736740

737-
// a. If module.[[DFSIndex]] is not equal to module.[[DFSAncestorIndex]],
738-
// then
739-
if (module->dfs_index() != module->dfs_ancestor_index()) {
740-
// i. Assert: m.[[DFSAncestorIndex]] is equal to
741-
// module.[[DFSAncestorIndex]].
742-
DCHECK_LE(m->dfs_ancestor_index(), module->dfs_ancestor_index());
743-
}
744-
// b. Decrement m.[[PendingAsyncDependencies]] by 1.
741+
// a. Decrement m.[[PendingAsyncDependencies]] by 1.
745742
m->DecrementPendingAsyncDependencies();
746743

747-
// c. If m.[[PendingAsyncDependencies]] is 0 and m.[[EvaluationError]] is
744+
// b. If m.[[PendingAsyncDependencies]] is 0 and m.[[EvaluationError]] is
748745
// undefined, then
749746
if (!m->HasPendingAsyncDependencies() && m->status() == kEvaluated) {
750747
// i. Assert: m.[[AsyncEvaluating]] is true.
751748
DCHECK(m->async_evaluating());
752749

753-
// ii. Let cycleRoot be ! GetAsyncCycleRoot(m).
754-
auto cycle_root = GetAsyncCycleRoot(isolate, m);
755-
756-
// iii. If cycleRoot.[[EvaluationError]] is not undefined,
750+
// ii. If m.[[CycleRoot]].[[EvaluationError]] is not undefined,
757751
// return undefined.
758-
if (cycle_root->status() == kErrored) {
752+
if (m->GetCycleRoot(isolate)->status() == kErrored) {
759753
return;
760754
}
761755

762-
// iv. If m.[[Async]] is true, then
756+
// iii. If m.[[Async]] is true, then
763757
if (m->async()) {
764758
// 1. Perform ! ExecuteAsyncModule(m).
765759
ExecuteAsyncModule(isolate, m);
766760
} else {
767-
// v. Otherwise,
761+
// iv. Otherwise,
768762
// 1. Let result be m.ExecuteModule().
769763
// 2. If result is a normal completion,
770764
Handle<Object> unused_result;
@@ -1044,8 +1038,8 @@ MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
10441038
required_module->dfs_ancestor_index()));
10451039
} else {
10461040
// iv. Otherwise,
1047-
// 1. Set requiredModule to GetAsyncCycleRoot(requiredModule).
1048-
required_module = GetAsyncCycleRoot(isolate, required_module);
1041+
// 1. Set requiredModule to requiredModule.[[CycleRoot]].
1042+
required_module = required_module->GetCycleRoot(isolate);
10491043

10501044
// 2. Assert: requiredModule.[[Status]] is "evaluated".
10511045
CHECK_GE(required_module->status(), kEvaluated);
@@ -1103,43 +1097,6 @@ MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
11031097
return result;
11041098
}
11051099

1106-
Handle<SourceTextModule> SourceTextModule::GetAsyncCycleRoot(
1107-
Isolate* isolate, Handle<SourceTextModule> module) {
1108-
// 1. Assert: module.[[Status]] is "evaluated".
1109-
CHECK_GE(module->status(), kEvaluated);
1110-
1111-
// 2. If module.[[AsyncParentModules]] is an empty List, return module.
1112-
if (module->AsyncParentModuleCount() == 0) {
1113-
return module;
1114-
}
1115-
1116-
// 3. Repeat, while module.[[DFSIndex]] is greater than
1117-
// module.[[DFSAncestorIndex]],
1118-
while (module->dfs_index() > module->dfs_ancestor_index()) {
1119-
// a. Assert: module.[[AsyncParentModules]] is a non-empty List.
1120-
DCHECK_GT(module->AsyncParentModuleCount(), 0);
1121-
1122-
// b. Let nextCycleModule be the first element of
1123-
// module.[[AsyncParentModules]].
1124-
Handle<SourceTextModule> next_cycle_module =
1125-
module->GetAsyncParentModule(isolate, 0);
1126-
1127-
// c. Assert: nextCycleModule.[[DFSAncestorIndex]] is less than or equal
1128-
// to module.[[DFSAncestorIndex]].
1129-
DCHECK_LE(next_cycle_module->dfs_ancestor_index(),
1130-
module->dfs_ancestor_index());
1131-
1132-
// d. Set module to nextCycleModule
1133-
module = next_cycle_module;
1134-
}
1135-
1136-
// 4. Assert: module.[[DFSIndex]] is equal to module.[[DFSAncestorIndex]].
1137-
DCHECK_EQ(module->dfs_index(), module->dfs_ancestor_index());
1138-
1139-
// 5. Return module.
1140-
return module;
1141-
}
1142-
11431100
void SourceTextModule::Reset(Isolate* isolate,
11441101
Handle<SourceTextModule> module) {
11451102
Factory* factory = isolate->factory();

deps/v8/src/objects/source-text-module.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class SourceTextModule
7878
Handle<SourceTextModule> module,
7979
Handle<SourceTextModule> parent);
8080

81+
// Get the non-hole cycle root. Only valid when status >= kEvaluated.
82+
inline Handle<SourceTextModule> GetCycleRoot(Isolate* isolate) const;
83+
8184
// Returns a SourceTextModule, the
8285
// ith parent in depth first traversal order of a given async child.
8386
inline Handle<SourceTextModule> GetAsyncParentModule(Isolate* isolate,
@@ -163,10 +166,6 @@ class SourceTextModule
163166
Isolate* isolate, Handle<SourceTextModule> module,
164167
ZoneForwardList<Handle<SourceTextModule>>* stack, Status new_status);
165168

166-
// Implementation of spec GetAsyncCycleRoot.
167-
static V8_WARN_UNUSED_RESULT Handle<SourceTextModule> GetAsyncCycleRoot(
168-
Isolate* isolate, Handle<SourceTextModule> module);
169-
170169
// Implementation of spec ExecuteModule is broken up into
171170
// InnerExecuteAsyncModule for asynchronous modules and ExecuteModule
172171
// for synchronous modules.

deps/v8/src/objects/source-text-module.tq

+5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ extern class SourceTextModule extends Module {
2929
// a JSObject afterwards.
3030
import_meta: TheHole|JSObject;
3131

32+
// The first visited module of a cycle. For modules not in a cycle, this is
33+
// the module itself. It's the hole before the module state transitions to
34+
// kEvaluated.
35+
cycle_root: SourceTextModule|TheHole;
36+
3237
async_parent_modules: ArrayList;
3338
top_level_capability: JSPromise|Undefined;
3439

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
import "modules-skip-async-cycle-start.mjs"
8+
9+
assertEquals(globalThis.test_order, [
10+
'2', 'async before', 'async after', '1',
11+
'3', 'start',
12+
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
import "modules-skip-async-cycle-2.mjs";
8+
import "modules-skip-async-cycle-leaf.mjs";
9+
10+
if (globalThis.test_order === undefined) {
11+
globalThis.test_order = [];
12+
}
13+
globalThis.test_order.push('1');
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
import "modules-skip-async-cycle-1.mjs";
8+
9+
if (globalThis.test_order === undefined) {
10+
globalThis.test_order = [];
11+
}
12+
globalThis.test_order.push('2');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
import "modules-skip-async-cycle-2.mjs";
8+
9+
if (globalThis.test_order === undefined) {
10+
globalThis.test_order = [];
11+
}
12+
globalThis.test_order.push('3');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
if (globalThis.test_order === undefined) {
8+
globalThis.test_order = [];
9+
}
10+
11+
globalThis.test_order.push('async before');
12+
await 0;
13+
globalThis.test_order.push('async after');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2021 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+
// Flags: --harmony-top-level-await
6+
7+
import "modules-skip-async-cycle-1.mjs";
8+
import "modules-skip-async-cycle-3.mjs";
9+
10+
if (globalThis.test_order === undefined) {
11+
globalThis.test_order = [];
12+
}
13+
globalThis.test_order.push('start');

0 commit comments

Comments
 (0)