diff options
author | networkException <git@nwex.de> | 2022-10-03 20:58:36 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-10-06 16:41:36 +0200 |
commit | 992311c0ee8d439a6d4b4f58e56d3d83338627b6 (patch) | |
tree | fa0bf6ab4d6abd9c9141ccd5ef41d9a70e1482f6 /Userland/Libraries | |
parent | 83554526f0488b063e0fff07f0fd11d86301e765 (diff) | |
download | serenity-992311c0ee8d439a6d4b4f58e56d3d83338627b6.zip |
LibWeb: Implement ModuleMap and expose it on EnvironmentSettingsObject
This patch adds the ModuleMap class used to keep track of the type and
url of a module as well as the fetching state associated. Each
environment settings object now also has a module map.
Diffstat (limited to 'Userland/Libraries')
5 files changed, 143 insertions, 1 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 53dc40f06f..ae7969b4da 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -258,6 +258,7 @@ set(SOURCES HTML/Scripting/ClassicScript.cpp HTML/Scripting/Environments.cpp HTML/Scripting/ExceptionReporter.cpp + HTML/Scripting/ModuleMap.cpp HTML/Scripting/Script.cpp HTML/Scripting/WindowEnvironmentSettingsObject.cpp HTML/Storage.cpp diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp index 961bc39459..df530f78dd 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.cpp @@ -11,6 +11,7 @@ #include <LibWeb/HTML/PromiseRejectionEvent.h> #include <LibWeb/HTML/Scripting/Environments.h> #include <LibWeb/HTML/Scripting/ExceptionReporter.h> +#include <LibWeb/HTML/Scripting/WindowEnvironmentSettingsObject.h> #include <LibWeb/HTML/Window.h> #include <LibWeb/Page/Page.h> @@ -34,6 +35,11 @@ JS::ExecutionContext& EnvironmentSettingsObject::realm_execution_context() return *m_realm_execution_context; } +ModuleMap& EnvironmentSettingsObject::module_map() +{ + return m_module_map; +} + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object%27s-realm JS::Realm& EnvironmentSettingsObject::realm() { diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h index 6c42681ddd..c5169fb022 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/Environments.h @@ -14,6 +14,7 @@ #include <LibJS/Runtime/Realm.h> #include <LibWeb/HTML/EventLoop/EventLoop.h> #include <LibWeb/HTML/Origin.h> +#include <LibWeb/HTML/Scripting/ModuleMap.h> namespace Web::HTML { @@ -61,7 +62,8 @@ struct EnvironmentSettingsObject // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-target-browsing-context JS::ExecutionContext& realm_execution_context(); - // FIXME: A module map https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-module-map + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-module-map + ModuleMap& module_map(); // https://html.spec.whatwg.org/multipage/webappapis.html#responsible-document virtual JS::GCPtr<DOM::Document> responsible_document() = 0; @@ -113,6 +115,8 @@ protected: private: NonnullOwnPtr<JS::ExecutionContext> m_realm_execution_context; + ModuleMap m_module_map; + EventLoop* m_responsible_event_loop { nullptr }; // https://html.spec.whatwg.org/multipage/webappapis.html#outstanding-rejected-promises-weak-set diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.cpp new file mode 100644 index 0000000000..ab775f0149 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, networkException <networkexception@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/HTML/Scripting/ModuleMap.h> + +namespace Web::HTML { + +bool ModuleMap::is_fetching(AK::URL const& url, String const& type) const +{ + return is(url, type, EntryType::Fetching); +} + +bool ModuleMap::is_failed(AK::URL const& url, String const& type) const +{ + return is(url, type, EntryType::Failed); +} + +bool ModuleMap::is(AK::URL const& url, String const& type, EntryType entry_type) const +{ + auto value = m_values.get({ url, type }); + if (!value.has_value()) + return false; + + return value->type == entry_type; +} + +Optional<ModuleMap::Entry> ModuleMap::get(AK::URL const& url, String const& type) const +{ + return m_values.get({ url, type }); +} + +AK::HashSetResult ModuleMap::set(AK::URL const& url, String const& type, Entry entry) +{ + auto callbacks = m_callbacks.get({ url, type }); + if (callbacks.has_value()) + for (auto const& callback : *callbacks) + callback(entry); + + return m_values.set({ url, type }, entry); +} + +void ModuleMap::wait_for_change(AK::URL const& url, String const& type, Function<void(Entry)> callback) +{ + m_callbacks.ensure({ url, type }).append(move(callback)); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.h b/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.h new file mode 100644 index 0000000000..90143af09a --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Scripting/ModuleMap.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022, networkException <networkexception@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/HTML/Scripting/ModuleScript.h> + +namespace Web::HTML { + +class ModuleLocationTuple { +public: + ModuleLocationTuple(AK::URL url, String type) + : m_url(move(url)) + , m_type(move(type)) + { + } + + AK::URL const& url() const { return m_url; }; + String const& type() const { return m_type; } + + bool operator==(ModuleLocationTuple const& other) const + { + return other.url() == m_url && other.type() == m_type; + }; + +private: + AK::URL m_url; + String m_type; +}; + +// https://html.spec.whatwg.org/multipage/webappapis.html#module-map +class ModuleMap { + AK_MAKE_NONCOPYABLE(ModuleMap); + +public: + ModuleMap() = default; + ~ModuleMap() = default; + + enum class EntryType { + Fetching, + Failed, + ModuleScript + }; + + struct Entry { + EntryType type; + JavaScriptModuleScript* module_script; + }; + + bool is_fetching(AK::URL const& url, String const& type) const; + bool is_failed(AK::URL const& url, String const& type) const; + + bool is(AK::URL const& url, String const& type, EntryType) const; + + Optional<Entry> get(AK::URL const& url, String const& type) const; + + AK::HashSetResult set(AK::URL const& url, String const& type, Entry); + + void wait_for_change(AK::URL const& url, String const& type, Function<void(Entry)> callback); + +private: + HashMap<ModuleLocationTuple, Entry> m_values; + HashMap<ModuleLocationTuple, Vector<Function<void(Entry)>>> m_callbacks; +}; + +} + +namespace AK { + +template<> +struct Traits<Web::HTML::ModuleLocationTuple> : public GenericTraits<Web::HTML::ModuleLocationTuple> { + static unsigned hash(Web::HTML::ModuleLocationTuple const& tuple) + { + return pair_int_hash(tuple.url().to_string().hash(), tuple.type().hash()); + } +}; + +} |