LibWeb: Optimize pseudo elements presence check in hover style update

Instead of using `has_pseudo_elements()` that iterates over all pseudo
elements, only check if `::before` or `::after` are present.

Before this change, `has_pseudo_elements()` was 10% of profiles on
Discord while now it's 1-2%.
This commit is contained in:
Aliaksandr Kalenik 2025-02-19 17:31:54 +01:00 committed by Alexander Kalenik
commit e1119023e9
Notes: github-actions[bot] 2025-02-19 18:57:53 +00:00
2 changed files with 13 additions and 1 deletions

View file

@ -1753,9 +1753,11 @@ void Document::invalidate_style_for_elements_affected_by_hover_change(Node& old_
bool selector_matched = false; bool selector_matched = false;
if (SelectorEngine::matches(selector, element, {}, context, {})) if (SelectorEngine::matches(selector, element, {}, context, {}))
selector_matched = true; selector_matched = true;
if (element.has_pseudo_elements()) { if (element.has_pseudo_element(CSS::Selector::PseudoElement::Type::Before)) {
if (SelectorEngine::matches(selector, element, {}, context, CSS::Selector::PseudoElement::Type::Before)) if (SelectorEngine::matches(selector, element, {}, context, CSS::Selector::PseudoElement::Type::Before))
selector_matched = true; selector_matched = true;
}
if (element.has_pseudo_element(CSS::Selector::PseudoElement::Type::After)) {
if (SelectorEngine::matches(selector, element, {}, context, CSS::Selector::PseudoElement::Type::After)) if (SelectorEngine::matches(selector, element, {}, context, CSS::Selector::PseudoElement::Type::After))
selector_matched = true; selector_matched = true;
} }

View file

@ -273,6 +273,7 @@ public:
void set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement::Type, GC::Ptr<Layout::NodeWithStyle>); void set_pseudo_element_node(Badge<Layout::TreeBuilder>, CSS::Selector::PseudoElement::Type, GC::Ptr<Layout::NodeWithStyle>);
GC::Ptr<Layout::NodeWithStyle> get_pseudo_element_node(CSS::Selector::PseudoElement::Type) const; GC::Ptr<Layout::NodeWithStyle> get_pseudo_element_node(CSS::Selector::PseudoElement::Type) const;
bool has_pseudo_element(CSS::Selector::PseudoElement::Type) const;
bool has_pseudo_elements() const; bool has_pseudo_elements() const;
void clear_pseudo_element_nodes(Badge<Layout::TreeBuilder>); void clear_pseudo_element_nodes(Badge<Layout::TreeBuilder>);
void serialize_pseudo_elements_as_json(JsonArraySerializer<StringBuilder>& children_array) const; void serialize_pseudo_elements_as_json(JsonArraySerializer<StringBuilder>& children_array) const;
@ -589,6 +590,15 @@ inline bool Element::has_class(FlyString const& class_name, CaseSensitivity case
}); });
} }
inline bool Element::has_pseudo_element(CSS::Selector::PseudoElement::Type type) const
{
if (!m_pseudo_element_data)
return false;
if (!CSS::Selector::PseudoElement::is_known_pseudo_element_type(type))
return false;
return m_pseudo_element_data->at(to_underlying(type)).layout_node;
}
WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Realm&, Optional<FlyString> namespace_, FlyString const& qualified_name); WebIDL::ExceptionOr<QualifiedName> validate_and_extract(JS::Realm&, Optional<FlyString> namespace_, FlyString const& qualified_name);
} }