LibWeb: Flesh out DOMTokenList::supports() implementation

This change makes `DOMTokenList::supports()` work as expected for
`relList` attributes.
This commit is contained in:
Tim Ledbetter 2024-05-16 18:07:46 +01:00 committed by Andreas Kling
parent 1e60b4ec40
commit d0555f3176
Notes: sideshowbarker 2024-07-18 01:43:16 +09:00
3 changed files with 74 additions and 3 deletions

View File

@ -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

View File

@ -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>

View File

@ -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 attributes 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