mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 08:11:13 +00:00
LibWeb: Filter :hover selectors early for elements that aren't hovered
Some websites (like vercel.com...) have a *lot* of :hover selectors that we can simply skip for any element that isn't currently hovered.
This commit is contained in:
parent
5bb0f43b90
commit
ef4f5ac8fb
Notes:
github-actions[bot]
2024-09-09 18:13:06 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/ef4f5ac8fb7 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1345
|
@ -140,7 +140,7 @@ static inline bool matches_link_pseudo_class(DOM::Element const& element)
|
|||
return element.has_attribute(HTML::AttributeNames::href);
|
||||
}
|
||||
|
||||
static inline bool matches_hover_pseudo_class(DOM::Element const& element)
|
||||
bool matches_hover_pseudo_class(DOM::Element const& element)
|
||||
{
|
||||
auto* hovered_node = element.document().hovered_node();
|
||||
if (!hovered_node)
|
||||
|
|
|
@ -21,4 +21,6 @@ bool matches(CSS::Selector const&, Optional<CSS::CSSStyleSheet const&> style_she
|
|||
[[nodiscard]] bool fast_matches(CSS::Selector const&, Optional<CSS::CSSStyleSheet const&> style_sheet_for_rule, DOM::Element const&, JS::GCPtr<DOM::Element const> shadow_host);
|
||||
[[nodiscard]] bool can_use_fast_matches(CSS::Selector const&);
|
||||
|
||||
[[nodiscard]] bool matches_hover_pseudo_class(DOM::Element const&);
|
||||
|
||||
}
|
||||
|
|
|
@ -356,16 +356,22 @@ Vector<MatchingRule> StyleComputer::collect_matching_rules(DOM::Element const& e
|
|||
|
||||
auto const& rule_cache = rule_cache_for_cascade_origin(cascade_origin);
|
||||
|
||||
bool is_hovered = SelectorEngine::matches_hover_pseudo_class(element);
|
||||
|
||||
Vector<MatchingRule, 512> rules_to_run;
|
||||
auto add_rules_to_run = [&](Vector<MatchingRule> const& rules) {
|
||||
rules_to_run.grow_capacity(rules_to_run.size() + rules.size());
|
||||
if (pseudo_element.has_value()) {
|
||||
for (auto const& rule : rules) {
|
||||
if (rule.must_be_hovered && !is_hovered)
|
||||
continue;
|
||||
if (rule.contains_pseudo_element && filter_namespace_rule(element, rule) && filter_layer(qualified_layer_name, rule))
|
||||
rules_to_run.unchecked_append(rule);
|
||||
}
|
||||
} else {
|
||||
for (auto const& rule : rules) {
|
||||
if (rule.must_be_hovered && !is_hovered)
|
||||
continue;
|
||||
if (!rule.contains_pseudo_element && filter_namespace_rule(element, rule) && filter_layer(qualified_layer_name, rule))
|
||||
rules_to_run.unchecked_append(rule);
|
||||
}
|
||||
|
@ -2692,6 +2698,7 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
|
|||
size_t num_pseudo_element_rules = 0;
|
||||
size_t num_root_rules = 0;
|
||||
size_t num_attribute_rules = 0;
|
||||
size_t num_hover_rules = 0;
|
||||
|
||||
Vector<MatchingRule> matching_rules;
|
||||
size_t style_sheet_index = 0;
|
||||
|
@ -2711,6 +2718,7 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
|
|||
cascade_origin,
|
||||
false,
|
||||
SelectorEngine::can_use_fast_matches(selector),
|
||||
false,
|
||||
};
|
||||
|
||||
bool contains_root_pseudo_class = false;
|
||||
|
@ -2729,6 +2737,27 @@ NonnullOwnPtr<StyleComputer::RuleCache> StyleComputer::make_rule_cache_for_casca
|
|||
++num_root_rules;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matching_rule.must_be_hovered) {
|
||||
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass && simple_selector.pseudo_class().type == CSS::PseudoClass::Hover) {
|
||||
matching_rule.must_be_hovered = true;
|
||||
++num_hover_rules;
|
||||
}
|
||||
if (simple_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass
|
||||
&& (simple_selector.pseudo_class().type == CSS::PseudoClass::Is
|
||||
|| simple_selector.pseudo_class().type == CSS::PseudoClass::Where)) {
|
||||
auto const& argument_selectors = simple_selector.pseudo_class().argument_selector_list;
|
||||
|
||||
if (argument_selectors.size() == 1) {
|
||||
auto const& simple_argument_selector = argument_selectors.first()->compound_selectors().last().simple_selectors.last();
|
||||
if (simple_argument_selector.type == CSS::Selector::SimpleSelector::Type::PseudoClass
|
||||
&& simple_argument_selector.pseudo_class().type == CSS::PseudoClass::Hover) {
|
||||
matching_rule.must_be_hovered = true;
|
||||
++num_hover_rules;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: We traverse the simple selectors in reverse order to make sure that class/ID buckets are preferred over tag buckets
|
||||
|
|
|
@ -92,6 +92,7 @@ struct MatchingRule {
|
|||
CascadeOrigin cascade_origin;
|
||||
bool contains_pseudo_element { false };
|
||||
bool can_use_fast_matches { false };
|
||||
bool must_be_hovered { false };
|
||||
bool skip { false };
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue