Files
ladybird/Tests/LibWeb/Text/input/css/shadow-root-replacesync-slotted-invalidation.html
Andreas Kling a0dc0c61f4 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.
2026-04-23 16:45:22 +02:00

37 lines
1.6 KiB
HTML

<!DOCTYPE html>
<script src="../include.js"></script>
<div id="host"><span id="slotted" class="item">slotted</span></div>
<script>
asyncTest(async done => {
const host = document.getElementById("host");
const slotted = document.getElementById("slotted");
const shadowRoot = host.attachShadow({ mode: "open" });
const slottedSheet = new CSSStyleSheet();
const keyframesSheet = new CSSStyleSheet();
shadowRoot.innerHTML = "<slot></slot>";
shadowRoot.adoptedStyleSheets = [slottedSheet, keyframesSheet];
slottedSheet.replaceSync(`
::slotted(.item) {
color: rgb(0, 0, 255);
animation-name: fade;
animation-duration: 1s;
animation-fill-mode: both;
}
`);
keyframesSheet.replaceSync("@keyframes fade { from { opacity: 0.25; } to { opacity: 0.25; } }");
println(`slotted before replaceSync: ${getComputedStyle(slotted).color}`);
await animationFrame();
println(`opacity before keyframes replaceSync: ${getComputedStyle(slotted).opacity}`);
slottedSheet.replaceSync("::slotted(.item) { color: rgb(255, 0, 0); animation-name: fade; animation-duration: 1s; animation-fill-mode: both; }");
println(`slotted after replaceSync: ${getComputedStyle(slotted).color}`);
keyframesSheet.replaceSync("@keyframes fade { from { opacity: 0.5; } to { opacity: 0.5; } }");
await animationFrame();
println(`opacity after keyframes replaceSync: ${getComputedStyle(slotted).opacity}`);
done();
});
</script>