mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 13:49:16 +00:00
LibWeb: Use ancestor filters for hover style invalidation
By using ancestor filters some selectors could be early rejected skipping selector engine invocation. According to my measurements it's 30-80% hover selectors depending on the website.
This commit is contained in:
parent
b153420feb
commit
db47fa3db1
Notes:
github-actions[bot]
2025-01-28 17:56:41 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: db47fa3db1
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3379
2 changed files with 30 additions and 20 deletions
|
@ -187,6 +187,8 @@ public:
|
||||||
void absolutize_values(ComputedProperties&) const;
|
void absolutize_values(ComputedProperties&) const;
|
||||||
void compute_font(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
void compute_font(ComputedProperties&, DOM::Element const*, Optional<CSS::Selector::PseudoElement::Type>) const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool should_reject_with_ancestor_filter(Selector const&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class ComputeStyleMode {
|
enum class ComputeStyleMode {
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -195,8 +197,6 @@ private:
|
||||||
|
|
||||||
struct MatchingFontCandidate;
|
struct MatchingFontCandidate;
|
||||||
|
|
||||||
[[nodiscard]] bool should_reject_with_ancestor_filter(Selector const&) const;
|
|
||||||
|
|
||||||
[[nodiscard]] GC::Ptr<ComputedProperties> compute_style_impl(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, ComputeStyleMode) const;
|
[[nodiscard]] GC::Ptr<ComputedProperties> compute_style_impl(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, ComputeStyleMode) const;
|
||||||
[[nodiscard]] GC::Ref<CascadedProperties> compute_cascaded_values(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, bool& did_match_any_pseudo_element_rules, bool& did_match_any_hover_rules, ComputeStyleMode) const;
|
[[nodiscard]] GC::Ref<CascadedProperties> compute_cascaded_values(DOM::Element&, Optional<CSS::Selector::PseudoElement::Type>, bool& did_match_any_pseudo_element_rules, bool& did_match_any_hover_rules, ComputeStyleMode) const;
|
||||||
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
static RefPtr<Gfx::FontCascadeList const> find_matching_font_weight_ascending(Vector<MatchingFontCandidate> const& candidates, int target_weight, float font_size_in_pt, bool inclusive);
|
||||||
|
|
|
@ -1667,6 +1667,7 @@ void Document::invalidate_style_for_elements_affected_by_hover_change(Node& old_
|
||||||
auto& root = old_new_hovered_common_ancestor.root();
|
auto& root = old_new_hovered_common_ancestor.root();
|
||||||
auto shadow_root = is<ShadowRoot>(root) ? static_cast<ShadowRoot const*>(&root) : nullptr;
|
auto shadow_root = is<ShadowRoot>(root) ? static_cast<ShadowRoot const*>(&root) : nullptr;
|
||||||
|
|
||||||
|
auto& style_computer = this->style_computer();
|
||||||
auto compute_hover_selectors_match_state = [&](Element const& element) {
|
auto compute_hover_selectors_match_state = [&](Element const& element) {
|
||||||
auto state = MUST(AK::Bitmap::create(hover_rules.size(), 0));
|
auto state = MUST(AK::Bitmap::create(hover_rules.size(), 0));
|
||||||
for (size_t rule_index = 0; rule_index < hover_rules.size(); ++rule_index) {
|
for (size_t rule_index = 0; rule_index < hover_rules.size(); ++rule_index) {
|
||||||
|
@ -1681,6 +1682,8 @@ void Document::invalidate_style_for_elements_affected_by_hover_change(Node& old_
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto const& selector = rule.selector;
|
auto const& selector = rule.selector;
|
||||||
|
if (style_computer.should_reject_with_ancestor_filter(selector))
|
||||||
|
continue;
|
||||||
|
|
||||||
SelectorEngine::MatchContext context;
|
SelectorEngine::MatchContext context;
|
||||||
bool selector_matched = false;
|
bool selector_matched = false;
|
||||||
|
@ -1703,27 +1706,34 @@ void Document::invalidate_style_for_elements_affected_by_hover_change(Node& old_
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
root.for_each_in_inclusive_subtree([&](Node& node) {
|
Function<void(Node&)> invalidate_hovered_elements_recursively = [&](Node& node) -> void {
|
||||||
if (!node.is_element())
|
if (node.is_element()) {
|
||||||
return TraversalDecision::Continue;
|
auto& element = static_cast<Element&>(node);
|
||||||
auto& element = static_cast<Element&>(node);
|
style_computer.push_ancestor(element);
|
||||||
if (!element.affected_by_hover())
|
if (element.affected_by_hover()) {
|
||||||
return TraversalDecision::Continue;
|
auto selectors_match_state_before = compute_hover_selectors_match_state(element);
|
||||||
|
TemporaryChange change { m_hovered_node, hovered_node };
|
||||||
|
auto selectors_match_state_after = compute_hover_selectors_match_state(element);
|
||||||
|
if (selectors_match_state_before.view() != selectors_match_state_after.view()) {
|
||||||
|
element.set_needs_style_update(true);
|
||||||
|
element.for_each_in_subtree_of_type<Element>([](auto& element) {
|
||||||
|
element.set_needs_inherited_style_update(true);
|
||||||
|
return TraversalDecision::Continue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto selectors_match_state_before = compute_hover_selectors_match_state(element);
|
node.for_each_child([&](auto& child) {
|
||||||
TemporaryChange change { m_hovered_node, hovered_node };
|
invalidate_hovered_elements_recursively(child);
|
||||||
auto selectors_match_state_after = compute_hover_selectors_match_state(element);
|
return IterationDecision::Continue;
|
||||||
if (selectors_match_state_before.view() == selectors_match_state_after.view())
|
|
||||||
return TraversalDecision::Continue;
|
|
||||||
|
|
||||||
element.set_needs_style_update(true);
|
|
||||||
element.for_each_in_subtree_of_type<Element>([](auto& element) {
|
|
||||||
element.set_needs_inherited_style_update(true);
|
|
||||||
return TraversalDecision::Continue;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return TraversalDecision::Continue;
|
if (node.is_element())
|
||||||
});
|
style_computer.pop_ancestor(static_cast<Element&>(node));
|
||||||
|
};
|
||||||
|
|
||||||
|
invalidate_hovered_elements_recursively(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::set_hovered_node(Node* node)
|
void Document::set_hovered_node(Node* node)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue