mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 17:55:07 +02:00
A DOM mutation under a document that uses any :has() rule currently walks every ancestor up to the root, invoking invalidate_style_if_ affected_by_has() on each. Most of those ancestors have nothing to do with :has(), so the work scales linearly with DOM depth. Introduce an in_has_scope flag on Element, set while evaluating :has() arguments for invalidation metadata. StyleScope's upward invalidation walk now terminates at the first element that is neither in :has() scope nor a :has() anchor, so it only traverses the region where some :has() rule might actually care about the change. Keep the existing fast :has() matching paths for normal selector matching, but bypass them while collecting per-element metadata so the scope markers still get populated. Node insertion also schedules the parent for the :has() walk so newly inserted nodes still reach the real anchor. The css-has-invalidation suite adds focused coverage for these shapes and updates the expected counters to reflect the shorter walks.
31 lines
1.1 KiB
HTML
31 lines
1.1 KiB
HTML
<!DOCTYPE html>
|
|
<script src="../include.js"></script>
|
|
<script src="_helpers.js"></script>
|
|
<style>
|
|
.anchor:has(> .match) { color: red; }
|
|
</style>
|
|
<div class="anchor" id="anchor">
|
|
<div id="child">
|
|
<span id="grandchild">grandchild</span>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
test(() => {
|
|
settleAndReset();
|
|
|
|
// Adding .match to a direct child should invalidate.
|
|
document.getElementById("child").classList.add("match");
|
|
getComputedStyle(document.getElementById("anchor")).color;
|
|
printCounters("add .match to direct child");
|
|
|
|
internals.resetStyleInvalidationCounters();
|
|
|
|
// Adding .match to a grandchild is NOT enough for :has(> .match);
|
|
// the anchor should stay unstyled. The walker may still run if the
|
|
// grandchild is in_has_scope (walked during initial match attempt).
|
|
document.getElementById("grandchild").classList.add("match");
|
|
getComputedStyle(document.getElementById("anchor")).color;
|
|
printCounters("add .match to grandchild (should not style anchor)");
|
|
});
|
|
</script>
|