LibWeb/CSS: Reject invalid :has() contents after absolutizing nesting

After we absolutize the contents of :has(), we check that those child
selectors don't contain anything that :has() rejects.

This is a separate path than the checks inside the parser, which is
unfortunate.

Fixes a WPT ref test. :^)
This commit is contained in:
Sam Atkins 2024-11-14 14:07:38 +00:00 committed by Andreas Kling
parent da31c10ce1
commit 3a71b8cda3
Notes: github-actions[bot] 2024-11-14 19:08:17 +00:00
2 changed files with 38 additions and 1 deletions

View file

@ -624,6 +624,33 @@ Optional<Selector::CompoundSelector> Selector::CompoundSelector::absolutized(Sel
};
}
static bool contains_invalid_contents_for_has(Selector const& selector)
{
// :has() has special validity rules:
// - It can't appear inside itself
// - It bans most pseudo-elements
// https://drafts.csswg.org/selectors/#relational
for (auto const& compound_selector : selector.compound_selectors()) {
for (auto const& simple_selector : compound_selector.simple_selectors) {
if (simple_selector.type == Selector::SimpleSelector::Type::PseudoElement) {
if (!is_has_allowed_pseudo_element(simple_selector.pseudo_element().type()))
return true;
}
if (simple_selector.type == Selector::SimpleSelector::Type::PseudoClass) {
if (simple_selector.pseudo_class().type == PseudoClass::Has)
return true;
for (auto& child_selector : simple_selector.pseudo_class().argument_selector_list) {
if (contains_invalid_contents_for_has(*child_selector))
return true;
}
}
}
}
return false;
}
Optional<Selector::SimpleSelector> Selector::SimpleSelector::absolutized(Selector::SimpleSelector const& selector_for_nesting) const
{
switch (type) {
@ -647,6 +674,17 @@ Optional<Selector::SimpleSelector> Selector::SimpleSelector::absolutized(Selecto
}
pseudo_class.argument_selector_list = move(new_selector_list);
}
// :has() has special validity rules
if (pseudo_class.type == PseudoClass::Has) {
for (auto const& selector : pseudo_class.argument_selector_list) {
if (contains_invalid_contents_for_has(selector)) {
dbgln_if(CSS_PARSER_DEBUG, "After absolutizing, :has() would contain invalid contents; rejecting");
return {};
}
}
}
return SimpleSelector {
.type = Type::PseudoClass,
.value = move(pseudo_class),

View file

@ -59,7 +59,6 @@ Text/input/wpt-import/html/infrastructure/safe-passing-of-structured-data/resour
Text/input/wpt-import/css/css-flexbox/flex-item-compressible-001.html
; WPT ref-tests that currently fail
Ref/input/wpt-import/css/css-nesting/has-nesting.html
Ref/input/wpt-import/css/css-nesting/host-nesting-003.html
Ref/input/wpt-import/css/css-nesting/host-nesting-004.html
Ref/input/wpt-import/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht