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