mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-03 04:52:06 +02:00
LibWeb: Scope broad shadow-root stylesheet invalidation
When invalidate_owners() runs on a stylesheet scoped to a shadow root, we previously dirtied the host and its light-DOM side too broadly. That forced restyles on nodes the shadow-scoped stylesheet cannot match. Inspect the sheet's effective selectors and dependent features up front. Only dirty assigned nodes, the host, the host root, or host-side animation consumers when the sheet can actually reach them, while keeping purely shadow-local mutations inside the shadow tree.
This commit is contained in:
committed by
Andreas Kling
parent
4e92765211
commit
a0dc0c61f4
Notes:
github-actions[bot]
2026-04-23 14:49:41 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/a0dc0c61f4e Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/9049
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<div id="host"></div>
|
||||
<script>
|
||||
function settleAndReset(triggerElement) {
|
||||
getComputedStyle(triggerElement).color;
|
||||
getComputedStyle(triggerElement).color;
|
||||
internals.resetStyleInvalidationCounters();
|
||||
}
|
||||
|
||||
function verifyInvalidationsStayBounded(label, maxInvalidations) {
|
||||
const invalidations = internals.getStyleInvalidationCounters().styleInvalidations;
|
||||
if (invalidations <= maxInvalidations)
|
||||
println(`PASS: ${label} (${invalidations} invalidations)`);
|
||||
else
|
||||
println(`FAIL: ${label} (${invalidations} invalidations)`);
|
||||
}
|
||||
|
||||
test(() => {
|
||||
const host = document.getElementById("host");
|
||||
for (let i = 0; i < 25; ++i) {
|
||||
const bystander = document.createElement("span");
|
||||
bystander.className = "shadow-target";
|
||||
bystander.textContent = `bystander ${i}`;
|
||||
document.body.appendChild(bystander);
|
||||
}
|
||||
|
||||
const shadowRoot = host.attachShadow({ mode: "open" });
|
||||
shadowRoot.innerHTML = `<div id="target" class="shadow-target">target</div>`;
|
||||
const target = shadowRoot.getElementById("target");
|
||||
|
||||
const baseStyle = document.createElement("style");
|
||||
baseStyle.textContent = `
|
||||
@layer alpha {
|
||||
.shadow-target { color: rgb(255, 0, 0); }
|
||||
}
|
||||
|
||||
@layer beta {
|
||||
.shadow-target { color: rgb(0, 128, 0); }
|
||||
}
|
||||
`;
|
||||
shadowRoot.appendChild(baseStyle);
|
||||
|
||||
const layerOrderStyle = document.createElement("style");
|
||||
layerOrderStyle.textContent = "@layer beta, alpha;";
|
||||
|
||||
settleAndReset(target);
|
||||
shadowRoot.appendChild(layerOrderStyle);
|
||||
getComputedStyle(target).color;
|
||||
verifyInvalidationsStayBounded("shadow-local layer-order add stays inside the shadow root", 4);
|
||||
|
||||
settleAndReset(target);
|
||||
layerOrderStyle.remove();
|
||||
getComputedStyle(target).color;
|
||||
verifyInvalidationsStayBounded("shadow-local layer-order remove stays inside the shadow root", 4);
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user