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