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