• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 #include "src/objects/source-text-module.h"
6 
7 #include "src/api/api-inl.h"
8 #include "src/ast/modules.h"
9 #include "src/builtins/accessors.h"
10 #include "src/objects/js-generator-inl.h"
11 #include "src/objects/module-inl.h"
12 #include "src/objects/objects-inl.h"
13 #include "src/objects/shared-function-info.h"
14 #include "src/utils/ostreams.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 struct StringHandleHash {
operator ()v8::internal::StringHandleHash20   V8_INLINE size_t operator()(Handle<String> string) const {
21     return string->Hash();
22   }
23 };
24 
25 struct StringHandleEqual {
operator ()v8::internal::StringHandleEqual26   V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
27     return lhs->Equals(*rhs);
28   }
29 };
30 
31 class UnorderedStringSet
32     : public std::unordered_set<Handle<String>, StringHandleHash,
33                                 StringHandleEqual,
34                                 ZoneAllocator<Handle<String>>> {
35  public:
UnorderedStringSet(Zone * zone)36   explicit UnorderedStringSet(Zone* zone)
37       : std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
38                            ZoneAllocator<Handle<String>>>(
39             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
40             ZoneAllocator<Handle<String>>(zone)) {}
41 };
42 
43 class UnorderedStringMap
44     : public std::unordered_map<
45           Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
46           ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>> {
47  public:
UnorderedStringMap(Zone * zone)48   explicit UnorderedStringMap(Zone* zone)
49       : std::unordered_map<
50             Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
51             ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>>(
52             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
53             ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>(
54                 zone)) {}
55 };
56 
57 class Module::ResolveSet
58     : public std::unordered_map<
59           Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
60           ModuleHandleEqual,
61           ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>> {
62  public:
ResolveSet(Zone * zone)63   explicit ResolveSet(Zone* zone)
64       : std::unordered_map<Handle<Module>, UnorderedStringSet*,
65                            ModuleHandleHash, ModuleHandleEqual,
66                            ZoneAllocator<std::pair<const Handle<Module>,
67                                                    UnorderedStringSet*>>>(
68             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
69             ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>(
70                 zone)),
71         zone_(zone) {}
72 
zone() const73   Zone* zone() const { return zone_; }
74 
75  private:
76   Zone* zone_;
77 };
78 
GetSharedFunctionInfo() const79 SharedFunctionInfo SourceTextModule::GetSharedFunctionInfo() const {
80   DisallowHeapAllocation no_alloc;
81   switch (status()) {
82     case kUninstantiated:
83     case kPreInstantiating:
84       DCHECK(code().IsSharedFunctionInfo());
85       return SharedFunctionInfo::cast(code());
86     case kInstantiating:
87       DCHECK(code().IsJSFunction());
88       return JSFunction::cast(code()).shared();
89     case kInstantiated:
90     case kEvaluating:
91     case kEvaluated:
92       DCHECK(code().IsJSGeneratorObject());
93       return JSGeneratorObject::cast(code()).function().shared();
94     case kErrored:
95       UNREACHABLE();
96   }
97 
98   UNREACHABLE();
99 }
100 
ExportIndex(int cell_index)101 int SourceTextModule::ExportIndex(int cell_index) {
102   DCHECK_EQ(SourceTextModuleDescriptor::GetCellIndexKind(cell_index),
103             SourceTextModuleDescriptor::kExport);
104   return cell_index - 1;
105 }
106 
ImportIndex(int cell_index)107 int SourceTextModule::ImportIndex(int cell_index) {
108   DCHECK_EQ(SourceTextModuleDescriptor::GetCellIndexKind(cell_index),
109             SourceTextModuleDescriptor::kImport);
110   return -cell_index - 1;
111 }
112 
CreateIndirectExport(Isolate * isolate,Handle<SourceTextModule> module,Handle<String> name,Handle<SourceTextModuleInfoEntry> entry)113 void SourceTextModule::CreateIndirectExport(
114     Isolate* isolate, Handle<SourceTextModule> module, Handle<String> name,
115     Handle<SourceTextModuleInfoEntry> entry) {
116   Handle<ObjectHashTable> exports(module->exports(), isolate);
117   DCHECK(exports->Lookup(name).IsTheHole(isolate));
118   exports = ObjectHashTable::Put(exports, name, entry);
119   module->set_exports(*exports);
120 }
121 
CreateExport(Isolate * isolate,Handle<SourceTextModule> module,int cell_index,Handle<FixedArray> names)122 void SourceTextModule::CreateExport(Isolate* isolate,
123                                     Handle<SourceTextModule> module,
124                                     int cell_index, Handle<FixedArray> names) {
125   DCHECK_LT(0, names->length());
126   Handle<Cell> cell =
127       isolate->factory()->NewCell(isolate->factory()->undefined_value());
128   module->regular_exports().set(ExportIndex(cell_index), *cell);
129 
130   Handle<ObjectHashTable> exports(module->exports(), isolate);
131   for (int i = 0, n = names->length(); i < n; ++i) {
132     Handle<String> name(String::cast(names->get(i)), isolate);
133     DCHECK(exports->Lookup(name).IsTheHole(isolate));
134     exports = ObjectHashTable::Put(exports, name, cell);
135   }
136   module->set_exports(*exports);
137 }
138 
GetCell(int cell_index)139 Cell SourceTextModule::GetCell(int cell_index) {
140   DisallowHeapAllocation no_gc;
141   Object cell;
142   switch (SourceTextModuleDescriptor::GetCellIndexKind(cell_index)) {
143     case SourceTextModuleDescriptor::kImport:
144       cell = regular_imports().get(ImportIndex(cell_index));
145       break;
146     case SourceTextModuleDescriptor::kExport:
147       cell = regular_exports().get(ExportIndex(cell_index));
148       break;
149     case SourceTextModuleDescriptor::kInvalid:
150       UNREACHABLE();
151       break;
152   }
153   return Cell::cast(cell);
154 }
155 
LoadVariable(Isolate * isolate,Handle<SourceTextModule> module,int cell_index)156 Handle<Object> SourceTextModule::LoadVariable(Isolate* isolate,
157                                               Handle<SourceTextModule> module,
158                                               int cell_index) {
159   return handle(module->GetCell(cell_index).value(), isolate);
160 }
161 
StoreVariable(Handle<SourceTextModule> module,int cell_index,Handle<Object> value)162 void SourceTextModule::StoreVariable(Handle<SourceTextModule> module,
163                                      int cell_index, Handle<Object> value) {
164   DisallowHeapAllocation no_gc;
165   DCHECK_EQ(SourceTextModuleDescriptor::GetCellIndexKind(cell_index),
166             SourceTextModuleDescriptor::kExport);
167   module->GetCell(cell_index).set_value(*value);
168 }
169 
ResolveExport(Isolate * isolate,Handle<SourceTextModule> module,Handle<String> module_specifier,Handle<String> export_name,MessageLocation loc,bool must_resolve,Module::ResolveSet * resolve_set)170 MaybeHandle<Cell> SourceTextModule::ResolveExport(
171     Isolate* isolate, Handle<SourceTextModule> module,
172     Handle<String> module_specifier, Handle<String> export_name,
173     MessageLocation loc, bool must_resolve, Module::ResolveSet* resolve_set) {
174   Handle<Object> object(module->exports().Lookup(export_name), isolate);
175   if (object->IsCell()) {
176     // Already resolved (e.g. because it's a local export).
177     return Handle<Cell>::cast(object);
178   }
179 
180   // Check for cycle before recursing.
181   {
182     // Attempt insertion with a null string set.
183     auto result = resolve_set->insert({module, nullptr});
184     UnorderedStringSet*& name_set = result.first->second;
185     if (result.second) {
186       // |module| wasn't in the map previously, so allocate a new name set.
187       Zone* zone = resolve_set->zone();
188       name_set = zone->New<UnorderedStringSet>(zone);
189     } else if (name_set->count(export_name)) {
190       // Cycle detected.
191       if (must_resolve) {
192         return isolate->ThrowAt<Cell>(
193             isolate->factory()->NewSyntaxError(
194                 MessageTemplate::kCyclicModuleDependency, export_name,
195                 module_specifier),
196             &loc);
197       }
198       return MaybeHandle<Cell>();
199     }
200     name_set->insert(export_name);
201   }
202 
203   if (object->IsSourceTextModuleInfoEntry()) {
204     // Not yet resolved indirect export.
205     Handle<SourceTextModuleInfoEntry> entry =
206         Handle<SourceTextModuleInfoEntry>::cast(object);
207     Handle<String> import_name(String::cast(entry->import_name()), isolate);
208     Handle<Script> script(module->script(), isolate);
209     MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
210 
211     Handle<Cell> cell;
212     if (!ResolveImport(isolate, module, import_name, entry->module_request(),
213                        new_loc, true, resolve_set)
214              .ToHandle(&cell)) {
215       DCHECK(isolate->has_pending_exception());
216       return MaybeHandle<Cell>();
217     }
218 
219     // The export table may have changed but the entry in question should be
220     // unchanged.
221     Handle<ObjectHashTable> exports(module->exports(), isolate);
222     DCHECK(exports->Lookup(export_name).IsSourceTextModuleInfoEntry());
223 
224     exports = ObjectHashTable::Put(exports, export_name, cell);
225     module->set_exports(*exports);
226     return cell;
227   }
228 
229   DCHECK(object->IsTheHole(isolate));
230   return SourceTextModule::ResolveExportUsingStarExports(
231       isolate, module, module_specifier, export_name, loc, must_resolve,
232       resolve_set);
233 }
234 
ResolveImport(Isolate * isolate,Handle<SourceTextModule> module,Handle<String> name,int module_request_index,MessageLocation loc,bool must_resolve,Module::ResolveSet * resolve_set)235 MaybeHandle<Cell> SourceTextModule::ResolveImport(
236     Isolate* isolate, Handle<SourceTextModule> module, Handle<String> name,
237     int module_request_index, MessageLocation loc, bool must_resolve,
238     Module::ResolveSet* resolve_set) {
239   Handle<Module> requested_module(
240       Module::cast(module->requested_modules().get(module_request_index)),
241       isolate);
242   Handle<ModuleRequest> module_request(
243       ModuleRequest::cast(
244           module->info().module_requests().get(module_request_index)),
245       isolate);
246   Handle<String> module_specifier(String::cast(module_request->specifier()),
247                                   isolate);
248   MaybeHandle<Cell> result =
249       Module::ResolveExport(isolate, requested_module, module_specifier, name,
250                             loc, must_resolve, resolve_set);
251   DCHECK_IMPLIES(isolate->has_pending_exception(), result.is_null());
252   return result;
253 }
254 
ResolveExportUsingStarExports(Isolate * isolate,Handle<SourceTextModule> module,Handle<String> module_specifier,Handle<String> export_name,MessageLocation loc,bool must_resolve,Module::ResolveSet * resolve_set)255 MaybeHandle<Cell> SourceTextModule::ResolveExportUsingStarExports(
256     Isolate* isolate, Handle<SourceTextModule> module,
257     Handle<String> module_specifier, Handle<String> export_name,
258     MessageLocation loc, bool must_resolve, Module::ResolveSet* resolve_set) {
259   if (!export_name->Equals(ReadOnlyRoots(isolate).default_string())) {
260     // Go through all star exports looking for the given name.  If multiple star
261     // exports provide the name, make sure they all map it to the same cell.
262     Handle<Cell> unique_cell;
263     Handle<FixedArray> special_exports(module->info().special_exports(),
264                                        isolate);
265     for (int i = 0, n = special_exports->length(); i < n; ++i) {
266       i::Handle<i::SourceTextModuleInfoEntry> entry(
267           i::SourceTextModuleInfoEntry::cast(special_exports->get(i)), isolate);
268       if (!entry->export_name().IsUndefined(isolate)) {
269         continue;  // Indirect export.
270       }
271 
272       Handle<Script> script(module->script(), isolate);
273       MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
274 
275       Handle<Cell> cell;
276       if (ResolveImport(isolate, module, export_name, entry->module_request(),
277                         new_loc, false, resolve_set)
278               .ToHandle(&cell)) {
279         if (unique_cell.is_null()) unique_cell = cell;
280         if (*unique_cell != *cell) {
281           return isolate->ThrowAt<Cell>(isolate->factory()->NewSyntaxError(
282                                             MessageTemplate::kAmbiguousExport,
283                                             module_specifier, export_name),
284                                         &loc);
285         }
286       } else if (isolate->has_pending_exception()) {
287         return MaybeHandle<Cell>();
288       }
289     }
290 
291     if (!unique_cell.is_null()) {
292       // Found a unique star export for this name.
293       Handle<ObjectHashTable> exports(module->exports(), isolate);
294       DCHECK(exports->Lookup(export_name).IsTheHole(isolate));
295       exports = ObjectHashTable::Put(exports, export_name, unique_cell);
296       module->set_exports(*exports);
297       return unique_cell;
298     }
299   }
300 
301   // Unresolvable.
302   if (must_resolve) {
303     return isolate->ThrowAt<Cell>(
304         isolate->factory()->NewSyntaxError(MessageTemplate::kUnresolvableExport,
305                                            module_specifier, export_name),
306         &loc);
307   }
308   return MaybeHandle<Cell>();
309 }
310 
PrepareInstantiate(Isolate * isolate,Handle<SourceTextModule> module,v8::Local<v8::Context> context,v8::Module::ResolveCallback callback)311 bool SourceTextModule::PrepareInstantiate(
312     Isolate* isolate, Handle<SourceTextModule> module,
313     v8::Local<v8::Context> context, v8::Module::ResolveCallback callback) {
314   // Obtain requested modules.
315   Handle<SourceTextModuleInfo> module_info(module->info(), isolate);
316   Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
317   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
318   for (int i = 0, length = module_requests->length(); i < length; ++i) {
319     Handle<ModuleRequest> module_request(
320         ModuleRequest::cast(module_requests->get(i)), isolate);
321     Handle<String> specifier(module_request->specifier(), isolate);
322     // TODO(v8:10958) Pass import assertions to the callback
323     v8::Local<v8::Module> api_requested_module;
324     if (!callback(context, v8::Utils::ToLocal(specifier),
325                   v8::Utils::ToLocal(Handle<Module>::cast(module)))
326              .ToLocal(&api_requested_module)) {
327       isolate->PromoteScheduledException();
328       return false;
329     }
330     Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
331     requested_modules->set(i, *requested_module);
332   }
333 
334   // Recurse.
335   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
336     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
337                                     isolate);
338     if (!Module::PrepareInstantiate(isolate, requested_module, context,
339                                     callback)) {
340       return false;
341     }
342   }
343 
344   // Set up local exports.
345   // TODO(neis): Create regular_exports array here instead of in factory method?
346   for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
347     int cell_index = module_info->RegularExportCellIndex(i);
348     Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
349                                     isolate);
350     CreateExport(isolate, module, cell_index, export_names);
351   }
352 
353   // Partially set up indirect exports.
354   // For each indirect export, we create the appropriate slot in the export
355   // table and store its SourceTextModuleInfoEntry there.  When we later find
356   // the correct Cell in the module that actually provides the value, we replace
357   // the SourceTextModuleInfoEntry by that Cell (see ResolveExport).
358   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
359   for (int i = 0, n = special_exports->length(); i < n; ++i) {
360     Handle<SourceTextModuleInfoEntry> entry(
361         SourceTextModuleInfoEntry::cast(special_exports->get(i)), isolate);
362     Handle<Object> export_name(entry->export_name(), isolate);
363     if (export_name->IsUndefined(isolate)) continue;  // Star export.
364     CreateIndirectExport(isolate, module, Handle<String>::cast(export_name),
365                          entry);
366   }
367 
368   DCHECK_EQ(module->status(), kPreInstantiating);
369   return true;
370 }
371 
RunInitializationCode(Isolate * isolate,Handle<SourceTextModule> module)372 bool SourceTextModule::RunInitializationCode(Isolate* isolate,
373                                              Handle<SourceTextModule> module) {
374   DCHECK_EQ(module->status(), kInstantiating);
375   Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
376   DCHECK_EQ(MODULE_SCOPE, function->shared().scope_info().scope_type());
377   Handle<Object> receiver = isolate->factory()->undefined_value();
378 
379   Handle<ScopeInfo> scope_info(function->shared().scope_info(), isolate);
380   Handle<Context> context = isolate->factory()->NewModuleContext(
381       module, isolate->native_context(), scope_info);
382   function->set_context(*context);
383 
384   MaybeHandle<Object> maybe_generator =
385       Execution::Call(isolate, function, receiver, 0, {});
386   Handle<Object> generator;
387   if (!maybe_generator.ToHandle(&generator)) {
388     DCHECK(isolate->has_pending_exception());
389     return false;
390   }
391   DCHECK_EQ(*function, Handle<JSGeneratorObject>::cast(generator)->function());
392   module->set_code(JSGeneratorObject::cast(*generator));
393   return true;
394 }
395 
MaybeTransitionComponent(Isolate * isolate,Handle<SourceTextModule> module,ZoneForwardList<Handle<SourceTextModule>> * stack,Status new_status)396 bool SourceTextModule::MaybeTransitionComponent(
397     Isolate* isolate, Handle<SourceTextModule> module,
398     ZoneForwardList<Handle<SourceTextModule>>* stack, Status new_status) {
399   DCHECK(new_status == kInstantiated || new_status == kEvaluated);
400   SLOW_DCHECK(
401       // {module} is on the {stack}.
402       std::count_if(stack->begin(), stack->end(),
403                     [&](Handle<Module> m) { return *m == *module; }) == 1);
404   DCHECK_LE(module->dfs_ancestor_index(), module->dfs_index());
405   if (module->dfs_ancestor_index() == module->dfs_index()) {
406     // This is the root of its strongly connected component.
407     Handle<SourceTextModule> ancestor;
408     do {
409       ancestor = stack->front();
410       stack->pop_front();
411       DCHECK_EQ(ancestor->status(),
412                 new_status == kInstantiated ? kInstantiating : kEvaluating);
413       if (new_status == kInstantiated) {
414         if (!SourceTextModule::RunInitializationCode(isolate, ancestor))
415           return false;
416       }
417       ancestor->SetStatus(new_status);
418     } while (*ancestor != *module);
419   }
420   return true;
421 }
422 
FinishInstantiate(Isolate * isolate,Handle<SourceTextModule> module,ZoneForwardList<Handle<SourceTextModule>> * stack,unsigned * dfs_index,Zone * zone)423 bool SourceTextModule::FinishInstantiate(
424     Isolate* isolate, Handle<SourceTextModule> module,
425     ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index,
426     Zone* zone) {
427   // Instantiate SharedFunctionInfo and mark module as instantiating for
428   // the recursion.
429   Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
430                                     isolate);
431   Handle<JSFunction> function =
432       isolate->factory()->NewFunctionFromSharedFunctionInfo(
433           shared, isolate->native_context());
434   module->set_code(*function);
435   module->SetStatus(kInstantiating);
436   module->set_dfs_index(*dfs_index);
437   module->set_dfs_ancestor_index(*dfs_index);
438   stack->push_front(module);
439   (*dfs_index)++;
440 
441   // Recurse.
442   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
443   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
444     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
445                                     isolate);
446     if (!Module::FinishInstantiate(isolate, requested_module, stack, dfs_index,
447                                    zone)) {
448       return false;
449     }
450 
451     DCHECK_NE(requested_module->status(), kEvaluating);
452     DCHECK_GE(requested_module->status(), kInstantiating);
453     SLOW_DCHECK(
454         // {requested_module} is instantiating iff it's on the {stack}.
455         (requested_module->status() == kInstantiating) ==
456         std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
457           return *m == *requested_module;
458         }));
459 
460     if (requested_module->status() == kInstantiating) {
461       // SyntheticModules go straight to kInstantiated so this must be a
462       // SourceTextModule
463       module->set_dfs_ancestor_index(std::min(
464           module->dfs_ancestor_index(),
465           SourceTextModule::cast(*requested_module).dfs_ancestor_index()));
466     }
467   }
468 
469   Handle<Script> script(module->script(), isolate);
470   Handle<SourceTextModuleInfo> module_info(module->info(), isolate);
471 
472   // Resolve imports.
473   Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
474   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
475     Handle<SourceTextModuleInfoEntry> entry(
476         SourceTextModuleInfoEntry::cast(regular_imports->get(i)), isolate);
477     Handle<String> name(String::cast(entry->import_name()), isolate);
478     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
479     ResolveSet resolve_set(zone);
480     Handle<Cell> cell;
481     if (!ResolveImport(isolate, module, name, entry->module_request(), loc,
482                        true, &resolve_set)
483              .ToHandle(&cell)) {
484       return false;
485     }
486     module->regular_imports().set(ImportIndex(entry->cell_index()), *cell);
487   }
488 
489   // Resolve indirect exports.
490   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
491   for (int i = 0, n = special_exports->length(); i < n; ++i) {
492     Handle<SourceTextModuleInfoEntry> entry(
493         SourceTextModuleInfoEntry::cast(special_exports->get(i)), isolate);
494     Handle<Object> name(entry->export_name(), isolate);
495     if (name->IsUndefined(isolate)) continue;  // Star export.
496     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
497     ResolveSet resolve_set(zone);
498     if (ResolveExport(isolate, module, Handle<String>(),
499                       Handle<String>::cast(name), loc, true, &resolve_set)
500             .is_null()) {
501       return false;
502     }
503   }
504 
505   return MaybeTransitionComponent(isolate, module, stack, kInstantiated);
506 }
507 
FetchStarExports(Isolate * isolate,Handle<SourceTextModule> module,Zone * zone,UnorderedModuleSet * visited)508 void SourceTextModule::FetchStarExports(Isolate* isolate,
509                                         Handle<SourceTextModule> module,
510                                         Zone* zone,
511                                         UnorderedModuleSet* visited) {
512   DCHECK_GE(module->status(), Module::kInstantiating);
513 
514   if (module->module_namespace().IsJSModuleNamespace()) return;  // Shortcut.
515 
516   bool cycle = !visited->insert(module).second;
517   if (cycle) return;
518   Handle<ObjectHashTable> exports(module->exports(), isolate);
519   UnorderedStringMap more_exports(zone);
520 
521   // TODO(neis): Only allocate more_exports if there are star exports.
522   // Maybe split special_exports into indirect_exports and star_exports.
523 
524   ReadOnlyRoots roots(isolate);
525   Handle<FixedArray> special_exports(module->info().special_exports(), isolate);
526   for (int i = 0, n = special_exports->length(); i < n; ++i) {
527     Handle<SourceTextModuleInfoEntry> entry(
528         SourceTextModuleInfoEntry::cast(special_exports->get(i)), isolate);
529     if (!entry->export_name().IsUndefined(roots)) {
530       continue;  // Indirect export.
531     }
532 
533     Handle<Module> requested_module(
534         Module::cast(module->requested_modules().get(entry->module_request())),
535         isolate);
536 
537     // Recurse.
538     if (requested_module->IsSourceTextModule())
539       FetchStarExports(isolate,
540                        Handle<SourceTextModule>::cast(requested_module), zone,
541                        visited);
542 
543     // Collect all of [requested_module]'s exports that must be added to
544     // [module]'s exports (i.e. to [exports]).  We record these in
545     // [more_exports].  Ambiguities (conflicting exports) are marked by mapping
546     // the name to undefined instead of a Cell.
547     Handle<ObjectHashTable> requested_exports(requested_module->exports(),
548                                               isolate);
549     for (InternalIndex i : requested_exports->IterateEntries()) {
550       Object key;
551       if (!requested_exports->ToKey(roots, i, &key)) continue;
552       Handle<String> name(String::cast(key), isolate);
553 
554       if (name->Equals(roots.default_string())) continue;
555       if (!exports->Lookup(name).IsTheHole(roots)) continue;
556 
557       Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
558       auto insert_result = more_exports.insert(std::make_pair(name, cell));
559       if (!insert_result.second) {
560         auto it = insert_result.first;
561         if (*it->second == *cell || it->second->IsUndefined(roots)) {
562           // We already recorded this mapping before, or the name is already
563           // known to be ambiguous.  In either case, there's nothing to do.
564         } else {
565           DCHECK(it->second->IsCell());
566           // Different star exports provide different cells for this name, hence
567           // mark the name as ambiguous.
568           it->second = roots.undefined_value_handle();
569         }
570       }
571     }
572   }
573 
574   // Copy [more_exports] into [exports].
575   for (const auto& elem : more_exports) {
576     if (elem.second->IsUndefined(isolate)) continue;  // Ambiguous export.
577     DCHECK(!elem.first->Equals(ReadOnlyRoots(isolate).default_string()));
578     DCHECK(elem.second->IsCell());
579     exports = ObjectHashTable::Put(exports, elem.first, elem.second);
580   }
581   module->set_exports(*exports);
582 }
583 
GetModuleNamespace(Isolate * isolate,Handle<SourceTextModule> module,int module_request)584 Handle<JSModuleNamespace> SourceTextModule::GetModuleNamespace(
585     Isolate* isolate, Handle<SourceTextModule> module, int module_request) {
586   Handle<Module> requested_module(
587       Module::cast(module->requested_modules().get(module_request)), isolate);
588   return Module::GetModuleNamespace(isolate, requested_module);
589 }
590 
GetImportMeta(Isolate * isolate,Handle<SourceTextModule> module)591 MaybeHandle<JSObject> SourceTextModule::GetImportMeta(
592     Isolate* isolate, Handle<SourceTextModule> module) {
593   Handle<HeapObject> import_meta(module->import_meta(), isolate);
594   if (import_meta->IsTheHole(isolate)) {
595     if (!isolate->RunHostInitializeImportMetaObjectCallback(module).ToHandle(
596             &import_meta)) {
597       return {};
598     }
599     module->set_import_meta(*import_meta);
600   }
601   return Handle<JSObject>::cast(import_meta);
602 }
603 
EvaluateMaybeAsync(Isolate * isolate,Handle<SourceTextModule> module)604 MaybeHandle<Object> SourceTextModule::EvaluateMaybeAsync(
605     Isolate* isolate, Handle<SourceTextModule> module) {
606   // In the event of errored evaluation, return a rejected promise.
607   if (module->status() == kErrored) {
608     // If we have a top level capability we assume it has already been
609     // rejected, and return it here. Otherwise create a new promise and
610     // reject it with the module's exception.
611     if (module->top_level_capability().IsJSPromise()) {
612       Handle<JSPromise> top_level_capability(
613           JSPromise::cast(module->top_level_capability()), isolate);
614       DCHECK(top_level_capability->status() == Promise::kRejected &&
615              top_level_capability->result() == module->exception());
616       return top_level_capability;
617     }
618     Handle<JSPromise> capability = isolate->factory()->NewJSPromise();
619     JSPromise::Reject(capability, handle(module->exception(), isolate));
620     return capability;
621   }
622 
623   // Start of Evaluate () Concrete Method
624   // 2. Assert: module.[[Status]] is "linked" or "evaluated".
625   CHECK(module->status() == kInstantiated || module->status() == kEvaluated);
626 
627   // 3. If module.[[Status]] is "evaluated", set module to
628   //    GetAsyncCycleRoot(module).
629   if (module->status() == kEvaluated) {
630     module = GetAsyncCycleRoot(isolate, module);
631   }
632 
633   // 4. If module.[[TopLevelCapability]] is not undefined, then
634   //    a. Return module.[[TopLevelCapability]].[[Promise]].
635   if (module->top_level_capability().IsJSPromise()) {
636     return handle(JSPromise::cast(module->top_level_capability()), isolate);
637   }
638   DCHECK(module->top_level_capability().IsUndefined());
639 
640   // 6. Let capability be ! NewPromiseCapability(%Promise%).
641   Handle<JSPromise> capability = isolate->factory()->NewJSPromise();
642 
643   // 7. Set module.[[TopLevelCapability]] to capability.
644   module->set_top_level_capability(*capability);
645   DCHECK(module->top_level_capability().IsJSPromise());
646 
647   // 9. If result is an abrupt completion, then
648   Handle<Object> unused_result;
649   if (!Evaluate(isolate, module).ToHandle(&unused_result)) {
650     // If the exception was a termination exception, rejecting the promise
651     // would resume execution, and our API contract is to return an empty
652     // handle. The module's status should be set to kErrored and the
653     // exception field should be set to `null`.
654     if (!isolate->is_catchable_by_javascript(isolate->pending_exception())) {
655       DCHECK_EQ(module->status(), kErrored);
656       DCHECK_EQ(module->exception(), *isolate->factory()->null_value());
657       return {};
658     }
659 
660     //  d. Perform ! Call(capability.[[Reject]], undefined,
661     //                    «result.[[Value]]»).
662     isolate->clear_pending_exception();
663     JSPromise::Reject(capability, handle(module->exception(), isolate));
664   } else {
665     // 10. Otherwise,
666     //  a. Assert: module.[[Status]] is "evaluated"...
667     CHECK_EQ(module->status(), kEvaluated);
668 
669     //  b. If module.[[AsyncEvaluating]] is false, then
670     if (!module->async_evaluating()) {
671       //   i. Perform ! Call(capability.[[Resolve]], undefined,
672       //                     «undefined»).
673       JSPromise::Resolve(capability, isolate->factory()->undefined_value())
674           .ToHandleChecked();
675     }
676   }
677 
678   // 11. Return capability.[[Promise]].
679   return capability;
680 }
681 
Evaluate(Isolate * isolate,Handle<SourceTextModule> module)682 MaybeHandle<Object> SourceTextModule::Evaluate(
683     Isolate* isolate, Handle<SourceTextModule> module) {
684   // Evaluate () Concrete Method continued from EvaluateMaybeAsync.
685   CHECK(module->status() == kInstantiated || module->status() == kEvaluated);
686 
687   // 5. Let stack be a new empty List.
688   Zone zone(isolate->allocator(), ZONE_NAME);
689   ZoneForwardList<Handle<SourceTextModule>> stack(&zone);
690   unsigned dfs_index = 0;
691 
692   // 8. Let result be InnerModuleEvaluation(module, stack, 0).
693   // 9. If result is an abrupt completion, then
694   Handle<Object> result;
695   if (!InnerModuleEvaluation(isolate, module, &stack, &dfs_index)
696            .ToHandle(&result)) {
697     //  a. For each Cyclic Module Record m in stack, do
698     for (auto& descendant : stack) {
699       //   i. Assert: m.[[Status]] is "evaluating".
700       CHECK_EQ(descendant->status(), kEvaluating);
701       //  ii. Set m.[[Status]] to "evaluated".
702       // iii. Set m.[[EvaluationError]] to result.
703       Module::RecordErrorUsingPendingException(isolate, descendant);
704     }
705 
706 #ifdef DEBUG
707     if (isolate->is_catchable_by_javascript(isolate->pending_exception())) {
708       CHECK_EQ(module->exception(), isolate->pending_exception());
709     } else {
710       CHECK_EQ(module->exception(), *isolate->factory()->null_value());
711     }
712 #endif  // DEBUG
713   } else {
714     // 10. Otherwise,
715     //  c. Assert: stack is empty.
716     DCHECK(stack.empty());
717   }
718   return result;
719 }
720 
AsyncModuleExecutionFulfilled(Isolate * isolate,Handle<SourceTextModule> module)721 void SourceTextModule::AsyncModuleExecutionFulfilled(
722     Isolate* isolate, Handle<SourceTextModule> module) {
723   // 1. Assert: module.[[Status]] is "evaluated".
724   CHECK(module->status() == kEvaluated || module->status() == kErrored);
725 
726   // 2. If module.[[AsyncEvaluating]] is false,
727   if (!module->async_evaluating()) {
728     //  a. Assert: module.[[EvaluationError]] is not undefined.
729     CHECK_EQ(module->status(), kErrored);
730 
731     //  b. Return undefined.
732     return;
733   }
734 
735   // 3. Assert: module.[[EvaluationError]] is undefined.
736   CHECK_EQ(module->status(), kEvaluated);
737 
738   // 4. Set module.[[AsyncEvaluating]] to false.
739   module->set_async_evaluating(false);
740 
741   // 5. For each Module m of module.[[AsyncParentModules]], do
742   for (int i = 0; i < module->AsyncParentModuleCount(); i++) {
743     Handle<SourceTextModule> m = module->GetAsyncParentModule(isolate, i);
744 
745     //  a. If module.[[DFSIndex]] is not equal to module.[[DFSAncestorIndex]],
746     //     then
747     if (module->dfs_index() != module->dfs_ancestor_index()) {
748       //   i. Assert: m.[[DFSAncestorIndex]] is equal to
749       //      module.[[DFSAncestorIndex]].
750       DCHECK_LE(m->dfs_ancestor_index(), module->dfs_ancestor_index());
751     }
752     //  b. Decrement m.[[PendingAsyncDependencies]] by 1.
753     m->DecrementPendingAsyncDependencies();
754 
755     //  c. If m.[[PendingAsyncDependencies]] is 0 and m.[[EvaluationError]] is
756     //     undefined, then
757     if (!m->HasPendingAsyncDependencies() && m->status() == kEvaluated) {
758       //   i. Assert: m.[[AsyncEvaluating]] is true.
759       DCHECK(m->async_evaluating());
760 
761       //  ii. Let cycleRoot be ! GetAsyncCycleRoot(m).
762       auto cycle_root = GetAsyncCycleRoot(isolate, m);
763 
764       // iii. If cycleRoot.[[EvaluationError]] is not undefined,
765       //      return undefined.
766       if (cycle_root->status() == kErrored) {
767         return;
768       }
769 
770       //  iv. If m.[[Async]] is true, then
771       if (m->async()) {
772         //    1. Perform ! ExecuteAsyncModule(m).
773         ExecuteAsyncModule(isolate, m);
774       } else {
775         // v. Otherwise,
776         //    1. Let result be m.ExecuteModule().
777         //    2. If result is a normal completion,
778         Handle<Object> unused_result;
779         if (ExecuteModule(isolate, m).ToHandle(&unused_result)) {
780           //     a. Perform ! AsyncModuleExecutionFulfilled(m).
781           AsyncModuleExecutionFulfilled(isolate, m);
782         } else {
783           //  3. Otherwise,
784           //     a. Perform ! AsyncModuleExecutionRejected(m,
785           //                                               result.[[Value]]).
786           Handle<Object> exception(isolate->pending_exception(), isolate);
787           isolate->clear_pending_exception();
788           AsyncModuleExecutionRejected(isolate, m, exception);
789         }
790       }
791     }
792   }
793 
794   // 6. If module.[[TopLevelCapability]] is not undefined, then
795   if (!module->top_level_capability().IsUndefined(isolate)) {
796     //  a. Assert: module.[[DFSIndex]] is equal to module.[[DFSAncestorIndex]].
797     DCHECK_EQ(module->dfs_index(), module->dfs_ancestor_index());
798 
799     //  b. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]],
800     //                    undefined, «undefined»).
801     Handle<JSPromise> capability(
802         JSPromise::cast(module->top_level_capability()), isolate);
803     JSPromise::Resolve(capability, isolate->factory()->undefined_value())
804         .ToHandleChecked();
805   }
806 
807   // 7. Return undefined.
808 }
809 
AsyncModuleExecutionRejected(Isolate * isolate,Handle<SourceTextModule> module,Handle<Object> exception)810 void SourceTextModule::AsyncModuleExecutionRejected(
811     Isolate* isolate, Handle<SourceTextModule> module,
812     Handle<Object> exception) {
813   DCHECK(isolate->is_catchable_by_javascript(*exception));
814 
815   // 1. Assert: module.[[Status]] is "evaluated".
816   CHECK(module->status() == kEvaluated || module->status() == kErrored);
817 
818   // 2. If module.[[AsyncEvaluating]] is false,
819   if (!module->async_evaluating()) {
820     //  a. Assert: module.[[EvaluationError]] is not undefined.
821     CHECK_EQ(module->status(), kErrored);
822 
823     //  b. Return undefined.
824     return;
825   }
826 
827   // 4. Set module.[[EvaluationError]] to ThrowCompletion(error).
828   Module::RecordError(isolate, module, exception);
829 
830   // 5. Set module.[[AsyncEvaluating]] to false.
831   module->set_async_evaluating(false);
832 
833   // 6. For each Module m of module.[[AsyncParentModules]], do
834   for (int i = 0; i < module->AsyncParentModuleCount(); i++) {
835     Handle<SourceTextModule> m = module->GetAsyncParentModule(isolate, i);
836 
837     //  a. If module.[[DFSIndex]] is not equal to module.[[DFSAncestorIndex]],
838     //     then
839     if (module->dfs_index() != module->dfs_ancestor_index()) {
840       //   i. Assert: m.[[DFSAncestorIndex]] is equal to
841       //      module.[[DFSAncestorIndex]].
842       DCHECK_EQ(m->dfs_ancestor_index(), module->dfs_ancestor_index());
843     }
844     //  b. Perform ! AsyncModuleExecutionRejected(m, error).
845     AsyncModuleExecutionRejected(isolate, m, exception);
846   }
847 
848   // 7. If module.[[TopLevelCapability]] is not undefined, then
849   if (!module->top_level_capability().IsUndefined(isolate)) {
850     //  a. Assert: module.[[DFSIndex]] is equal to module.[[DFSAncestorIndex]].
851     DCHECK(module->dfs_index() == module->dfs_ancestor_index());
852 
853     //  b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]],
854     //                    undefined, «error»).
855     Handle<JSPromise> capability(
856         JSPromise::cast(module->top_level_capability()), isolate);
857     JSPromise::Reject(capability, exception);
858   }
859 
860   // 8. Return undefined.
861 }
862 
ExecuteAsyncModule(Isolate * isolate,Handle<SourceTextModule> module)863 void SourceTextModule::ExecuteAsyncModule(Isolate* isolate,
864                                           Handle<SourceTextModule> module) {
865   // 1. Assert: module.[[Status]] is "evaluating" or "evaluated".
866   CHECK(module->status() == kEvaluating || module->status() == kEvaluated);
867 
868   // 2. Assert: module.[[Async]] is true.
869   DCHECK(module->async());
870 
871   // 3. Set module.[[AsyncEvaluating]] to true.
872   module->set_async_evaluating(true);
873 
874   // 4. Let capability be ! NewPromiseCapability(%Promise%).
875   Handle<JSPromise> capability = isolate->factory()->NewJSPromise();
876 
877   // 5. Let stepsFulfilled be the steps of a CallAsyncModuleFulfilled
878   Handle<JSFunction> steps_fulfilled(
879       isolate->native_context()->call_async_module_fulfilled(), isolate);
880 
881   ScopedVector<Handle<Object>> empty_argv(0);
882 
883   // 6. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled,
884   //                                             «[[Module]]»).
885   // 7. Set onFulfilled.[[Module]] to module.
886   Handle<JSBoundFunction> on_fulfilled =
887       isolate->factory()
888           ->NewJSBoundFunction(steps_fulfilled, module, empty_argv)
889           .ToHandleChecked();
890 
891   // 8. Let stepsRejected be the steps of a CallAsyncModuleRejected.
892   Handle<JSFunction> steps_rejected(
893       isolate->native_context()->call_async_module_rejected(), isolate);
894 
895   // 9. Let onRejected be CreateBuiltinFunction(stepsRejected, «[[Module]]»).
896   // 10. Set onRejected.[[Module]] to module.
897   Handle<JSBoundFunction> on_rejected =
898       isolate->factory()
899           ->NewJSBoundFunction(steps_rejected, module, empty_argv)
900           .ToHandleChecked();
901 
902   // 11. Perform ! PerformPromiseThen(capability.[[Promise]],
903   //                                  onFulfilled, onRejected).
904   Handle<Object> argv[] = {on_fulfilled, on_rejected};
905   Execution::CallBuiltin(isolate, isolate->promise_then(), capability,
906                          arraysize(argv), argv)
907       .ToHandleChecked();
908 
909   // 12. Perform ! module.ExecuteModule(capability).
910   // Note: In V8 we have broken module.ExecuteModule into
911   // ExecuteModule for synchronous module execution and
912   // InnerExecuteAsyncModule for asynchronous execution.
913   InnerExecuteAsyncModule(isolate, module, capability).ToHandleChecked();
914 
915   // 13. Return.
916 }
917 
InnerExecuteAsyncModule(Isolate * isolate,Handle<SourceTextModule> module,Handle<JSPromise> capability)918 MaybeHandle<Object> SourceTextModule::InnerExecuteAsyncModule(
919     Isolate* isolate, Handle<SourceTextModule> module,
920     Handle<JSPromise> capability) {
921   // If we have an async module, then it has an associated
922   // JSAsyncFunctionObject, which we then evaluate with the passed in promise
923   // capability.
924   Handle<JSAsyncFunctionObject> async_function_object(
925       JSAsyncFunctionObject::cast(module->code()), isolate);
926   async_function_object->set_promise(*capability);
927   Handle<JSFunction> resume(
928       isolate->native_context()->async_module_evaluate_internal(), isolate);
929   Handle<Object> result;
930   ASSIGN_RETURN_ON_EXCEPTION(
931       isolate, result,
932       Execution::TryCall(isolate, resume, async_function_object, 0, nullptr,
933                          Execution::MessageHandling::kKeepPending, nullptr,
934                          false),
935       Object);
936   return result;
937 }
938 
ExecuteModule(Isolate * isolate,Handle<SourceTextModule> module)939 MaybeHandle<Object> SourceTextModule::ExecuteModule(
940     Isolate* isolate, Handle<SourceTextModule> module) {
941   // Synchronous modules have an associated JSGeneratorObject.
942   Handle<JSGeneratorObject> generator(JSGeneratorObject::cast(module->code()),
943                                       isolate);
944   Handle<JSFunction> resume(
945       isolate->native_context()->generator_next_internal(), isolate);
946   Handle<Object> result;
947 
948   // With top_level_await, we need to catch any exceptions and reject
949   // the top level capability.
950   if (FLAG_harmony_top_level_await) {
951     ASSIGN_RETURN_ON_EXCEPTION(
952         isolate, result,
953         Execution::TryCall(isolate, resume, generator, 0, nullptr,
954                            Execution::MessageHandling::kKeepPending, nullptr,
955                            false),
956         Object);
957   } else {
958     ASSIGN_RETURN_ON_EXCEPTION(
959         isolate, result,
960         Execution::Call(isolate, resume, generator, 0, nullptr), Object);
961   }
962   DCHECK(JSIteratorResult::cast(*result).done().BooleanValue(isolate));
963   return handle(JSIteratorResult::cast(*result).value(), isolate);
964 }
965 
InnerModuleEvaluation(Isolate * isolate,Handle<SourceTextModule> module,ZoneForwardList<Handle<SourceTextModule>> * stack,unsigned * dfs_index)966 MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
967     Isolate* isolate, Handle<SourceTextModule> module,
968     ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index) {
969   STACK_CHECK(isolate, MaybeHandle<Object>());
970 
971   // InnerModuleEvaluation(module, stack, index)
972   // 2. If module.[[Status]] is "evaluated", then
973   //    a. If module.[[EvaluationError]] is undefined, return index.
974   //       (We return undefined instead)
975   if (module->status() == kEvaluated || module->status() == kEvaluating) {
976     return isolate->factory()->undefined_value();
977   }
978 
979   //    b. Otherwise return module.[[EvaluationError]].
980   //       (We throw on isolate and return a MaybeHandle<Object>
981   //        instead)
982   if (module->status() == kErrored) {
983     isolate->Throw(module->exception());
984     return MaybeHandle<Object>();
985   }
986 
987   // 4. Assert: module.[[Status]] is "linked".
988   CHECK_EQ(module->status(), kInstantiated);
989 
990   // 5. Set module.[[Status]] to "evaluating".
991   module->SetStatus(kEvaluating);
992 
993   // 6. Set module.[[DFSIndex]] to index.
994   module->set_dfs_index(*dfs_index);
995 
996   // 7. Set module.[[DFSAncestorIndex]] to index.
997   module->set_dfs_ancestor_index(*dfs_index);
998 
999   // 8. Set module.[[PendingAsyncDependencies]] to 0.
1000   DCHECK(!module->HasPendingAsyncDependencies());
1001 
1002   // 9. Set module.[[AsyncParentModules]] to a new empty List.
1003   Handle<ArrayList> async_parent_modules = ArrayList::New(isolate, 0);
1004   module->set_async_parent_modules(*async_parent_modules);
1005 
1006   // 10. Set index to index + 1.
1007   (*dfs_index)++;
1008 
1009   // 11. Append module to stack.
1010   stack->push_front(module);
1011 
1012   // Recursion.
1013   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
1014 
1015   // 12. For each String required that is an element of
1016   //     module.[[RequestedModules]], do
1017   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
1018     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
1019                                     isolate);
1020     //   d. If requiredModule is a Cyclic Module Record, then
1021     if (requested_module->IsSourceTextModule()) {
1022       Handle<SourceTextModule> required_module(
1023           SourceTextModule::cast(*requested_module), isolate);
1024       RETURN_ON_EXCEPTION(
1025           isolate,
1026           InnerModuleEvaluation(isolate, required_module, stack, dfs_index),
1027           Object);
1028 
1029       //    i. Assert: requiredModule.[[Status]] is either "evaluating" or
1030       //       "evaluated".
1031       //       (We also assert the module cannot be errored, because if it was
1032       //        we would have already returned from InnerModuleEvaluation)
1033       CHECK_GE(required_module->status(), kEvaluating);
1034       CHECK_NE(required_module->status(), kErrored);
1035 
1036       //   ii.  Assert: requiredModule.[[Status]] is "evaluating" if and
1037       //        only if requiredModule is in stack.
1038       SLOW_DCHECK(
1039           (requested_module->status() == kEvaluating) ==
1040           std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
1041             return *m == *requested_module;
1042           }));
1043 
1044       //  iii.  If requiredModule.[[Status]] is "evaluating", then
1045       if (required_module->status() == kEvaluating) {
1046         //      1. Set module.[[DFSAncestorIndex]] to
1047         //         min(
1048         //           module.[[DFSAncestorIndex]],
1049         //           requiredModule.[[DFSAncestorIndex]]).
1050         module->set_dfs_ancestor_index(
1051             std::min(module->dfs_ancestor_index(),
1052                      required_module->dfs_ancestor_index()));
1053       } else {
1054         //   iv. Otherwise,
1055         //      1. Set requiredModule to GetAsyncCycleRoot(requiredModule).
1056         required_module = GetAsyncCycleRoot(isolate, required_module);
1057 
1058         //      2. Assert: requiredModule.[[Status]] is "evaluated".
1059         CHECK_GE(required_module->status(), kEvaluated);
1060 
1061         //      3. If requiredModule.[[EvaluationError]] is not undefined,
1062         //         return module.[[EvaluationError]].
1063         //         (If there was an exception on the original required module
1064         //          we would have already returned. This check handles the case
1065         //          where the AsyncCycleRoot has an error. Instead of returning
1066         //          the exception, we throw on isolate and return a
1067         //          MaybeHandle<Object>)
1068         if (required_module->status() == kErrored) {
1069           isolate->Throw(required_module->exception());
1070           return MaybeHandle<Object>();
1071         }
1072       }
1073       //     v. If requiredModule.[[AsyncEvaluating]] is true, then
1074       if (required_module->async_evaluating()) {
1075         //      1. Set module.[[PendingAsyncDependencies]] to
1076         //         module.[[PendingAsyncDependencies]] + 1.
1077         module->IncrementPendingAsyncDependencies();
1078 
1079         //      2. Append module to requiredModule.[[AsyncParentModules]].
1080         AddAsyncParentModule(isolate, required_module, module);
1081       }
1082     } else {
1083       RETURN_ON_EXCEPTION(isolate, Module::Evaluate(isolate, requested_module),
1084                           Object);
1085     }
1086   }
1087 
1088   // The spec returns the module index for proper numbering of dependencies.
1089   // However, we pass the module index by pointer instead.
1090   //
1091   // Before async modules v8 returned the value result from calling next
1092   // on the module's implicit iterator. We preserve this behavior for
1093   // synchronous modules, but return undefined for AsyncModules.
1094   Handle<Object> result = isolate->factory()->undefined_value();
1095 
1096   // 14. If module.[[PendingAsyncDependencies]] is > 0, set
1097   //     module.[[AsyncEvaluating]] to true.
1098   if (module->HasPendingAsyncDependencies()) {
1099     module->set_async_evaluating(true);
1100   } else if (module->async()) {
1101     // 15. Otherwise, if module.[[Async]] is true,
1102     //     perform ! ExecuteAsyncModule(module).
1103     SourceTextModule::ExecuteAsyncModule(isolate, module);
1104   } else {
1105     // 16. Otherwise, perform ? module.ExecuteModule().
1106     ASSIGN_RETURN_ON_EXCEPTION(isolate, result, ExecuteModule(isolate, module),
1107                                Object);
1108   }
1109 
1110   CHECK(MaybeTransitionComponent(isolate, module, stack, kEvaluated));
1111   return result;
1112 }
1113 
GetAsyncCycleRoot(Isolate * isolate,Handle<SourceTextModule> module)1114 Handle<SourceTextModule> SourceTextModule::GetAsyncCycleRoot(
1115     Isolate* isolate, Handle<SourceTextModule> module) {
1116   // 1. Assert: module.[[Status]] is "evaluated".
1117   CHECK_GE(module->status(), kEvaluated);
1118 
1119   // 2. If module.[[AsyncParentModules]] is an empty List, return module.
1120   if (module->AsyncParentModuleCount() == 0) {
1121     return module;
1122   }
1123 
1124   // 3. Repeat, while module.[[DFSIndex]] is greater than
1125   //    module.[[DFSAncestorIndex]],
1126   while (module->dfs_index() > module->dfs_ancestor_index()) {
1127     //  a. Assert: module.[[AsyncParentModules]] is a non-empty List.
1128     DCHECK_GT(module->AsyncParentModuleCount(), 0);
1129 
1130     //  b. Let nextCycleModule be the first element of
1131     //     module.[[AsyncParentModules]].
1132     Handle<SourceTextModule> next_cycle_module =
1133         module->GetAsyncParentModule(isolate, 0);
1134 
1135     //  c. Assert: nextCycleModule.[[DFSAncestorIndex]] is less than or equal
1136     //     to module.[[DFSAncestorIndex]].
1137     DCHECK_LE(next_cycle_module->dfs_ancestor_index(),
1138               module->dfs_ancestor_index());
1139 
1140     //  d. Set module to nextCycleModule
1141     module = next_cycle_module;
1142   }
1143 
1144   // 4. Assert: module.[[DFSIndex]] is equal to module.[[DFSAncestorIndex]].
1145   DCHECK_EQ(module->dfs_index(), module->dfs_ancestor_index());
1146 
1147   // 5. Return module.
1148   return module;
1149 }
1150 
Reset(Isolate * isolate,Handle<SourceTextModule> module)1151 void SourceTextModule::Reset(Isolate* isolate,
1152                              Handle<SourceTextModule> module) {
1153   Factory* factory = isolate->factory();
1154 
1155   DCHECK(module->import_meta().IsTheHole(isolate));
1156 
1157   Handle<FixedArray> regular_exports =
1158       factory->NewFixedArray(module->regular_exports().length());
1159   Handle<FixedArray> regular_imports =
1160       factory->NewFixedArray(module->regular_imports().length());
1161   Handle<FixedArray> requested_modules =
1162       factory->NewFixedArray(module->requested_modules().length());
1163 
1164   if (module->status() == kInstantiating) {
1165     module->set_code(JSFunction::cast(module->code()).shared());
1166   }
1167   module->set_regular_exports(*regular_exports);
1168   module->set_regular_imports(*regular_imports);
1169   module->set_requested_modules(*requested_modules);
1170   module->set_dfs_index(-1);
1171   module->set_dfs_ancestor_index(-1);
1172 }
1173 
1174 }  // namespace internal
1175 }  // namespace v8
1176