LibWeb: Cache whether there are any :has() selectors present

As useful as they may be to web developers, :has() selectors complicate
the style invalidation process quite a lot.

Let's have StyleComputer keep track of whether they are present at all
in the current set of active style sheets. This will allow us to
implement fast-path optimizations when there are no :has() selectors.
This commit is contained in:
Andreas Kling 2024-09-19 13:27:37 +02:00 committed by Andreas Kling
commit 8beb7c7700
Notes: github-actions[bot] 2024-09-22 18:08:47 +00:00
2 changed files with 9 additions and 0 deletions

View file

@ -2479,6 +2479,8 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
Optional<CSS::Selector::PseudoElement::Type> pseudo_element; Optional<CSS::Selector::PseudoElement::Type> pseudo_element;
for (auto const& simple_selector : selector.compound_selectors().last().simple_selectors) { 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 (!matching_rule.contains_pseudo_element) {
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoElement) { if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoElement) {
matching_rule.contains_pseudo_element = true; matching_rule.contains_pseudo_element = true;
@ -2726,6 +2728,8 @@ void StyleComputer::build_rule_cache()
m_author_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::Author); m_author_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::Author);
m_user_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::User); m_user_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::User);
m_user_agent_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::UserAgent); m_user_agent_rule_cache = make_rule_cache_for_cascade_origin(CascadeOrigin::UserAgent);
m_has_has_selectors = m_author_rule_cache->has_has_selectors || m_user_rule_cache->has_has_selectors || m_user_agent_rule_cache->has_has_selectors;
} }
void StyleComputer::invalidate_rule_cache() void StyleComputer::invalidate_rule_cache()

View file

@ -156,6 +156,8 @@ public:
}; };
void collect_animation_into(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, JS::NonnullGCPtr<Animations::KeyframeEffect> animation, StyleProperties& style_properties, AnimationRefresh = AnimationRefresh::No) const; void collect_animation_into(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, JS::NonnullGCPtr<Animations::KeyframeEffect> animation, StyleProperties& style_properties, AnimationRefresh = AnimationRefresh::No) const;
[[nodiscard]] bool has_has_selectors() const { return m_has_has_selectors; }
private: private:
enum class ComputeStyleMode { enum class ComputeStyleMode {
Normal, Normal,
@ -221,12 +223,15 @@ private:
Vector<MatchingRule> other_rules; Vector<MatchingRule> other_rules;
HashMap<FlyString, NonnullRefPtr<Animations::KeyframeEffect::KeyFrameSet>> rules_by_animation_keyframes; HashMap<FlyString, NonnullRefPtr<Animations::KeyframeEffect::KeyFrameSet>> rules_by_animation_keyframes;
bool has_has_selectors { false };
}; };
NonnullOwnPtr<RuleCache> make_rule_cache_for_cascade_origin(CascadeOrigin); NonnullOwnPtr<RuleCache> make_rule_cache_for_cascade_origin(CascadeOrigin);
RuleCache const& rule_cache_for_cascade_origin(CascadeOrigin) const; RuleCache const& rule_cache_for_cascade_origin(CascadeOrigin) const;
bool m_has_has_selectors { false };
OwnPtr<RuleCache> m_author_rule_cache; OwnPtr<RuleCache> m_author_rule_cache;
OwnPtr<RuleCache> m_user_rule_cache; OwnPtr<RuleCache> m_user_rule_cache;
OwnPtr<RuleCache> m_user_agent_rule_cache; OwnPtr<RuleCache> m_user_agent_rule_cache;