Преглед на файлове

LibWeb: Implement two module related host hooks

This patch adds support for the HostGetSupportedImportAssertions and
HostResolveImportedModule host hooks.

Co-authored-by: davidot <davidot@serenityos.org>
networkException преди 2 години
родител
ревизия
c51cf66347
променени са 1 файла, в които са добавени 55 реда и са изтрити 3 реда
  1. 55 3
      Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp

+ 55 - 3
Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp

@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2021-2022, Andreas Kling <kling@serenityos.org>
  * Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
+ * Copyright (c) 2022, networkException <networkexception@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -20,6 +21,7 @@
 #include <LibWeb/HTML/Scripting/ClassicScript.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
+#include <LibWeb/HTML/Scripting/Fetching.h>
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/WindowProxy.h>
 #include <LibWeb/Platform/EventLoopPlugin.h>
@@ -306,10 +308,60 @@ JS::VM& main_thread_vm()
         // FIXME: Implement 8.1.5.5.1 HostGetImportMetaProperties(moduleRecord), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetimportmetaproperties
         // FIXME: Implement 8.1.5.5.2 HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability), https://html.spec.whatwg.org/multipage/webappapis.html#hostimportmoduledynamically(referencingscriptormodule,-modulerequest,-promisecapability)
         // FIXME: Implement 8.1.5.5.3 HostResolveImportedModule(referencingScriptOrModule, moduleRequest), https://html.spec.whatwg.org/multipage/webappapis.html#hostresolveimportedmodule(referencingscriptormodule,-modulerequest)
-        // FIXME: Implement 8.1.5.5.4 HostGetSupportedImportAssertions(), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetsupportedimportassertions
 
-        vm->host_resolve_imported_module = [](JS::ScriptOrModule, JS::ModuleRequest const&) -> JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Module>> {
-            return vm->throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Modules in the browser");
+        // 8.1.5.5.4 HostGetSupportedImportAssertions(), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetsupportedimportassertions
+        vm->host_get_supported_import_assertions = []() -> Vector<String> {
+            // 1. Return « "type" ».
+            return { "type"sv };
+        };
+
+        // 8.1.5.5.3 HostResolveImportedModule(referencingScriptOrModule, moduleRequest), https://html.spec.whatwg.org/multipage/webappapis.html#hostresolveimportedmodule(referencingscriptormodule,-modulerequest)
+        vm->host_resolve_imported_module = [](JS::ScriptOrModule const& referencing_string_or_module, JS::ModuleRequest const& module_request) -> JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Module>> {
+            // 1. Let settings object be the current settings object.
+            auto* settings_object = &HTML::current_settings_object();
+
+            // 2. Let base URL be settings object's API base URL.
+            auto base_url = settings_object->api_base_url();
+
+            // 3. If referencingScriptOrModule is not null, then:
+            if (!referencing_string_or_module.has<Empty>()) {
+                // 1. Let referencing script be referencingScriptOrModule.[[HostDefined]].
+                auto const& referencing_script = verify_cast<HTML::Script>(referencing_string_or_module.has<JS::NonnullGCPtr<JS::Script>>() ? referencing_string_or_module.get<JS::NonnullGCPtr<JS::Script>>()->host_defined() : referencing_string_or_module.get<JS::NonnullGCPtr<JS::Module>>()->host_defined());
+
+                // 2. Set settings object to referencing script's settings object.
+                settings_object = &referencing_script->settings_object();
+
+                // 3. Set base URL to referencing script's base URL.
+                base_url = referencing_script->base_url();
+
+                // 4. Assert: base URL is not null, as referencing script is a classic script or a JavaScript module script.
+                VERIFY(base_url.is_valid());
+            }
+
+            // 4. Let moduleMap be settings object's module map.
+            auto& module_map = settings_object->module_map();
+
+            // 5. Let url be the result of resolving a module specifier given base URL and moduleRequest.[[Specifier]].
+            auto url = HTML::resolve_module_specifier(module_request, base_url);
+
+            // 6. Assert: url is never failure, because resolving a module specifier must have been previously successful
+            //    with these same two arguments (either while creating the corresponding module script, or in fetch an import() module script graph).
+            VERIFY(url.is_valid());
+
+            // 7. Let moduleType be the result of running the module type from module request steps given moduleRequest.
+            auto module_type = HTML::module_type_from_module_request(module_request);
+
+            // 8. Let resolved module script be moduleMap[(url, moduleType)]. (This entry must exist for us to have gotten to this point.)
+            auto resolved_module = module_map.get(url, module_type).value();
+
+            // 9. Assert: resolved module script is a module script (i.e., is not null or "fetching").
+            VERIFY(resolved_module.type == HTML::ModuleMap::EntryType::ModuleScript);
+
+            // 10. Assert: resolved module script's record is not null.
+            VERIFY(resolved_module.module_script->record());
+
+            // 11. Return resolved module script's record.
+            return JS::NonnullGCPtr(*resolved_module.module_script->record());
         };
 
         // NOTE: We push a dummy execution context onto the JS execution context stack,