mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-04 15:19:42 +00:00
LibWeb: Narrow :has()
style invalidation to ancestor nodes
The current implementation of `:has()` style invalidation is divided into two cases: - When used in subject position (e.g., `.a:has(.b)`). - When in a non-subject position (e.g., `.a > .b:has(.c)`). This change focuses on improving the first case. For non-subject usage, we still perform a full tree traversal and invalidate all elements affected by the `:has()` pseudo-class invalidation set. We already optimize subject `:has()` invalidations by limiting invalidated elements to ones that were tested against `has()` selectors during selector matching. However, selectors like `div:has(.a)` currently cause every div element in the document to be invalidated. By modifying the invalidation traversal to consider only ancestor nodes (and, optionally, their siblings), we can drastically reduce the number of invalidated elements for broad selectors like the example above. On Discord, when scrolling through message history, this change allows to reduce number of invalidated elements from ~1k to ~5.
This commit is contained in:
parent
7441aa34e4
commit
e677ab1699
Notes:
github-actions[bot]
2025-02-10 00:15:09 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: e677ab1699
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3521
7 changed files with 104 additions and 22 deletions
|
@ -121,6 +121,9 @@ static inline bool matches_relative_selector(CSS::Selector const& selector, size
|
|||
return has;
|
||||
}
|
||||
case CSS::Selector::Combinator::NextSibling: {
|
||||
if (context.collect_per_element_selector_involvement_metadata) {
|
||||
const_cast<DOM::Element&>(*anchor).set_affected_by_has_pseudo_class_with_relative_selector_that_has_sibling_combinator(true);
|
||||
}
|
||||
auto* sibling = element.next_element_sibling();
|
||||
if (!sibling)
|
||||
return false;
|
||||
|
@ -129,6 +132,9 @@ static inline bool matches_relative_selector(CSS::Selector const& selector, size
|
|||
return matches_relative_selector(selector, compound_index + 1, *sibling, shadow_host, context, anchor);
|
||||
}
|
||||
case CSS::Selector::Combinator::SubsequentSibling: {
|
||||
if (context.collect_per_element_selector_involvement_metadata) {
|
||||
const_cast<DOM::Element&>(*anchor).set_affected_by_has_pseudo_class_with_relative_selector_that_has_sibling_combinator(true);
|
||||
}
|
||||
for (auto const* sibling = element.next_element_sibling(); sibling; sibling = sibling->next_element_sibling()) {
|
||||
if (!matches(selector, compound_index, *sibling, shadow_host, context, {}, SelectorKind::Relative, anchor))
|
||||
continue;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue