@@ -76,6 +76,15 @@ class Module::ResolveSet
76
76
Zone* zone_;
77
77
};
78
78
79
+ struct SourceTextModule ::AsyncEvaluatingOrdinalCompare {
80
+ bool operator ()(Handle <SourceTextModule> lhs,
81
+ Handle <SourceTextModule> rhs) const {
82
+ DCHECK (lhs->IsAsyncEvaluating ());
83
+ DCHECK (rhs->IsAsyncEvaluating ());
84
+ return lhs->async_evaluating_ordinal () < rhs->async_evaluating_ordinal ();
85
+ }
86
+ };
87
+
79
88
SharedFunctionInfo SourceTextModule::GetSharedFunctionInfo () const {
80
89
DisallowHeapAllocation no_alloc;
81
90
switch (status ()) {
@@ -580,6 +589,58 @@ void SourceTextModule::FetchStarExports(Isolate* isolate,
580
589
module->set_exports (*exports);
581
590
}
582
591
592
+ void SourceTextModule::GatherAsyncParentCompletions (
593
+ Isolate* isolate, Zone* zone, Handle <SourceTextModule> start,
594
+ AsyncParentCompletionSet* exec_list) {
595
+ // The spec algorithm is recursive. It is transformed to an equivalent
596
+ // iterative one here.
597
+ ZoneStack<Handle <SourceTextModule>> worklist (zone);
598
+ worklist.push (start);
599
+
600
+ while (!worklist.empty ()) {
601
+ Handle <SourceTextModule> module = worklist.top ();
602
+ worklist.pop ();
603
+
604
+ // 1. Assert: module.[[Status]] is evaluated.
605
+ DCHECK_EQ (module->status (), kEvaluated );
606
+
607
+ // 2. For each Module m of module.[[AsyncParentModules]], do
608
+ for (int i = module->AsyncParentModuleCount (); i-- > 0 ;) {
609
+ Handle <SourceTextModule> m = module->GetAsyncParentModule (isolate, i);
610
+
611
+ // a. If execList does not contain m and
612
+ // m.[[CycleRoot]].[[EvaluationError]] is empty, then
613
+ if (exec_list->find (m) == exec_list->end () &&
614
+ m->GetCycleRoot (isolate)->status () != kErrored ) {
615
+ // i. Assert: m.[[EvaluationError]] is empty.
616
+ DCHECK_NE (m->status (), kErrored );
617
+
618
+ // ii. Assert: m.[[AsyncEvaluating]] is true.
619
+ DCHECK (m->IsAsyncEvaluating ());
620
+
621
+ // iii. Assert: m.[[PendingAsyncDependencies]] > 0.
622
+ DCHECK (m->HasPendingAsyncDependencies ());
623
+
624
+ // iv. Set m.[[PendingAsyncDependencies]] to
625
+ // m.[[PendingAsyncDependencies]] - 1.
626
+ m->DecrementPendingAsyncDependencies ();
627
+
628
+ // v. If m.[[PendingAsyncDependencies]] is equal to 0, then
629
+ if (!m->HasPendingAsyncDependencies ()) {
630
+ // 1. Append m to execList.
631
+ exec_list->insert (m);
632
+
633
+ // 2. If m.[[Async]] is false,
634
+ // perform ! GatherAsyncParentCompletions(m, execList).
635
+ if (!m->async ()) worklist.push (m);
636
+ }
637
+ }
638
+ }
639
+ }
640
+
641
+ // 3. Return undefined.
642
+ }
643
+
583
644
Handle <JSModuleNamespace> SourceTextModule::GetModuleNamespace (
584
645
Isolate* isolate, Handle <SourceTextModule> module, int module_request) {
585
646
Handle <Module> requested_module (
@@ -663,7 +724,7 @@ MaybeHandle<Object> SourceTextModule::EvaluateMaybeAsync(
663
724
CHECK_EQ (module->status (), kEvaluated );
664
725
665
726
// b. If module.[[AsyncEvaluating]] is false, then
666
- if (!module->async_evaluating ()) {
727
+ if (!module->IsAsyncEvaluating ()) {
667
728
// i. Perform ! Call(capability.[[Resolve]], undefined,
668
729
// «undefined»).
669
730
JSPromise::Resolve (capability, isolate->factory ()->undefined_value ())
@@ -716,81 +777,97 @@ MaybeHandle<Object> SourceTextModule::Evaluate(
716
777
717
778
void SourceTextModule::AsyncModuleExecutionFulfilled (
718
779
Isolate* isolate, Handle <SourceTextModule> module) {
719
- // 1. Assert: module.[[Status ]] is "evaluated" .
720
- CHECK (module->status () == kEvaluated || module-> status () == kErrored );
780
+ // 1. Assert: module.[[AsyncEvaluating ]] is true .
781
+ DCHECK (module->IsAsyncEvaluating () );
721
782
722
- // 2. If module.[[AsyncEvaluating]] is false,
723
- if (!module->async_evaluating ()) {
724
- // a. Assert: module.[[EvaluationError]] is not undefined.
725
- CHECK_EQ (module->status (), kErrored );
726
-
727
- // b. Return undefined.
728
- return ;
729
- }
730
-
731
- // 3. Assert: module.[[EvaluationError]] is undefined.
783
+ // 2. Assert: module.[[EvaluationError]] is undefined.
732
784
CHECK_EQ (module->status (), kEvaluated );
733
785
734
- // 4. Set module.[[AsyncEvaluating]] to false.
735
- module->set_async_evaluating (false );
786
+ // 3. Set module.[[AsyncEvaluating]] to false.
787
+ isolate->DidFinishModuleAsyncEvaluation (module->async_evaluating_ordinal ());
788
+ module->set_async_evaluating_ordinal (kAsyncEvaluateDidFinish );
736
789
737
- // 5. For each Module m of module.[[AsyncParentModules]], do
738
- for (int i = 0 ; i < module->AsyncParentModuleCount (); i++) {
739
- Handle <SourceTextModule> m = module->GetAsyncParentModule (isolate, i);
790
+ // 4. If module.[[TopLevelCapability]] is not empty, then
791
+ if (!module->top_level_capability ().IsUndefined (isolate)) {
792
+ // a. Assert: module.[[CycleRoot]] is equal to module.
793
+ DCHECK_EQ (*module->GetCycleRoot (isolate), *module);
740
794
741
- // a. Decrement m.[[PendingAsyncDependencies]] by 1.
742
- m->DecrementPendingAsyncDependencies ();
795
+ // i. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined,
796
+ // «undefined»).
797
+ Handle <JSPromise> capability (
798
+ JSPromise::cast (module->top_level_capability ()), isolate);
799
+ JSPromise::Resolve (capability, isolate->factory ()->undefined_value ())
800
+ .ToHandleChecked ();
801
+ }
743
802
744
- // b. If m.[[PendingAsyncDependencies]] is 0 and m.[[EvaluationError]] is
745
- // undefined, then
746
- if (!m->HasPendingAsyncDependencies () && m->status () == kEvaluated ) {
747
- // i. Assert: m.[[AsyncEvaluating]] is true.
748
- DCHECK (m->async_evaluating ());
803
+ // 5. Let execList be a new empty List.
804
+ Zone zone (isolate->allocator (), ZONE_NAME);
805
+ AsyncParentCompletionSet exec_list (&zone);
749
806
750
- // ii. If m.[[CycleRoot]].[[EvaluationError]] is not undefined,
751
- // return undefined.
752
- if (m->GetCycleRoot (isolate)->status () == kErrored ) {
753
- return ;
754
- }
807
+ // 6. Perform ! GatherAsyncParentCompletions(module, execList).
808
+ GatherAsyncParentCompletions (isolate, &zone, module, &exec_list);
809
+
810
+ // 7. Let sortedExecList be a List of elements that are the elements of
811
+ // execList, in the order in which they had their [[AsyncEvaluating]]
812
+ // fields set to true in InnerModuleEvaluation.
813
+ //
814
+ // This step is implemented by AsyncParentCompletionSet, which is a set
815
+ // ordered on async_evaluating_ordinal.
755
816
756
- // iii. If m.[[Async]] is true, then
757
- if (m->async ()) {
758
- // 1. Perform ! ExecuteAsyncModule(m).
759
- ExecuteAsyncModule (isolate, m);
817
+ // 8. Assert: All elements of sortedExecList have their [[AsyncEvaluating]]
818
+ // field set to true, [[PendingAsyncDependencies]] field set to 0 and
819
+ // [[EvaluationError]] field set to undefined.
820
+ #ifdef DEBUG
821
+ for (Handle <SourceTextModule> m : exec_list) {
822
+ DCHECK (m->IsAsyncEvaluating ());
823
+ DCHECK (!m->HasPendingAsyncDependencies ());
824
+ DCHECK_NE (m->status (), kErrored );
825
+ }
826
+ #endif
827
+
828
+ // 9. For each Module m of sortedExecList, do
829
+ for (Handle <SourceTextModule> m : exec_list) {
830
+ // i. If m.[[AsyncEvaluating]] is false, then
831
+ if (!m->IsAsyncEvaluating ()) {
832
+ // a. Assert: m.[[EvaluatingError]] is not empty.
833
+ DCHECK_EQ (m->status (), kErrored );
834
+ } else if (m->async ()) {
835
+ // ii. Otherwise, if m.[[Async]] is *true*, then
836
+ // a. Perform ! ExecuteAsyncModule(m).
837
+ ExecuteAsyncModule (isolate, m);
838
+ } else {
839
+ // iii. Otherwise,
840
+ // a. Let _result_ be m.ExecuteModule().
841
+ Handle <Object> unused_result;
842
+ // b. If _result_ is an abrupt completion,
843
+ if (!ExecuteModule (isolate, m).ToHandle (&unused_result)) {
844
+ // 1. Perform ! AsyncModuleExecutionRejected(m, result.[[Value]]).
845
+ Handle <Object> exception (isolate->pending_exception (), isolate);
846
+ isolate->clear_pending_exception ();
847
+ AsyncModuleExecutionRejected (isolate, m, exception );
760
848
} else {
761
- // iv. Otherwise,
762
- // 1. Let result be m.ExecuteModule().
763
- // 2. If result is a normal completion,
764
- Handle <Object> unused_result;
765
- if (ExecuteModule (isolate, m).ToHandle (&unused_result)) {
766
- // a. Perform ! AsyncModuleExecutionFulfilled(m).
767
- AsyncModuleExecutionFulfilled (isolate, m);
768
- } else {
769
- // 3. Otherwise,
770
- // a. Perform ! AsyncModuleExecutionRejected(m,
771
- // result.[[Value]]).
772
- Handle <Object> exception (isolate->pending_exception (), isolate);
773
- isolate->clear_pending_exception ();
774
- AsyncModuleExecutionRejected (isolate, m, exception );
849
+ // c. Otherwise,
850
+ // 1. Set m.[[AsyncEvaluating]] to false.
851
+ isolate->DidFinishModuleAsyncEvaluation (m->async_evaluating_ordinal ());
852
+ m->set_async_evaluating_ordinal (kAsyncEvaluateDidFinish );
853
+
854
+ // 2. If m.[[TopLevelCapability]] is not empty, then
855
+ if (!m->top_level_capability ().IsUndefined (isolate)) {
856
+ // i. Assert: m.[[CycleRoot]] is equal to m.
857
+ DCHECK_EQ (*m->GetCycleRoot (isolate), *m);
858
+
859
+ // ii. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]],
860
+ // undefined, «undefined»).
861
+ Handle <JSPromise> capability (
862
+ JSPromise::cast (m->top_level_capability ()), isolate);
863
+ JSPromise::Resolve (capability, isolate->factory ()->undefined_value ())
864
+ .ToHandleChecked ();
775
865
}
776
866
}
777
867
}
778
868
}
779
869
780
- // 6. If module.[[TopLevelCapability]] is not undefined, then
781
- if (!module->top_level_capability ().IsUndefined (isolate)) {
782
- // a. Assert: module.[[DFSIndex]] is equal to module.[[DFSAncestorIndex]].
783
- DCHECK_EQ (module->dfs_index (), module->dfs_ancestor_index ());
784
-
785
- // b. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]],
786
- // undefined, «undefined»).
787
- Handle <JSPromise> capability (
788
- JSPromise::cast (module->top_level_capability ()), isolate);
789
- JSPromise::Resolve (capability, isolate->factory ()->undefined_value ())
790
- .ToHandleChecked ();
791
- }
792
-
793
- // 7. Return undefined.
870
+ // 10. Return undefined.
794
871
}
795
872
796
873
void SourceTextModule::AsyncModuleExecutionRejected (
@@ -802,7 +879,7 @@ void SourceTextModule::AsyncModuleExecutionRejected(
802
879
CHECK (module->status () == kEvaluated || module->status () == kErrored );
803
880
804
881
// 2. If module.[[AsyncEvaluating]] is false,
805
- if (!module->async_evaluating ()) {
882
+ if (!module->IsAsyncEvaluating ()) {
806
883
// a. Assert: module.[[EvaluationError]] is not undefined.
807
884
CHECK_EQ (module->status (), kErrored );
808
885
@@ -814,7 +891,8 @@ void SourceTextModule::AsyncModuleExecutionRejected(
814
891
module->RecordError (isolate, exception );
815
892
816
893
// 5. Set module.[[AsyncEvaluating]] to false.
817
- module->set_async_evaluating (false );
894
+ isolate->DidFinishModuleAsyncEvaluation (module->async_evaluating_ordinal ());
895
+ module->set_async_evaluating_ordinal (kAsyncEvaluateDidFinish );
818
896
819
897
// 6. For each Module m of module.[[AsyncParentModules]], do
820
898
for (int i = 0 ; i < module->AsyncParentModuleCount (); i++) {
@@ -833,8 +911,8 @@ void SourceTextModule::AsyncModuleExecutionRejected(
833
911
834
912
// 7. If module.[[TopLevelCapability]] is not undefined, then
835
913
if (!module->top_level_capability ().IsUndefined (isolate)) {
836
- // a. Assert: module.[[DFSIndex ]] is equal to module.[[DFSAncestorIndex]] .
837
- DCHECK ( module->dfs_index () == module-> dfs_ancestor_index () );
914
+ // a. Assert: module.[[CycleRoot ]] is equal to module.
915
+ DCHECK_EQ (* module->GetCycleRoot (isolate), * module);
838
916
839
917
// b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]],
840
918
// undefined, «error»).
@@ -855,7 +933,8 @@ void SourceTextModule::ExecuteAsyncModule(Isolate* isolate,
855
933
DCHECK (module->async ());
856
934
857
935
// 3. Set module.[[AsyncEvaluating]] to true.
858
- module->set_async_evaluating (true );
936
+ module->set_async_evaluating_ordinal (
937
+ isolate->NextModuleAsyncEvaluatingOrdinal ());
859
938
860
939
// 4. Let capability be ! NewPromiseCapability(%Promise%).
861
940
Handle <JSPromise> capability = isolate->factory ()->NewJSPromise ();
@@ -1057,7 +1136,7 @@ MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
1057
1136
}
1058
1137
}
1059
1138
// v. If requiredModule.[[AsyncEvaluating]] is true, then
1060
- if (required_module->async_evaluating ()) {
1139
+ if (required_module->IsAsyncEvaluating ()) {
1061
1140
// 1. Set module.[[PendingAsyncDependencies]] to
1062
1141
// module.[[PendingAsyncDependencies]] + 1.
1063
1142
module->IncrementPendingAsyncDependencies ();
@@ -1079,16 +1158,26 @@ MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
1079
1158
// synchronous modules, but return undefined for AsyncModules.
1080
1159
Handle <Object> result = isolate->factory ()->undefined_value ();
1081
1160
1082
- // 14. If module.[[PendingAsyncDependencies]] is > 0, set
1083
- // module.[[AsyncEvaluating]] to true.
1084
- if (module->HasPendingAsyncDependencies ()) {
1085
- module->set_async_evaluating (true );
1086
- } else if (module->async ()) {
1087
- // 15. Otherwise, if module.[[Async]] is true,
1088
- // perform ! ExecuteAsyncModule(module).
1089
- SourceTextModule::ExecuteAsyncModule (isolate, module);
1161
+ // 14. If module.[[PendingAsyncDependencies]] > 0 or module.[[Async]] is
1162
+ // true, then
1163
+ if (module->HasPendingAsyncDependencies () || module->async ()) {
1164
+ // a. Assert: module.[[AsyncEvaluating]] is false and was never previously
1165
+ // set to true.
1166
+ DCHECK_EQ (module->async_evaluating_ordinal (), kNotAsyncEvaluated );
1167
+
1168
+ // b. Set module.[[AsyncEvaluating]] to true.
1169
+ // NOTE: The order in which modules transition to async evaluating is
1170
+ // significant.
1171
+ module->set_async_evaluating_ordinal (
1172
+ isolate->NextModuleAsyncEvaluatingOrdinal ());
1173
+
1174
+ // c. If module.[[PendingAsyncDependencies]] is 0,
1175
+ // perform ! ExecuteAsyncModule(_module_).
1176
+ if (!module->HasPendingAsyncDependencies ()) {
1177
+ SourceTextModule::ExecuteAsyncModule (isolate, module);
1178
+ }
1090
1179
} else {
1091
- // 16 . Otherwise, perform ? module.ExecuteModule().
1180
+ // 15 . Otherwise, perform ? module.ExecuteModule().
1092
1181
ASSIGN_RETURN_ON_EXCEPTION (isolate, result, ExecuteModule (isolate, module),
1093
1182
Object);
1094
1183
}
0 commit comments