Serenity Operating System
at master 674 lines 29 kB view raw
1/* 2 * Copyright (c) 2022, David Tuin <davidot@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Debug.h> 8#include <AK/TypeCasts.h> 9#include <LibJS/CyclicModule.h> 10#include <LibJS/Runtime/ModuleRequest.h> 11#include <LibJS/Runtime/PromiseCapability.h> 12#include <LibJS/Runtime/PromiseConstructor.h> 13#include <LibJS/Runtime/VM.h> 14 15namespace JS { 16 17CyclicModule::CyclicModule(Realm& realm, StringView filename, bool has_top_level_await, Vector<ModuleRequest> requested_modules, Script::HostDefined* host_defined) 18 : Module(realm, filename, host_defined) 19 , m_requested_modules(move(requested_modules)) 20 , m_has_top_level_await(has_top_level_await) 21{ 22} 23 24void CyclicModule::visit_edges(Cell::Visitor& visitor) 25{ 26 Base::visit_edges(visitor); 27 visitor.visit(m_cycle_root); 28 for (auto* module : m_async_parent_modules) 29 visitor.visit(module); 30} 31 32// 16.2.1.5.1 Link ( ), https://tc39.es/ecma262/#sec-moduledeclarationlinking 33ThrowCompletionOr<void> CyclicModule::link(VM& vm) 34{ 35 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] link[{}]()", this); 36 // 1. Assert: module.[[Status]] is not linking or evaluating. 37 VERIFY(m_status != ModuleStatus::Linking && m_status != ModuleStatus::Evaluating); 38 // 2. Let stack be a new empty List. 39 Vector<Module*> stack; 40 41 // 3. Let result be Completion(InnerModuleLinking(module, stack, 0)). 42 auto result = inner_module_linking(vm, stack, 0); 43 44 // 4. If result is an abrupt completion, then 45 if (result.is_throw_completion()) { 46 // a. For each Cyclic Module Record m of stack, do 47 for (auto* module : stack) { 48 if (is<CyclicModule>(module)) { 49 auto& cyclic_module = static_cast<CyclicModule&>(*module); 50 // i. Assert: m.[[Status]] is linking. 51 VERIFY(cyclic_module.m_status == ModuleStatus::Linking); 52 53 // ii. Set m.[[Status]] to unlinked. 54 cyclic_module.m_status = ModuleStatus::Unlinked; 55 } 56 } 57 // b. Assert: module.[[Status]] is unlinked. 58 VERIFY(m_status == ModuleStatus::Unlinked); 59 60 // c. Return result. 61 return result.release_error(); 62 } 63 64 // 5. Assert: module.[[Status]] is linked, evaluating-async, or evaluated. 65 VERIFY(m_status == ModuleStatus::Linked || m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated); 66 // 6. Assert: stack is empty. 67 VERIFY(stack.is_empty()); 68 69 // 7. Return unused. 70 return {}; 71} 72 73// 16.2.1.5.1.1 InnerModuleLinking ( module, stack, index ), https://tc39.es/ecma262/#sec-InnerModuleLinking 74ThrowCompletionOr<u32> CyclicModule::inner_module_linking(VM& vm, Vector<Module*>& stack, u32 index) 75{ 76 // 1. If module is not a Cyclic Module Record, then 77 // a. Perform ? module.Link(). 78 // b. Return index. 79 // Note: Step 1, 1.a and 1.b are handled in Module.cpp 80 81 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_linking[{}](vm, {}, {})", this, DeprecatedString::join(',', stack), index); 82 83 // 2. If module.[[Status]] is linking, linked, evaluating-async, or evaluated, then 84 if (m_status == ModuleStatus::Linking || m_status == ModuleStatus::Linked || m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated) { 85 // a. Return index. 86 return index; 87 } 88 89 // 3. Assert: module.[[Status]] is unlinked. 90 VERIFY(m_status == ModuleStatus::Unlinked); 91 92 // 4. Set module.[[Status]] to linking. 93 m_status = ModuleStatus::Linking; 94 95 // 5. Set module.[[DFSIndex]] to index. 96 m_dfs_index = index; 97 98 // 6. Set module.[[DFSAncestorIndex]] to index. 99 m_dfs_ancestor_index = index; 100 101 // 7. Set index to index + 1. 102 ++index; 103 104 // 8. Append module to stack. 105 stack.append(this); 106 107#if JS_MODULE_DEBUG 108 StringBuilder request_module_names; 109 for (auto& module_request : m_requested_modules) { 110 request_module_names.append(module_request.module_specifier); 111 request_module_names.append(", "sv); 112 } 113 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] module: {} has requested modules: [{}]", filename(), request_module_names.string_view()); 114#endif 115 116 // 9. For each String required of module.[[RequestedModules]], do 117 for (auto& required_string : m_requested_modules) { 118 ModuleRequest required { required_string }; 119 120 // a. Let requiredModule be ? HostResolveImportedModule(module, required). 121 auto required_module = TRY(vm.host_resolve_imported_module(NonnullGCPtr<Module>(*this), required)); 122 123 // b. Set index to ? InnerModuleLinking(requiredModule, stack, index). 124 index = TRY(required_module->inner_module_linking(vm, stack, index)); 125 126 // c. If requiredModule is a Cyclic Module Record, then 127 if (is<CyclicModule>(*required_module)) { 128 auto& cyclic_module = static_cast<CyclicModule&>(*required_module); 129 // i. Assert: requiredModule.[[Status]] is either linking, linked, evaluating-async, or evaluated. 130 VERIFY(cyclic_module.m_status == ModuleStatus::Linking || cyclic_module.m_status == ModuleStatus::Linked || cyclic_module.m_status == ModuleStatus::EvaluatingAsync || cyclic_module.m_status == ModuleStatus::Evaluated); 131 132 // ii. Assert: requiredModule.[[Status]] is linking if and only if requiredModule is in stack. 133 VERIFY((cyclic_module.m_status == ModuleStatus::Linking) == (stack.contains_slow(&cyclic_module))); 134 135 // iii. If requiredModule.[[Status]] is linking, then 136 if (cyclic_module.m_status == ModuleStatus::Linking) { 137 // 1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]). 138 m_dfs_ancestor_index = min(m_dfs_ancestor_index.value(), cyclic_module.m_dfs_ancestor_index.value()); 139 } 140 } 141 } 142 143 // 10. Perform ? module.InitializeEnvironment(). 144 TRY(initialize_environment(vm)); 145 146 // 11. Assert: module occurs exactly once in stack. 147 size_t count = 0; 148 for (auto* module : stack) { 149 if (module == this) 150 count++; 151 } 152 VERIFY(count == 1); 153 154 // 12. Assert: module.[[DFSAncestorIndex]] ≤ module.[[DFSIndex]]. 155 VERIFY(m_dfs_ancestor_index.value() <= m_dfs_index.value()); 156 157 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] module {} after inner_linking has dfs {} and ancestor dfs {}", filename(), m_dfs_index.value(), m_dfs_ancestor_index.value()); 158 159 // 13. If module.[[DFSAncestorIndex]] = module.[[DFSIndex]], then 160 if (m_dfs_ancestor_index == m_dfs_index) { 161 // a. Let done be false. 162 // b. Repeat, while done is false, 163 while (true) { 164 // i. Let requiredModule be the last element in stack. 165 // ii. Remove the last element of stack. 166 auto* required_module = stack.take_last(); 167 168 // iii. Assert: requiredModule is a Cyclic Module Record. 169 VERIFY(is<CyclicModule>(*required_module)); 170 171 // iv. Set requiredModule.[[Status]] to linked. 172 static_cast<CyclicModule&>(*required_module).m_status = ModuleStatus::Linked; 173 174 // v. If requiredModule and module are the same Module Record, set done to true. 175 if (required_module == this) 176 break; 177 } 178 } 179 180 // 14. Return index. 181 return index; 182} 183 184// 16.2.1.5.2 Evaluate ( ), https://tc39.es/ecma262/#sec-moduleevaluation 185ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm) 186{ 187 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] evaluate[{}](vm)", this); 188 // 1. Assert: This call to Evaluate is not happening at the same time as another call to Evaluate within the surrounding agent. 189 // FIXME: Verify this somehow 190 191 // 2. Assert: module.[[Status]] is linked, evaluating-async, or evaluated. 192 VERIFY(m_status == ModuleStatus::Linked || m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated); 193 194 // NOTE: The spec does not catch the case where evaluate is called twice on a script which failed 195 // during evaluation. This means the script is evaluated but does not have a cycle root. 196 // In that case we first check if this module itself has a top level capability. 197 // See also: https://github.com/tc39/ecma262/issues/2823 . 198 if (m_top_level_capability != nullptr) 199 return verify_cast<Promise>(m_top_level_capability->promise().ptr()); 200 201 // 3. If module.[[Status]] is evaluating-async or evaluated, set module to module.[[CycleRoot]]. 202 if (m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated) { 203 // Note: This will continue this function with module.[[CycleRoot]] 204 VERIFY(m_cycle_root); 205 VERIFY(this != m_cycle_root); 206 VERIFY(m_cycle_root->m_status == ModuleStatus::Linked); 207 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] evaluate[{}](vm) deferring to cycle root at {}", this, m_cycle_root); 208 return m_cycle_root->evaluate(vm); 209 } 210 211 // 4. If module.[[TopLevelCapability]] is not empty, then 212 if (m_top_level_capability != nullptr) { 213 // a. Return module.[[TopLevelCapability]].[[Promise]]. 214 return verify_cast<Promise>(m_top_level_capability->promise().ptr()); 215 } 216 217 // 5. Let stack be a new empty List. 218 Vector<Module*> stack; 219 220 auto& realm = *vm.current_realm(); 221 222 // 6. Let capability be ! NewPromiseCapability(%Promise%). 223 // 7. Set module.[[TopLevelCapability]] to capability. 224 m_top_level_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); 225 226 // 8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)). 227 auto result = inner_module_evaluation(vm, stack, 0); 228 229 // 9. If result is an abrupt completion, then 230 if (result.is_throw_completion()) { 231 VERIFY(!m_evaluation_error.is_error()); 232 233 // a. For each Cyclic Module Record m of stack, do 234 for (auto* mod : stack) { 235 if (!is<CyclicModule>(*mod)) 236 continue; 237 238 auto& cyclic_module = static_cast<CyclicModule&>(*mod); 239 240 // i. Assert: m.[[Status]] is evaluating. 241 VERIFY(cyclic_module.m_status == ModuleStatus::Evaluating); 242 243 // ii. Set m.[[Status]] to evaluated. 244 cyclic_module.m_status = ModuleStatus::Evaluated; 245 246 // iii. Set m.[[EvaluationError]] to result. 247 cyclic_module.m_evaluation_error = result.throw_completion(); 248 } 249 250 // b. Assert: module.[[Status]] is evaluated. 251 VERIFY(m_status == ModuleStatus::Evaluated); 252 253 // c. Assert: module.[[EvaluationError]] is result. 254 VERIFY(m_evaluation_error.is_error() && same_value(*m_evaluation_error.throw_completion().value(), *result.throw_completion().value())); 255 256 // d. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »). 257 MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), *result.throw_completion().value())); 258 } 259 // 10. Else, 260 else { 261 // a. Assert: module.[[Status]] is evaluating-async or evaluated. 262 VERIFY(m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated); 263 // b. Assert: module.[[EvaluationError]] is empty. 264 VERIFY(!m_evaluation_error.is_error()); 265 266 // c. If module.[[AsyncEvaluation]] is false, then 267 if (!m_async_evaluation) { 268 // i. Assert: module.[[Status]] is evaluated. 269 VERIFY(m_status == ModuleStatus::Evaluated); 270 // ii. Perform ! Call(capability.[[Resolve]], undefined, « undefined »). 271 MUST(call(vm, *m_top_level_capability->resolve(), js_undefined(), js_undefined())); 272 } 273 274 // d. Assert: stack is empty. 275 VERIFY(stack.is_empty()); 276 } 277 278 // 11. Return capability.[[Promise]]. 279 return verify_cast<Promise>(m_top_level_capability->promise().ptr()); 280} 281 282// 16.2.1.5.2.1 InnerModuleEvaluation ( module, stack, index ), https://tc39.es/ecma262/#sec-innermoduleevaluation 283ThrowCompletionOr<u32> CyclicModule::inner_module_evaluation(VM& vm, Vector<Module*>& stack, u32 index) 284{ 285 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_evaluation[{}](vm, {}, {})", this, DeprecatedString::join(", "sv, stack), index); 286 // Note: Step 1 is performed in Module.cpp 287 288 // 2. If module.[[Status]] is evaluating-async or evaluated, then 289 if (m_status == ModuleStatus::EvaluatingAsync || m_status == ModuleStatus::Evaluated) { 290 // a. If module.[[EvaluationError]] is empty, return index. 291 if (!m_evaluation_error.is_error()) 292 return index; 293 294 // b. Otherwise, return ? module.[[EvaluationError]]. 295 return m_evaluation_error.throw_completion(); 296 } 297 298 // 3. If module.[[Status]] is evaluating, return index. 299 if (m_status == ModuleStatus::Evaluating) 300 return index; 301 302 // 4. Assert: module.[[Status]] is linked. 303 VERIFY(m_status == ModuleStatus::Linked); 304 305 // 5. Set module.[[Status]] to evaluating. 306 m_status = ModuleStatus::Evaluating; 307 308 // 6. Set module.[[DFSIndex]] to index. 309 m_dfs_index = index; 310 311 // 7. Set module.[[DFSAncestorIndex]] to index. 312 m_dfs_ancestor_index = index; 313 314 // 8. Set module.[[PendingAsyncDependencies]] to 0. 315 m_pending_async_dependencies = 0; 316 317 // 9. Set index to index + 1. 318 ++index; 319 320 // 10. Append module to stack. 321 stack.append(this); 322 323 // 11. For each String required of module.[[RequestedModules]], do 324 for (auto& required : m_requested_modules) { 325 326 // a. Let requiredModule be ! HostResolveImportedModule(module, required). 327 auto* required_module = MUST(vm.host_resolve_imported_module(NonnullGCPtr<Module>(*this), required)).ptr(); 328 // b. NOTE: Link must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully. 329 330 // c. Set index to ? InnerModuleEvaluation(requiredModule, stack, index). 331 index = TRY(required_module->inner_module_evaluation(vm, stack, index)); 332 333 // d. If requiredModule is a Cyclic Module Record, then 334 if (!is<CyclicModule>(*required_module)) 335 continue; 336 337 auto* cyclic_module = static_cast<CyclicModule*>(required_module); 338 // i. Assert: requiredModule.[[Status]] is either evaluating, evaluating-async, or evaluated. 339 VERIFY(cyclic_module->m_status == ModuleStatus::Evaluating || cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated); 340 341 // ii. Assert: requiredModule.[[Status]] is evaluating if and only if requiredModule is in stack. 342 VERIFY(cyclic_module->m_status != ModuleStatus::Evaluating || stack.contains_slow(cyclic_module)); 343 344 // iii. If requiredModule.[[Status]] is evaluating, then 345 if (cyclic_module->m_status == ModuleStatus::Evaluating) { 346 // 1. Set module.[[DFSAncestorIndex]] to min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]]). 347 m_dfs_ancestor_index = min(m_dfs_ancestor_index.value(), cyclic_module->m_dfs_ancestor_index.value()); 348 } 349 // iv. Else, 350 else { 351 // 1. Set requiredModule to requiredModule.[[CycleRoot]]. 352 cyclic_module = cyclic_module->m_cycle_root; 353 354 // 2. Assert: requiredModule.[[Status]] is evaluating-async or evaluated. 355 VERIFY(cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated); 356 357 // 3. If requiredModule.[[EvaluationError]] is not empty, return ? requiredModule.[[EvaluationError]]. 358 if (cyclic_module->m_evaluation_error.is_error()) 359 return cyclic_module->m_evaluation_error.throw_completion(); 360 } 361 362 // v. If requiredModule.[[AsyncEvaluation]] is true, then 363 if (cyclic_module->m_async_evaluation) { 364 // 1. Set module.[[PendingAsyncDependencies]] to module.[[PendingAsyncDependencies]] + 1. 365 ++m_pending_async_dependencies.value(); 366 367 // 2. Append module to requiredModule.[[AsyncParentModules]]. 368 cyclic_module->m_async_parent_modules.append(this); 369 } 370 } 371 372 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] inner_module_evaluation on {} has tla: {} and pending async dep: {} dfs: {} ancestor dfs: {}", filename(), m_has_top_level_await, m_pending_async_dependencies.value(), m_dfs_index.value(), m_dfs_ancestor_index.value()); 373 // 12. If module.[[PendingAsyncDependencies]] > 0 or module.[[HasTLA]] is true, then 374 if (m_pending_async_dependencies.value() > 0 || m_has_top_level_await) { 375 // a. Assert: module.[[AsyncEvaluation]] is false and was never previously set to true. 376 VERIFY(!m_async_evaluation); // FIXME: I don't think we can check previously? 377 378 // b. Set module.[[AsyncEvaluation]] to true. 379 m_async_evaluation = true; 380 // c. NOTE: The order in which module records have their [[AsyncEvaluation]] fields transition to true is significant. (See 16.2.1.5.2.4.) 381 382 // d. If module.[[PendingAsyncDependencies]] is 0, perform ExecuteAsyncModule(module). 383 if (m_pending_async_dependencies.value() == 0) 384 execute_async_module(vm); 385 } 386 // 13. Otherwise, perform ? module.ExecuteModule(). 387 else { 388 TRY(execute_module(vm)); 389 } 390 391 // 14. Assert: module occurs exactly once in stack. 392 auto count = 0; 393 for (auto* module : stack) { 394 if (module == this) 395 count++; 396 } 397 VERIFY(count == 1); 398 399 // 15. Assert: module.[[DFSAncestorIndex]] ≤ module.[[DFSIndex]]. 400 VERIFY(m_dfs_ancestor_index.value() <= m_dfs_index.value()); 401 402 // 16. If module.[[DFSAncestorIndex]] = module.[[DFSIndex]], then 403 if (m_dfs_ancestor_index == m_dfs_index) { 404 // a. Let done be false. 405 bool done = false; 406 // b. Repeat, while done is false, 407 while (!done) { 408 409 // i. Let requiredModule be the last element in stack. 410 // ii. Remove the last element of stack. 411 auto* required_module = stack.take_last(); 412 413 // iii. Assert: requiredModule is a Cyclic Module Record. 414 VERIFY(is<CyclicModule>(*required_module)); 415 416 auto& cyclic_module = static_cast<CyclicModule&>(*required_module); 417 418 // iv. If requiredModule.[[AsyncEvaluation]] is false, set requiredModule.[[Status]] to evaluated. 419 if (!cyclic_module.m_async_evaluation) 420 cyclic_module.m_status = ModuleStatus::Evaluated; 421 // v. Otherwise, set requiredModule.[[Status]] to evaluating-async. 422 else 423 cyclic_module.m_status = ModuleStatus::EvaluatingAsync; 424 425 // vi. If requiredModule and module are the same Module Record, set done to true. 426 if (required_module == this) 427 done = true; 428 429 // vii. Set requiredModule.[[CycleRoot]] to module. 430 cyclic_module.m_cycle_root = this; 431 } 432 } 433 434 // 17. Return index. 435 return index; 436} 437 438ThrowCompletionOr<void> CyclicModule::initialize_environment(VM&) 439{ 440 // Note: In ecma262 this is never called on a cyclic module only on SourceTextModules. 441 // So this check is to make sure we don't accidentally call this. 442 VERIFY_NOT_REACHED(); 443} 444 445ThrowCompletionOr<void> CyclicModule::execute_module(VM&, GCPtr<PromiseCapability>) 446{ 447 // Note: In ecma262 this is never called on a cyclic module only on SourceTextModules. 448 // So this check is to make sure we don't accidentally call this. 449 VERIFY_NOT_REACHED(); 450} 451 452// 16.2.1.5.2.2 ExecuteAsyncModule ( module ), https://tc39.es/ecma262/#sec-execute-async-module 453void CyclicModule::execute_async_module(VM& vm) 454{ 455 auto& realm = *vm.current_realm(); 456 457 dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] executing async module {}", filename()); 458 // 1. Assert: module.[[Status]] is evaluating or evaluating-async. 459 VERIFY(m_status == ModuleStatus::Evaluating || m_status == ModuleStatus::EvaluatingAsync); 460 // 2. Assert: module.[[HasTLA]] is true. 461 VERIFY(m_has_top_level_await); 462 463 // 3. Let capability be ! NewPromiseCapability(%Promise%). 464 auto capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); 465 466 // 4. Let fulfilledClosure be a new Abstract Closure with no parameters that captures module and performs the following steps when called: 467 auto fulfilled_closure = [&](VM& vm) -> ThrowCompletionOr<Value> { 468 // a. Perform AsyncModuleExecutionFulfilled(module). 469 async_module_execution_fulfilled(vm); 470 471 // b. Return undefined. 472 return js_undefined(); 473 }; 474 475 // 5. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 0, "", « »). 476 auto on_fulfilled = NativeFunction::create(realm, move(fulfilled_closure), 0, ""); 477 478 // 6. Let rejectedClosure be a new Abstract Closure with parameters (error) that captures module and performs the following steps when called: 479 auto rejected_closure = [&](VM& vm) -> ThrowCompletionOr<Value> { 480 auto error = vm.argument(0); 481 482 // a. Perform AsyncModuleExecutionRejected(module, error). 483 async_module_execution_rejected(vm, error); 484 485 // b. Return undefined. 486 return js_undefined(); 487 }; 488 489 // 7. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »). 490 auto on_rejected = NativeFunction::create(realm, move(rejected_closure), 0, ""); 491 492 // 8. Perform PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected). 493 verify_cast<Promise>(capability->promise().ptr())->perform_then(on_fulfilled, on_rejected, {}); 494 495 // 9. Perform ! module.ExecuteModule(capability). 496 MUST(execute_module(vm, capability)); 497 498 // 10. Return unused. 499} 500 501// 16.2.1.5.2.3 GatherAvailableAncestors ( module, execList ), https://tc39.es/ecma262/#sec-gather-available-ancestors 502void CyclicModule::gather_available_ancestors(Vector<CyclicModule*>& exec_list) 503{ 504 // 1. For each Cyclic Module Record m of module.[[AsyncParentModules]], do 505 for (auto* module : m_async_parent_modules) { 506 // a. If execList does not contain m and m.[[CycleRoot]].[[EvaluationError]] is empty, then 507 if (!exec_list.contains_slow(module) && !module->m_cycle_root->m_evaluation_error.is_error()) { 508 // i. Assert: m.[[Status]] is evaluating-async. 509 VERIFY(module->m_status == ModuleStatus::EvaluatingAsync); 510 511 // ii. Assert: m.[[EvaluationError]] is empty. 512 VERIFY(!module->m_evaluation_error.is_error()); 513 514 // iii. Assert: m.[[AsyncEvaluation]] is true. 515 VERIFY(module->m_async_evaluation); 516 517 // iv. Assert: m.[[PendingAsyncDependencies]] > 0. 518 VERIFY(module->m_pending_async_dependencies.value() > 0); 519 520 // v. Set m.[[PendingAsyncDependencies]] to m.[[PendingAsyncDependencies]] - 1. 521 module->m_pending_async_dependencies.value()--; 522 523 // vi. If m.[[PendingAsyncDependencies]] = 0, then 524 if (module->m_pending_async_dependencies.value() == 0) { 525 // 1. Append m to execList. 526 exec_list.append(module); 527 528 // 2. If m.[[HasTLA]] is false, perform GatherAvailableAncestors(m, execList). 529 if (!module->m_has_top_level_await) 530 module->gather_available_ancestors(exec_list); 531 } 532 } 533 } 534 535 // 2. Return unused. 536} 537 538// 16.2.1.5.2.4 AsyncModuleExecutionFulfilled ( module ), https://tc39.es/ecma262/#sec-async-module-execution-fulfilled 539void CyclicModule::async_module_execution_fulfilled(VM& vm) 540{ 541 // 1. If module.[[Status]] is evaluated, then 542 if (m_status == ModuleStatus::Evaluated) { 543 // a. Assert: module.[[EvaluationError]] is not empty. 544 VERIFY(m_evaluation_error.is_error()); 545 546 // b. Return unused. 547 return; 548 } 549 550 // 2. Assert: module.[[Status]] is evaluating-async. 551 VERIFY(m_status == ModuleStatus::EvaluatingAsync); 552 553 // 3. Assert: module.[[AsyncEvaluation]] is true. 554 VERIFY(m_async_evaluation); 555 556 // 4. Assert: module.[[EvaluationError]] is empty. 557 VERIFY(!m_evaluation_error.is_error()); 558 559 // 5. Set module.[[AsyncEvaluation]] to false. 560 m_async_evaluation = false; 561 562 // 6. Set module.[[Status]] to evaluated. 563 m_status = ModuleStatus::Evaluated; 564 565 // 7. If module.[[TopLevelCapability]] is not empty, then 566 if (m_top_level_capability != nullptr) { 567 // a. Assert: module.[[CycleRoot]] is module. 568 VERIFY(m_cycle_root == this); 569 570 // b. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »). 571 MUST(call(vm, *m_top_level_capability->resolve(), js_undefined(), js_undefined())); 572 } 573 574 // 8. Let execList be a new empty List. 575 Vector<CyclicModule*> exec_list; 576 577 // 9. Perform GatherAvailableAncestors(module, execList). 578 gather_available_ancestors(exec_list); 579 580 // 10. Let sortedExecList be a List whose elements are the elements of execList, in the order in which they had their [[AsyncEvaluation]] fields set to true in InnerModuleEvaluation. 581 // FIXME: Sort the list. To do this we need to use more than an Optional<bool> to track [[AsyncEvaluation]]. 582 583 // 11. Assert: All elements of sortedExecList have their [[AsyncEvaluation]] field set to true, [[PendingAsyncDependencies]] field set to 0, and [[EvaluationError]] field set to empty. 584 VERIFY(all_of(exec_list, [&](CyclicModule* module) { return module->m_async_evaluation && module->m_pending_async_dependencies.value() == 0 && !module->m_evaluation_error.is_error(); })); 585 586 // 12. For each Cyclic Module Record m of sortedExecList, do 587 for (auto* module : exec_list) { 588 // a. If m.[[Status]] is evaluated, then 589 if (module->m_status == ModuleStatus::Evaluated) { 590 // i. Assert: m.[[EvaluationError]] is not empty. 591 VERIFY(module->m_evaluation_error.is_error()); 592 } 593 // b. Else if m.[[HasTLA]] is true, then 594 else if (module->m_has_top_level_await) { 595 // i. Perform ExecuteAsyncModule(m). 596 module->execute_async_module(vm); 597 } 598 // c. Else, 599 else { 600 // i. Let result be m.ExecuteModule(). 601 auto result = module->execute_module(vm); 602 603 // ii. If result is an abrupt completion, then 604 if (result.is_throw_completion()) { 605 // 1. Perform AsyncModuleExecutionRejected(m, result.[[Value]]). 606 module->async_module_execution_rejected(vm, *result.throw_completion().value()); 607 } 608 // iii. Else, 609 else { 610 // 1. Set m.[[Status]] to evaluated. 611 module->m_status = ModuleStatus::Evaluated; 612 613 // 2. If m.[[TopLevelCapability]] is not empty, then 614 if (module->m_top_level_capability != nullptr) { 615 // a. Assert: m.[[CycleRoot]] is m. 616 VERIFY(module->m_cycle_root == module); 617 618 // b. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »). 619 MUST(call(vm, *module->m_top_level_capability->resolve(), js_undefined(), js_undefined())); 620 } 621 } 622 } 623 } 624 625 // 13. Return unused. 626} 627 628// 16.2.1.5.2.5 AsyncModuleExecutionRejected ( module, error ), https://tc39.es/ecma262/#sec-async-module-execution-rejected 629void CyclicModule::async_module_execution_rejected(VM& vm, Value error) 630{ 631 // 1. If module.[[Status]] is evaluated, then 632 if (m_status == ModuleStatus::Evaluated) { 633 // a. Assert: module.[[EvaluationError]] is not empty. 634 VERIFY(m_evaluation_error.is_error()); 635 636 // b. Return unused. 637 return; 638 } 639 640 // 2. Assert: module.[[Status]] is evaluating-async. 641 VERIFY(m_status == ModuleStatus::EvaluatingAsync); 642 643 // 3. Assert: module.[[AsyncEvaluation]] is true. 644 VERIFY(m_async_evaluation); 645 646 // 4. Assert: module.[[EvaluationError]] is empty. 647 VERIFY(!m_evaluation_error.is_error()); 648 649 // 5. Set module.[[EvaluationError]] to ThrowCompletion(error) 650 m_evaluation_error = throw_completion(error); 651 652 // 6. Set module.[[Status]] to evaluated. 653 m_status = ModuleStatus::Evaluated; 654 655 // 7. For each Cyclic Module Record m of module.[[AsyncParentModules]], do 656 for (auto* module : m_async_parent_modules) { 657 658 // a. Perform AsyncModuleExecutionRejected(m, error). 659 module->async_module_execution_rejected(vm, error); 660 } 661 662 // 8. If module.[[TopLevelCapability]] is not empty, then 663 if (m_top_level_capability != nullptr) { 664 // a. Assert: module.[[CycleRoot]] is module. 665 VERIFY(m_cycle_root == this); 666 667 // b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »). 668 MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), error)); 669 } 670 671 // 9. Return unused. 672} 673 674}