فهرست منبع

LibWeb: Flesh out `DOMTokenList::supports()` implementation

This change makes `DOMTokenList::supports()` work as expected for
`relList` attributes.
Tim Ledbetter 1 سال پیش
والد
کامیت
d0555f3176

+ 33 - 0
Tests/LibWeb/Text/expected/DOMTokenList-supports.txt

@@ -0,0 +1,33 @@
+a.relList.supports("alternate"): false
+a.relList.supports("stylesheet"): false
+a.relList.supports("preload"): false
+a.relList.supports("dns-prefetch"): false
+a.relList.supports("preconnect"): false
+a.relList.supports("icon"): false
+a.relList.supports("STYLESHEET"): false
+a.relList.supports("never-supported"): false
+area.relList.supports("alternate"): false
+area.relList.supports("stylesheet"): false
+area.relList.supports("preload"): false
+area.relList.supports("dns-prefetch"): false
+area.relList.supports("preconnect"): false
+area.relList.supports("icon"): false
+area.relList.supports("STYLESHEET"): false
+area.relList.supports("never-supported"): false
+form.relList.supports("alternate"): false
+form.relList.supports("stylesheet"): false
+form.relList.supports("preload"): false
+form.relList.supports("dns-prefetch"): false
+form.relList.supports("preconnect"): false
+form.relList.supports("icon"): false
+form.relList.supports("STYLESHEET"): false
+form.relList.supports("never-supported"): false
+link.relList.supports("alternate"): true
+link.relList.supports("stylesheet"): true
+link.relList.supports("preload"): true
+link.relList.supports("dns-prefetch"): true
+link.relList.supports("preconnect"): true
+link.relList.supports("icon"): true
+link.relList.supports("STYLESHEET"): true
+link.relList.supports("never-supported"): false
+html.classList.supports("foo") throws: TypeError

+ 22 - 0
Tests/LibWeb/Text/input/DOMTokenList-supports.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<script src="include.js"></script>
+<script>    
+    test(() => {
+        for (const tagName of ["a", "area", "form", "link"]) {
+            const element = document.createElement(tagName);
+            const relList = element.relList;
+            for (const propertyValue of ["alternate", "stylesheet", "preload", "dns-prefetch", "preconnect", "icon", "STYLESHEET", "never-supported"]) {
+                println(`${tagName}.relList.supports("${propertyValue}"): ${relList.supports(propertyValue)}`);
+            }
+        }
+
+        const documentElement = document.documentElement
+        const classList = documentElement.classList;
+        try {
+            classList.supports("foo");
+            println("FAIL");
+        } catch (e) {
+            println(`${documentElement.tagName.toLowerCase()}.classList.supports("foo") throws: ${e.name}`);
+        }
+    });
+</script>

+ 19 - 3
Userland/Libraries/LibWeb/DOM/DOMTokenList.cpp

@@ -10,6 +10,7 @@
 #include <LibWeb/DOM/DOMTokenList.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Element.h>
+#include <LibWeb/HTML/HTMLLinkElement.h>
 #include <LibWeb/Infra/CharacterTypes.h>
 #include <LibWeb/WebIDL/DOMException.h>
 
@@ -211,16 +212,31 @@ WebIDL::ExceptionOr<bool> DOMTokenList::replace(String const& token, String cons
 
 // https://dom.spec.whatwg.org/#dom-domtokenlist-supports
 // https://dom.spec.whatwg.org/#concept-domtokenlist-validation
-WebIDL::ExceptionOr<bool> DOMTokenList::supports([[maybe_unused]] StringView token)
+WebIDL::ExceptionOr<bool> DOMTokenList::supports(StringView token)
 {
-    // FIXME: Implement this fully when any use case defines supported tokens.
+    static HashMap<FlyString, Vector<StringView>> 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 } },
+    };
 
     // 1. If the associated attribute’s local name does not define supported tokens, throw a TypeError.
-    return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, String::formatted("Attribute {} does not define any supported tokens", m_associated_attribute).release_value_but_fixme_should_propagate_errors() };
+    auto supported_tokens = supported_tokens_map.get(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<HTML::HTMLLinkElement>(*m_associated_element))
+        return false;
 
     // 2. Let lowercase token be a copy of token, in ASCII lowercase.
+    auto lowercase_token = token.to_lowercase_string();
+
     // 3. If lowercase token is present in supported tokens, return true.
+    if (supported_tokens->contains_slow(lowercase_token))
+        return true;
+
     // 4. Return false.
+    return false;
 }
 
 // https://dom.spec.whatwg.org/#dom-domtokenlist-value