diff --git a/Userland/Libraries/LibJS/CyclicModule.cpp b/Userland/Libraries/LibJS/CyclicModule.cpp index 802c8ec802..d21a2af46d 100644 --- a/Userland/Libraries/LibJS/CyclicModule.cpp +++ b/Userland/Libraries/LibJS/CyclicModule.cpp @@ -254,8 +254,8 @@ ThrowCompletionOr CyclicModule::inner_module_linking(VM& vm, Vector(*this), required)); + // a. Let requiredModule be GetImportedModule(module, required). + auto required_module = get_imported_module(required); // b. Set index to ? InnerModuleLinking(requiredModule, stack, index). index = TRY(required_module->inner_module_linking(vm, stack, index)); @@ -461,18 +461,17 @@ ThrowCompletionOr CyclicModule::inner_module_evaluation(VM& vm, Vector(*this), required)).ptr(); - // b. NOTE: Link must be completed successfully prior to invoking this method, so every requested module is guaranteed to resolve successfully. + // a. Let requiredModule be GetImportedModule(module, required). + auto required_module = get_imported_module(required); - // c. Set index to ? InnerModuleEvaluation(requiredModule, stack, index). + // b. Set index to ? InnerModuleEvaluation(requiredModule, stack, index). index = TRY(required_module->inner_module_evaluation(vm, stack, index)); - // d. If requiredModule is a Cyclic Module Record, then + // c. If requiredModule is a Cyclic Module Record, then if (!is(*required_module)) continue; - auto* cyclic_module = static_cast(required_module); + JS::NonnullGCPtr cyclic_module = verify_cast(*required_module); // i. Assert: requiredModule.[[Status]] is either evaluating, evaluating-async, or evaluated. VERIFY(cyclic_module->m_status == ModuleStatus::Evaluating || cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated); @@ -487,7 +486,8 @@ ThrowCompletionOr CyclicModule::inner_module_evaluation(VM& vm, Vectorm_cycle_root; + VERIFY(cyclic_module->m_cycle_root); + cyclic_module = *cyclic_module->m_cycle_root; // 2. Assert: requiredModule.[[Status]] is evaluating-async or evaluated. VERIFY(cyclic_module->m_status == ModuleStatus::EvaluatingAsync || cyclic_module->m_status == ModuleStatus::Evaluated); @@ -808,4 +808,26 @@ void CyclicModule::async_module_execution_rejected(VM& vm, Value error) // 9. Return unused. } +// 16.2.1.7 GetImportedModule ( referrer, specifier ), https://tc39.es/ecma262/#sec-GetImportedModule +NonnullGCPtr CyclicModule::get_imported_module(ModuleRequest const& request) +{ + // 1. Assert: Exactly one element of referrer.[[LoadedModules]] is a Record whose [[Specifier]] is specifier, + // since LoadRequestedModules has completed successfully on referrer prior to invoking this abstract operation. + size_t element_with_specifier_count = 0; + for (auto const& loaded_module : m_loaded_modules) { + if (loaded_module.specifier == request.module_specifier) + ++element_with_specifier_count; + } + VERIFY(element_with_specifier_count == 1); + + for (auto const& loaded_module : m_loaded_modules) { + if (loaded_module.specifier == request.module_specifier) { + // 2. Let record be the Record in referrer.[[LoadedModules]] whose [[Specifier]] is specifier. + // 3. Return record.[[Module]]. + return loaded_module.module; + } + } + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibJS/CyclicModule.h b/Userland/Libraries/LibJS/CyclicModule.h index 09f9971a1e..259eeb773f 100644 --- a/Userland/Libraries/LibJS/CyclicModule.h +++ b/Userland/Libraries/LibJS/CyclicModule.h @@ -82,6 +82,8 @@ protected: virtual ThrowCompletionOr initialize_environment(VM& vm); virtual ThrowCompletionOr execute_module(VM& vm, GCPtr capability = {}); + [[nodiscard]] NonnullGCPtr get_imported_module(ModuleRequest const&); + void execute_async_module(VM& vm); void gather_available_ancestors(Vector& exec_list); void async_module_execution_fulfilled(VM& vm); diff --git a/Userland/Libraries/LibJS/SourceTextModule.cpp b/Userland/Libraries/LibJS/SourceTextModule.cpp index 1d14b78183..755723a86f 100644 --- a/Userland/Libraries/LibJS/SourceTextModule.cpp +++ b/Userland/Libraries/LibJS/SourceTextModule.cpp @@ -314,8 +314,8 @@ ThrowCompletionOr> SourceTextModule::get_exported_na // 8. For each ExportEntry Record e of module.[[StarExportEntries]], do for (auto& entry : m_star_export_entries) { // a. Assert: e.[[ModuleRequest]] is not null. - // b. Let requestedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]). - auto requested_module = TRY(vm.host_resolve_imported_module(NonnullGCPtr(*this), entry.module_request())); + // b. Let requestedModule be GetImportedModule(module, e.[[ModuleRequest]]). + auto requested_module = get_imported_module(entry.module_request()); // c. Let starNames be ? requestedModule.GetExportedNames(exportStarSet). auto star_names = TRY(requested_module->get_exported_names(vm, export_star_set)); @@ -368,8 +368,8 @@ ThrowCompletionOr SourceTextModule::initialize_environment(VM& vm) // 7. For each ImportEntry Record in of module.[[ImportEntries]], do for (auto& import_entry : m_import_entries) { - // a. Let importedModule be ! HostResolveImportedModule(module, in.[[ModuleRequest]]). - auto imported_module = MUST(vm.host_resolve_imported_module(NonnullGCPtr(*this), import_entry.module_request())); + // a. Let importedModule be GetImportedModule(module, in.[[ModuleRequest]]). + auto imported_module = get_imported_module(import_entry.module_request()); // b. NOTE: The above call cannot fail because imported module requests are a subset of module.[[RequestedModules]], and these have been resolved earlier in this algorithm. // c. If in.[[ImportName]] is namespace-object, then @@ -584,8 +584,8 @@ ThrowCompletionOr SourceTextModule::resolve_export(VM& vm, Depr continue; // i. Assert: e.[[ModuleRequest]] is not null. - // ii. Let importedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]). - auto imported_module = TRY(vm.host_resolve_imported_module(NonnullGCPtr(*this), entry.module_request())); + // ii. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]). + auto imported_module = get_imported_module(entry.module_request()); // iii. If e.[[ImportName]] is all, then if (entry.kind == ExportEntry::Kind::ModuleRequestAll) { @@ -625,8 +625,8 @@ ThrowCompletionOr SourceTextModule::resolve_export(VM& vm, Depr // 9. For each ExportEntry Record e of module.[[StarExportEntries]], do for (auto& entry : m_star_export_entries) { // a. Assert: e.[[ModuleRequest]] is not null. - // b. Let importedModule be ? HostResolveImportedModule(module, e.[[ModuleRequest]]). - auto imported_module = TRY(vm.host_resolve_imported_module(NonnullGCPtr(*this), entry.module_request())); + // b. Let importedModule be GetImportedModule(module, e.[[ModuleRequest]]). + auto imported_module = get_imported_module(entry.module_request()); // c. Let resolution be ? importedModule.ResolveExport(exportName, resolveSet). auto resolution = TRY(imported_module->resolve_export(vm, export_name, resolve_set));