LibWeb: Implement :required/:optional pseudo-classes

This commit is contained in:
Gingeh 2025-04-30 10:23:46 +10:00 committed by Sam Atkins
commit 7acc0f4a42
Notes: github-actions[bot] 2025-05-24 09:32:37 +00:00
13 changed files with 300 additions and 2 deletions

View file

@ -116,6 +116,9 @@
"optimal-value": {
"argument": ""
},
"optional": {
"argument": ""
},
"popover-open": {
"argument": ""
},
@ -134,6 +137,9 @@
"read-write": {
"argument": ""
},
"required": {
"argument": ""
},
"root": {
"argument": ""
},

View file

@ -988,6 +988,55 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
return false;
}
case CSS::PseudoClass::Required: {
// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-required
// The :required pseudo-class must match any element falling into one of the following categories:
// - input elements that are required
if (auto const* input_element = as_if<Web::HTML::HTMLInputElement>(element)) {
if (input_element->required_applies() && input_element->has_attribute(HTML::AttributeNames::required))
return true;
}
// - select elements that have a required attribute
else if (auto const* select_element = as_if<Web::HTML::HTMLSelectElement>(element)) {
if (select_element->has_attribute(HTML::AttributeNames::required))
return true;
}
// - textarea elements that have a required attribute
else if (auto const* textarea_element = as_if<Web::HTML::HTMLTextAreaElement>(element)) {
if (textarea_element->has_attribute(HTML::AttributeNames::required))
return true;
}
return false;
}
case CSS::PseudoClass::Optional: {
// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-optional
// The :optional pseudo-class must match any element falling into one of the following categories:
// - input elements to which the required attribute applies that are not required
if (auto const* input_element = as_if<Web::HTML::HTMLInputElement>(element)) {
if (input_element->required_applies() && !input_element->has_attribute(HTML::AttributeNames::required))
return true;
// AD-HOC: Chromium and Webkit also match for hidden inputs (and WPT expects this)
// See: https://github.com/whatwg/html/issues/11273
if (input_element->type_state() == HTML::HTMLInputElement::TypeAttributeState::Hidden)
return true;
}
// - select elements that do not have a required attribute
else if (auto const* select_element = as_if<Web::HTML::HTMLSelectElement>(element)) {
if (!select_element->has_attribute(HTML::AttributeNames::required))
return true;
}
// - textarea elements that do not have a required attribute
else if (auto const* textarea_element = as_if<Web::HTML::HTMLTextAreaElement>(element)) {
if (!textarea_element->has_attribute(HTML::AttributeNames::required))
return true;
}
return false;
}
}
return false;

View file

@ -141,6 +141,8 @@ static void build_invalidation_sets_for_simple_selector(Selector::SimpleSelector
case PseudoClass::Link:
case PseudoClass::AnyLink:
case PseudoClass::LocalLink:
case PseudoClass::Required:
case PseudoClass::Optional:
invalidation_set.set_needs_invalidate_pseudo_class(pseudo_class.type);
break;
default: