From 690d9c8752544a0cd97e6d3a95e9f0f777c39d9f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 27 Oct 2024 12:13:05 +0100 Subject: [PATCH] LibWeb: Be more thorough when marking selectors as "contains :has()" We were missing this flag on a lot of selectors, which led to insufficient invalidation in some cases. --- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 6b21c634b4a..9d3b99eb020 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -2421,6 +2421,23 @@ static Optional is_roundabout_selector_bucketabl return {}; } +static bool contains_has_pseudo_class(Selector const& selector) +{ + for (auto const& compound_selector : selector.compound_selectors()) { + for (auto const& simple_selector : compound_selector.simple_selectors) { + if (simple_selector.type != CSS::Selector::SimpleSelector::Type::PseudoClass) + continue; + if (simple_selector.pseudo_class().type == CSS::PseudoClass::Has) + return true; + for (auto const& argument_selector : simple_selector.pseudo_class().argument_selector_list) { + if (contains_has_pseudo_class(argument_selector)) + return true; + } + } + } + return false; +} + NonnullOwnPtr StyleComputer::make_rule_cache_for_cascade_origin(CascadeOrigin cascade_origin) { auto rule_cache = make(); @@ -2464,9 +2481,10 @@ NonnullOwnPtr StyleComputer::make_rule_cache_for_casca bool contains_root_pseudo_class = false; Optional pseudo_element; + if (!rule_cache->has_has_selectors) + rule_cache->has_has_selectors = contains_has_pseudo_class(selector); + for (auto const& simple_selector : selector.compound_selectors().last().simple_selectors) { - if (!rule_cache->has_has_selectors && simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass && simple_selector.pseudo_class().type == CSS::PseudoClass::Has) - rule_cache->has_has_selectors = true; if (!matching_rule.contains_pseudo_element) { if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoElement) { matching_rule.contains_pseudo_element = true;