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
17namespace v8 {
18namespace internal {
19
20struct StringHandleHash {
21  V8_INLINE size_t operator()(Handle<String> string) const {
22    return string->EnsureHash();
23  }
24};
25
26struct StringHandleEqual {
27  V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
28    return lhs->Equals(*rhs);
29  }
30};
31
32class UnorderedStringSet
33    : public std::unordered_set<Handle<String>, StringHandleHash,
34                                StringHandleEqual,
35                                ZoneAllocator<Handle<String>>> {
36 public:
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
44class UnorderedStringMap
45    : public std::unordered_map<
46          Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
47          ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>> {
48 public:
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
58class Module::ResolveSet
59    : public std::unordered_map<
60          Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
61          ModuleHandleEqual,
62          ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>> {
63 public:
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
74  Zone* zone() const { return zone_; }
75
76 private:
77  Zone* zone_;
78};
79
80struct SourceTextModule::AsyncEvaluatingOrdinalCompare {
81  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
89SharedFunctionInfo 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
108Script SourceTextModule::GetScript() const {
109  DisallowGarbageCollection no_gc;
110  return Script::cast(GetSharedFunctionInfo().script());
111}
112
113int SourceTextModule::ExportIndex(int cell_index) {
114  DCHECK_EQ(SourceTextModuleDescriptor::GetCellIndexKind(cell_index),
115            SourceTextModuleDescriptor::kExport);
116  return cell_index - 1;
117}
118
119int SourceTextModule::ImportIndex(int cell_index) {
120  DCHECK_EQ(SourceTextModuleDescriptor::GetCellIndexKind(cell_index),
121            SourceTextModuleDescriptor::kImport);
122  return -cell_index - 1;
123}
124
125void 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
134void 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
151Cell 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
167Handle<Object> SourceTextModule::LoadVariable(Isolate* isolate,
168                                              Handle<SourceTextModule> module,
169                                              int cell_index) {
170  return handle(module->GetCell(cell_index).value(), isolate);
171}
172
173void 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
181MaybeHandle<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
246MaybeHandle<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
266MaybeHandle<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
322bool 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
398bool 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
422bool 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
453bool 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
538void 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 index : requested_exports->IterateEntries()) {
580      Object key;
581      if (!requested_exports->ToKey(roots, index, &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(index)), 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
614void 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
666Handle<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
673MaybeHandle<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
686MaybeHandle<Object> SourceTextModule::Evaluate(
687    Isolate* isolate, Handle<SourceTextModule> module) {
688  CHECK(module->status() == kLinked || module->status() == kEvaluated);
689
690  // 5. Let stack be a new empty List.
691  Zone zone(isolate->allocator(), ZONE_NAME);
692  ZoneForwardList<Handle<SourceTextModule>> stack(&zone);
693  unsigned dfs_index = 0;
694
695  // 6. Let capability be ! NewPromiseCapability(%Promise%).
696  Handle<JSPromise> capability = isolate->factory()->NewJSPromise();
697
698  // 7. Set module.[[TopLevelCapability]] to capability.
699  module->set_top_level_capability(*capability);
700  DCHECK(module->top_level_capability().IsJSPromise());
701
702  // 8. Let result be InnerModuleEvaluation(module, stack, 0).
703  // 9. If result is an abrupt completion, then
704  Handle<Object> unused_result;
705  if (!InnerModuleEvaluation(isolate, module, &stack, &dfs_index)
706           .ToHandle(&unused_result)) {
707    //  a. For each Cyclic Module Record m in stack, do
708    for (auto& descendant : stack) {
709      //   i. Assert: m.[[Status]] is "evaluating".
710      CHECK_EQ(descendant->status(), kEvaluating);
711      //  ii. Set m.[[Status]] to "evaluated".
712      // iii. Set m.[[EvaluationError]] to result.
713      Module::RecordErrorUsingPendingException(isolate, descendant);
714    }
715
716    // If the exception was a termination exception, rejecting the promise
717    // would resume execution, and our API contract is to return an empty
718    // handle. The module's status should be set to kErrored and the
719    // exception field should be set to `null`.
720    if (!isolate->is_catchable_by_javascript(isolate->pending_exception())) {
721      CHECK_EQ(module->status(), kErrored);
722      CHECK_EQ(module->exception(), *isolate->factory()->null_value());
723      return {};
724    }
725    CHECK_EQ(module->exception(), isolate->pending_exception());
726
727    //  d. Perform ! Call(capability.[[Reject]], undefined,
728    //                    «result.[[Value]]»).
729    isolate->clear_pending_exception();
730    JSPromise::Reject(capability, handle(module->exception(), isolate));
731  } else {
732    // 10. Otherwise,
733    //  a. Assert: module.[[Status]] is "evaluated"...
734    CHECK_EQ(module->status(), kEvaluated);
735
736    //  b. If module.[[AsyncEvaluating]] is false, then
737    if (!module->IsAsyncEvaluating()) {
738      //   i. Perform ! Call(capability.[[Resolve]], undefined,
739      //                     «undefined»).
740      JSPromise::Resolve(capability, isolate->factory()->undefined_value())
741          .ToHandleChecked();
742    }
743
744    //  c. Assert: stack is empty.
745    DCHECK(stack.empty());
746  }
747
748  // 11. Return capability.[[Promise]].
749  return capability;
750}
751
752Maybe<bool> SourceTextModule::AsyncModuleExecutionFulfilled(
753    Isolate* isolate, Handle<SourceTextModule> module) {
754  // 1. If module.[[Status]] is evaluated, then
755  if (module->status() == kErrored) {
756    // a. Assert: module.[[EvaluationError]] is not empty.
757    DCHECK(!module->exception().IsTheHole(isolate));
758    // b. Return.
759    return Just(true);
760  }
761  // 3. Assert: module.[[AsyncEvaluating]] is true.
762  DCHECK(module->IsAsyncEvaluating());
763  // 4. Assert: module.[[EvaluationError]] is empty.
764  CHECK_EQ(module->status(), kEvaluated);
765  // 5. Set module.[[AsyncEvaluating]] to false.
766  isolate->DidFinishModuleAsyncEvaluation(module->async_evaluating_ordinal());
767  module->set_async_evaluating_ordinal(kAsyncEvaluateDidFinish);
768  // TODO(cbruni): update to match spec.
769  // 7. If module.[[TopLevelCapability]] is not empty, then
770  if (!module->top_level_capability().IsUndefined(isolate)) {
771    //  a. Assert: module.[[CycleRoot]] is equal to module.
772    DCHECK_EQ(*module->GetCycleRoot(isolate), *module);
773    //   i. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined,
774    //                     «undefined»).
775    Handle<JSPromise> capability(
776        JSPromise::cast(module->top_level_capability()), isolate);
777    JSPromise::Resolve(capability, isolate->factory()->undefined_value())
778        .ToHandleChecked();
779  }
780
781  // 8. Let execList be a new empty List.
782  Zone zone(isolate->allocator(), ZONE_NAME);
783  AsyncParentCompletionSet exec_list(&zone);
784
785  // 9. Perform ! GatherAsyncParentCompletions(module, execList).
786  GatherAsyncParentCompletions(isolate, &zone, module, &exec_list);
787
788  // 10. Let sortedExecList be a List of elements that are the elements of
789  //    execList, in the order in which they had their [[AsyncEvaluating]]
790  //    fields set to true in InnerModuleEvaluation.
791  //
792  // This step is implemented by AsyncParentCompletionSet, which is a set
793  // ordered on async_evaluating_ordinal.
794
795  // 11. Assert: All elements of sortedExecList have their [[AsyncEvaluating]]
796  //    field set to true, [[PendingAsyncDependencies]] field set to 0 and
797  //    [[EvaluationError]] field set to undefined.
798#ifdef DEBUG
799  for (Handle<SourceTextModule> m : exec_list) {
800    DCHECK(m->IsAsyncEvaluating());
801    DCHECK(!m->HasPendingAsyncDependencies());
802    DCHECK_NE(m->status(), kErrored);
803  }
804#endif
805
806  // 12. For each Module m of sortedExecList, do
807  for (Handle<SourceTextModule> m : exec_list) {
808    //  i. If m.[[AsyncEvaluating]] is false, then
809    if (!m->IsAsyncEvaluating()) {
810      //   a. Assert: m.[[EvaluatingError]] is not empty.
811      DCHECK_EQ(m->status(), kErrored);
812    } else if (m->async()) {
813      //  ii. Otherwise, if m.[[Async]] is *true*, then
814      //   a. Perform ! ExecuteAsyncModule(m).
815      // The execution may have been terminated and can not be resumed, so just
816      // raise the exception.
817      MAYBE_RETURN(ExecuteAsyncModule(isolate, m), Nothing<bool>());
818    } else {
819      //  iii. Otherwise,
820      //   a. Let _result_ be m.ExecuteModule().
821      Handle<Object> unused_result;
822      //   b. If _result_ is an abrupt completion,
823      if (!ExecuteModule(isolate, m).ToHandle(&unused_result)) {
824        //    1. Perform ! AsyncModuleExecutionRejected(m, result.[[Value]]).
825        Handle<Object> exception(isolate->pending_exception(), isolate);
826        isolate->clear_pending_exception();
827        AsyncModuleExecutionRejected(isolate, m, exception);
828      } else {
829        //   c. Otherwise,
830        //    1. Set m.[[AsyncEvaluating]] to false.
831        isolate->DidFinishModuleAsyncEvaluation(m->async_evaluating_ordinal());
832        m->set_async_evaluating_ordinal(kAsyncEvaluateDidFinish);
833
834        //    2. If m.[[TopLevelCapability]] is not empty, then
835        if (!m->top_level_capability().IsUndefined(isolate)) {
836          //  i. Assert: m.[[CycleRoot]] is equal to m.
837          DCHECK_EQ(*m->GetCycleRoot(isolate), *m);
838
839          //  ii. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]],
840          //                     undefined, «undefined»).
841          Handle<JSPromise> capability(
842              JSPromise::cast(m->top_level_capability()), isolate);
843          JSPromise::Resolve(capability, isolate->factory()->undefined_value())
844              .ToHandleChecked();
845        }
846      }
847    }
848  }
849
850  // 10. Return undefined.
851  return Just(true);
852}
853
854void SourceTextModule::AsyncModuleExecutionRejected(
855    Isolate* isolate, Handle<SourceTextModule> module,
856    Handle<Object> exception) {
857  // 1. If module.[[Status]] is evaluated, then
858  if (module->status() == kErrored) {
859    // a. Assert: module.[[EvaluationError]] is not empty.
860    DCHECK(!module->exception().IsTheHole(isolate));
861    // b. Return.
862    return;
863  }
864
865  // TODO(cbruni): update to match spec.
866  DCHECK(isolate->is_catchable_by_javascript(*exception));
867  // 1. Assert: module.[[Status]] is "evaluated".
868  CHECK(module->status() == kEvaluated || module->status() == kErrored);
869  // 2. If module.[[AsyncEvaluating]] is false,
870  if (!module->IsAsyncEvaluating()) {
871    //  a. Assert: module.[[EvaluationError]] is not empty.
872    CHECK_EQ(module->status(), kErrored);
873    //  b. Return undefined.
874    return;
875  }
876
877  // 5. Set module.[[EvaluationError]] to ThrowCompletion(error).
878  Module::RecordError(isolate, module, exception);
879
880  // 6. Set module.[[AsyncEvaluating]] to false.
881  isolate->DidFinishModuleAsyncEvaluation(module->async_evaluating_ordinal());
882  module->set_async_evaluating_ordinal(kAsyncEvaluateDidFinish);
883
884  // 7. For each Module m of module.[[AsyncParentModules]], do
885  for (int i = 0; i < module->AsyncParentModuleCount(); i++) {
886    Handle<SourceTextModule> m = module->GetAsyncParentModule(isolate, i);
887    // TODO(cbruni): update to match spec.
888    //  a. If module.[[DFSIndex]] is not equal to module.[[DFSAncestorIndex]],
889    //     then
890    if (module->dfs_index() != module->dfs_ancestor_index()) {
891      //   i. Assert: m.[[DFSAncestorIndex]] is equal to
892      //      module.[[DFSAncestorIndex]].
893      DCHECK_EQ(m->dfs_ancestor_index(), module->dfs_ancestor_index());
894    }
895    //  b. Perform ! AsyncModuleExecutionRejected(m, error).
896    AsyncModuleExecutionRejected(isolate, m, exception);
897  }
898
899  // 8. If module.[[TopLevelCapability]] is not empty, then
900  if (!module->top_level_capability().IsUndefined(isolate)) {
901    //  a. Assert: module.[[CycleRoot]] is equal to module.
902    DCHECK_EQ(*module->GetCycleRoot(isolate), *module);
903    //  b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]],
904    //                    undefined, «error»).
905    Handle<JSPromise> capability(
906        JSPromise::cast(module->top_level_capability()), isolate);
907    JSPromise::Reject(capability, exception);
908  }
909}
910
911// static
912Maybe<bool> SourceTextModule::ExecuteAsyncModule(
913    Isolate* isolate, Handle<SourceTextModule> module) {
914  // 1. Assert: module.[[Status]] is "evaluating" or "evaluated".
915  CHECK(module->status() == kEvaluating || module->status() == kEvaluated);
916
917  // 2. Assert: module.[[Async]] is true.
918  DCHECK(module->async());
919
920  // 3. Set module.[[AsyncEvaluating]] to true.
921  module->set_async_evaluating_ordinal(
922      isolate->NextModuleAsyncEvaluatingOrdinal());
923
924  // 4. Let capability be ! NewPromiseCapability(%Promise%).
925  Handle<JSPromise> capability = isolate->factory()->NewJSPromise();
926
927  // 5. Let stepsFulfilled be the steps of a CallAsyncModuleFulfilled
928  Handle<JSFunction> steps_fulfilled(
929      isolate->native_context()->call_async_module_fulfilled(), isolate);
930
931  base::ScopedVector<Handle<Object>> empty_argv(0);
932
933  // 6. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled,
934  //                                             «[[Module]]»).
935  // 7. Set onFulfilled.[[Module]] to module.
936  Handle<JSBoundFunction> on_fulfilled =
937      isolate->factory()
938          ->NewJSBoundFunction(steps_fulfilled, module, empty_argv)
939          .ToHandleChecked();
940
941  // 8. Let stepsRejected be the steps of a CallAsyncModuleRejected.
942  Handle<JSFunction> steps_rejected(
943      isolate->native_context()->call_async_module_rejected(), isolate);
944
945  // 9. Let onRejected be CreateBuiltinFunction(stepsRejected, «[[Module]]»).
946  // 10. Set onRejected.[[Module]] to module.
947  Handle<JSBoundFunction> on_rejected =
948      isolate->factory()
949          ->NewJSBoundFunction(steps_rejected, module, empty_argv)
950          .ToHandleChecked();
951
952  // 11. Perform ! PerformPromiseThen(capability.[[Promise]],
953  //                                  onFulfilled, onRejected).
954  Handle<Object> argv[] = {on_fulfilled, on_rejected};
955  Execution::CallBuiltin(isolate, isolate->promise_then(), capability,
956                         arraysize(argv), argv)
957      .ToHandleChecked();
958
959  // 12. Perform ! module.ExecuteModule(capability).
960  // Note: In V8 we have broken module.ExecuteModule into
961  // ExecuteModule for synchronous module execution and
962  // InnerExecuteAsyncModule for asynchronous execution.
963  MaybeHandle<Object> ret =
964      InnerExecuteAsyncModule(isolate, module, capability);
965  if (ret.is_null()) {
966    // The evaluation of async module can not throwing a JavaScript observable
967    // exception.
968    DCHECK(isolate->has_pending_exception());
969    DCHECK_EQ(isolate->pending_exception(),
970              ReadOnlyRoots(isolate).termination_exception());
971    return Nothing<bool>();
972  }
973
974  // 13. Return.
975  return Just<bool>(true);
976}
977
978MaybeHandle<Object> SourceTextModule::InnerExecuteAsyncModule(
979    Isolate* isolate, Handle<SourceTextModule> module,
980    Handle<JSPromise> capability) {
981  // If we have an async module, then it has an associated
982  // JSAsyncFunctionObject, which we then evaluate with the passed in promise
983  // capability.
984  Handle<JSAsyncFunctionObject> async_function_object(
985      JSAsyncFunctionObject::cast(module->code()), isolate);
986  async_function_object->set_promise(*capability);
987  Handle<JSFunction> resume(
988      isolate->native_context()->async_module_evaluate_internal(), isolate);
989  Handle<Object> result;
990  ASSIGN_RETURN_ON_EXCEPTION(
991      isolate, result,
992      Execution::TryCall(isolate, resume, async_function_object, 0, nullptr,
993                         Execution::MessageHandling::kKeepPending, nullptr,
994                         false),
995      Object);
996  return result;
997}
998
999MaybeHandle<Object> SourceTextModule::ExecuteModule(
1000    Isolate* isolate, Handle<SourceTextModule> module) {
1001  // Synchronous modules have an associated JSGeneratorObject.
1002  Handle<JSGeneratorObject> generator(JSGeneratorObject::cast(module->code()),
1003                                      isolate);
1004  Handle<JSFunction> resume(
1005      isolate->native_context()->generator_next_internal(), isolate);
1006  Handle<Object> result;
1007
1008  ASSIGN_RETURN_ON_EXCEPTION(
1009      isolate, result,
1010      Execution::TryCall(isolate, resume, generator, 0, nullptr,
1011                         Execution::MessageHandling::kKeepPending, nullptr,
1012                         false),
1013      Object);
1014  DCHECK(JSIteratorResult::cast(*result).done().BooleanValue(isolate));
1015  return handle(JSIteratorResult::cast(*result).value(), isolate);
1016}
1017
1018MaybeHandle<Object> SourceTextModule::InnerModuleEvaluation(
1019    Isolate* isolate, Handle<SourceTextModule> module,
1020    ZoneForwardList<Handle<SourceTextModule>>* stack, unsigned* dfs_index) {
1021  STACK_CHECK(isolate, MaybeHandle<Object>());
1022
1023  // InnerModuleEvaluation(module, stack, index)
1024  // 2. If module.[[Status]] is "evaluated", then
1025  //    a. If module.[[EvaluationError]] is undefined, return index.
1026  //       (We return undefined instead)
1027  if (module->status() == kEvaluated || module->status() == kEvaluating) {
1028    return isolate->factory()->undefined_value();
1029  }
1030
1031  //    b. Otherwise return module.[[EvaluationError]].
1032  //       (We throw on isolate and return a MaybeHandle<Object>
1033  //        instead)
1034  if (module->status() == kErrored) {
1035    isolate->Throw(module->exception());
1036    return MaybeHandle<Object>();
1037  }
1038
1039  // 4. Assert: module.[[Status]] is "linked".
1040  CHECK_EQ(module->status(), kLinked);
1041
1042  // 5. Set module.[[Status]] to "evaluating".
1043  module->SetStatus(kEvaluating);
1044
1045  // 6. Set module.[[DFSIndex]] to index.
1046  module->set_dfs_index(*dfs_index);
1047
1048  // 7. Set module.[[DFSAncestorIndex]] to index.
1049  module->set_dfs_ancestor_index(*dfs_index);
1050
1051  // 8. Set module.[[PendingAsyncDependencies]] to 0.
1052  DCHECK(!module->HasPendingAsyncDependencies());
1053
1054  // 9. Set module.[[AsyncParentModules]] to a new empty List.
1055  module->set_async_parent_modules(ReadOnlyRoots(isolate).empty_array_list());
1056
1057  // 10. Set index to index + 1.
1058  (*dfs_index)++;
1059
1060  // 11. Append module to stack.
1061  stack->push_front(module);
1062
1063  // Recursion.
1064  Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
1065
1066  // 12. For each String required that is an element of
1067  //     module.[[RequestedModules]], do
1068  for (int i = 0, length = requested_modules->length(); i < length; ++i) {
1069    Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
1070                                    isolate);
1071    //   d. If requiredModule is a Cyclic Module Record, then
1072    if (requested_module->IsSourceTextModule()) {
1073      Handle<SourceTextModule> required_module(
1074          SourceTextModule::cast(*requested_module), isolate);
1075      RETURN_ON_EXCEPTION(
1076          isolate,
1077          InnerModuleEvaluation(isolate, required_module, stack, dfs_index),
1078          Object);
1079
1080      //    i. Assert: requiredModule.[[Status]] is either "evaluating" or
1081      //       "evaluated".
1082      //       (We also assert the module cannot be errored, because if it was
1083      //        we would have already returned from InnerModuleEvaluation)
1084      CHECK_GE(required_module->status(), kEvaluating);
1085      CHECK_NE(required_module->status(), kErrored);
1086
1087      //   ii.  Assert: requiredModule.[[Status]] is "evaluating" if and
1088      //        only if requiredModule is in stack.
1089      SLOW_DCHECK(
1090          (requested_module->status() == kEvaluating) ==
1091          std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
1092            return *m == *requested_module;
1093          }));
1094
1095      //  iii.  If requiredModule.[[Status]] is "evaluating", then
1096      if (required_module->status() == kEvaluating) {
1097        //      1. Set module.[[DFSAncestorIndex]] to
1098        //         min(
1099        //           module.[[DFSAncestorIndex]],
1100        //           requiredModule.[[DFSAncestorIndex]]).
1101        module->set_dfs_ancestor_index(
1102            std::min(module->dfs_ancestor_index(),
1103                     required_module->dfs_ancestor_index()));
1104      } else {
1105        //   iv. Otherwise,
1106        //      1. Set requiredModule to requiredModule.[[CycleRoot]].
1107        required_module = required_module->GetCycleRoot(isolate);
1108
1109        //      2. Assert: requiredModule.[[Status]] is "evaluated".
1110        CHECK_GE(required_module->status(), kEvaluated);
1111
1112        //      3. If requiredModule.[[EvaluationError]] is not undefined,
1113        //         return module.[[EvaluationError]].
1114        //         (If there was an exception on the original required module
1115        //          we would have already returned. This check handles the case
1116        //          where the AsyncCycleRoot has an error. Instead of returning
1117        //          the exception, we throw on isolate and return a
1118        //          MaybeHandle<Object>)
1119        if (required_module->status() == kErrored) {
1120          isolate->Throw(required_module->exception());
1121          return MaybeHandle<Object>();
1122        }
1123      }
1124      //     v. If requiredModule.[[AsyncEvaluating]] is true, then
1125      if (required_module->IsAsyncEvaluating()) {
1126        //      1. Set module.[[PendingAsyncDependencies]] to
1127        //         module.[[PendingAsyncDependencies]] + 1.
1128        module->IncrementPendingAsyncDependencies();
1129
1130        //      2. Append module to requiredModule.[[AsyncParentModules]].
1131        AddAsyncParentModule(isolate, required_module, module);
1132      }
1133    } else {
1134      RETURN_ON_EXCEPTION(isolate, Module::Evaluate(isolate, requested_module),
1135                          Object);
1136    }
1137  }
1138
1139  // The spec returns the module index for proper numbering of dependencies.
1140  // However, we pass the module index by pointer instead.
1141  //
1142  // Before async modules v8 returned the value result from calling next
1143  // on the module's implicit iterator. We preserve this behavior for
1144  // synchronous modules, but return undefined for AsyncModules.
1145  Handle<Object> result = isolate->factory()->undefined_value();
1146
1147  // 14. If module.[[PendingAsyncDependencies]] > 0 or module.[[Async]] is
1148  //     true, then
1149  if (module->HasPendingAsyncDependencies() || module->async()) {
1150    // a. Assert: module.[[AsyncEvaluating]] is false and was never previously
1151    //     set to true.
1152    DCHECK_EQ(module->async_evaluating_ordinal(), kNotAsyncEvaluated);
1153
1154    // b. Set module.[[AsyncEvaluating]] to true.
1155    // NOTE: The order in which modules transition to async evaluating is
1156    // significant.
1157    module->set_async_evaluating_ordinal(
1158        isolate->NextModuleAsyncEvaluatingOrdinal());
1159
1160    // c. If module.[[PendingAsyncDependencies]] is 0,
1161    //    perform ! ExecuteAsyncModule(_module_).
1162    // The execution may have been terminated and can not be resumed, so just
1163    // raise the exception.
1164    if (!module->HasPendingAsyncDependencies()) {
1165      MAYBE_RETURN(SourceTextModule::ExecuteAsyncModule(isolate, module),
1166                   MaybeHandle<Object>());
1167    }
1168  } else {
1169    // 15. Otherwise, perform ? module.ExecuteModule().
1170    ASSIGN_RETURN_ON_EXCEPTION(isolate, result, ExecuteModule(isolate, module),
1171                               Object);
1172  }
1173
1174  CHECK(MaybeTransitionComponent(isolate, module, stack, kEvaluated));
1175  return result;
1176}
1177
1178void SourceTextModule::Reset(Isolate* isolate,
1179                             Handle<SourceTextModule> module) {
1180  Factory* factory = isolate->factory();
1181
1182  DCHECK(module->import_meta(kAcquireLoad).IsTheHole(isolate));
1183
1184  Handle<FixedArray> regular_exports =
1185      factory->NewFixedArray(module->regular_exports().length());
1186  Handle<FixedArray> regular_imports =
1187      factory->NewFixedArray(module->regular_imports().length());
1188  Handle<FixedArray> requested_modules =
1189      factory->NewFixedArray(module->requested_modules().length());
1190
1191  if (module->status() == kLinking) {
1192    module->set_code(JSFunction::cast(module->code()).shared());
1193  }
1194  module->set_regular_exports(*regular_exports);
1195  module->set_regular_imports(*regular_imports);
1196  module->set_requested_modules(*requested_modules);
1197  module->set_dfs_index(-1);
1198  module->set_dfs_ancestor_index(-1);
1199}
1200
1201}  // namespace internal
1202}  // namespace v8
1203