From d946d94e2d28287f7e253feed72e1930bed1af18 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 6 Dec 2024 08:57:33 +0000 Subject: [PATCH] LibWeb: Improve relList feature detection support `DOMTokenList.supports()` is now correct for all possible `rel` attribute values for `link`, `a`, `area` and `form` elements. --- Libraries/LibWeb/DOM/DOMTokenList.cpp | 18 ++-- Libraries/LibWeb/DOM/DOMTokenList.h | 19 +++++ .../semantics/rellist-feature-detection.txt | 9 ++ .../semantics/rellist-feature-detection.html | 84 +++++++++++++++++++ 4 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/html/semantics/rellist-feature-detection.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/html/semantics/rellist-feature-detection.html diff --git a/Libraries/LibWeb/DOM/DOMTokenList.cpp b/Libraries/LibWeb/DOM/DOMTokenList.cpp index c34d0480b65..31f8c06751d 100644 --- a/Libraries/LibWeb/DOM/DOMTokenList.cpp +++ b/Libraries/LibWeb/DOM/DOMTokenList.cpp @@ -211,21 +211,21 @@ WebIDL::ExceptionOr DOMTokenList::replace(String const& token, String cons // https://dom.spec.whatwg.org/#concept-domtokenlist-validation WebIDL::ExceptionOr DOMTokenList::supports(StringView token) { - static HashMap> supported_tokens_map = { - // NOTE: The supported values for rel were taken from HTMLLinkElement::Relationship - { HTML::AttributeNames::rel, { "alternate"sv, "stylesheet"sv, "preload"sv, "dns-prefetch"sv, "preconnect"sv, "icon"sv } }, - { HTML::AttributeNames::sandbox, { "allow-downloads"sv, "allow-forms"sv, "allow-modals"sv, "allow-orientation-lock"sv, "allow-pointer-lock"sv, "allow-popups"sv, "allow-popups-to-escape-sandbox"sv, "allow-presentation"sv, "allow-same-origin"sv, "allow-scripts"sv, "allow-top-navigation"sv, "allow-top-navigation-by-user-activation"sv, "allow-top-navigation-to-custom-protocols"sv } }, + // https://html.spec.whatwg.org/multipage/links.html#linkTypes + // https://html.spec.whatwg.org/multipage/iframe-embed-object.html#attr-iframe-sandbox + static HashMap> supported_tokens_map = { + { { HTML::TagNames::link, HTML::AttributeNames::rel }, { "modulepreload"sv, "preload"sv, "preconnect"sv, "dns-prefetch"sv, "stylesheet"sv, "icon"sv, "alternate"sv, "prefetch"sv, "prerender"sv, "next"sv, "manifest"sv, "apple-touch-icon"sv, "apple-touch-icon-precomposed"sv, "canonical"sv } }, + { { HTML::TagNames::a, HTML::AttributeNames::rel }, { "noreferrer"sv, "noopener"sv, "opener"sv } }, + { { HTML::TagNames::area, HTML::AttributeNames::rel }, { "noreferrer"sv, "noopener"sv, "opener"sv } }, + { { HTML::TagNames::form, HTML::AttributeNames::rel }, { "noreferrer"sv, "noopener"sv, "opener"sv } }, + { { HTML::TagNames::iframe, HTML::AttributeNames::sandbox }, { "allow-downloads"sv, "allow-forms"sv, "allow-modals"sv, "allow-orientation-lock"sv, "allow-pointer-lock"sv, "allow-popups"sv, "allow-popups-to-escape-sandbox"sv, "allow-presentation"sv, "allow-same-origin"sv, "allow-scripts"sv, "allow-top-navigation"sv, "allow-top-navigation-by-user-activation"sv, "allow-top-navigation-to-custom-protocols"sv } }, }; // 1. If the associated attribute’s local name does not define supported tokens, throw a TypeError. - auto supported_tokens = supported_tokens_map.get(m_associated_attribute); + auto supported_tokens = supported_tokens_map.get({ m_associated_element->local_name(), m_associated_attribute }); if (!supported_tokens.has_value()) return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Attribute {} does not define any supported tokens", m_associated_attribute)) }; - // AD-HOC: Other browsers return false for rel attributes on non-link elements for all attribute values we currently support. - if (m_associated_attribute == HTML::AttributeNames::rel && !is(*m_associated_element)) - return false; - // 2. Let lowercase token be a copy of token, in ASCII lowercase. auto lowercase_token = token.to_lowercase_string(); diff --git a/Libraries/LibWeb/DOM/DOMTokenList.h b/Libraries/LibWeb/DOM/DOMTokenList.h index 6e171ea2488..cac7177a711 100644 --- a/Libraries/LibWeb/DOM/DOMTokenList.h +++ b/Libraries/LibWeb/DOM/DOMTokenList.h @@ -62,3 +62,22 @@ private: }; } + +struct SupportedTokenKey { + FlyString element_name; + FlyString attribute_name; + + constexpr bool operator==(SupportedTokenKey const& other) const = default; +}; + +namespace AK { + +template<> +struct Traits : public DefaultTraits { + static unsigned hash(SupportedTokenKey const& key) + { + return pair_int_hash(key.element_name.hash(), key.attribute_name.hash()); + } +}; + +} diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/semantics/rellist-feature-detection.txt b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/rellist-feature-detection.txt new file mode 100644 index 00000000000..93320767505 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/semantics/rellist-feature-detection.txt @@ -0,0 +1,9 @@ +Harness status: OK + +Found 4 tests + +4 Pass +Pass Make sure that relList based feature detection is working for +Pass Make sure that relList based feature detection is working for +Pass Make sure that relList based feature detection is working for +Pass Make sure that relList based feature detection is working for
\ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/html/semantics/rellist-feature-detection.html b/Tests/LibWeb/Text/input/wpt-import/html/semantics/rellist-feature-detection.html new file mode 100644 index 00000000000..c95017fc599 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/semantics/rellist-feature-detection.html @@ -0,0 +1,84 @@ + +Test relList attribute + + +