LibWeb: Invalidate stylesheet owners when disabled state changes

Toggling CSSStyleSheet::disabled previously cleared the cached media
match bits and reloaded fonts, but never informed the owning documents
or shadow roots that style resolution was now stale. Worse, the IDL
binding for the disabled attribute dispatches through a non-virtual
setter on StyleSheet, so any override on CSSStyleSheet was bypassed
entirely.

Make set_disabled() virtual so the CSSStyleSheet override actually runs,
snapshot the pre-mutation shadow-root stylesheet effects before flipping
the flag, and hand them to invalidate_owners() so a disable that strips
the last host-reaching rule still tears down host-side style correctly.
This commit is contained in:
Andreas Kling
2026-04-22 22:35:21 +02:00
committed by Andreas Kling
parent a0dc0c61f4
commit cfa75e6eb4
Notes: github-actions[bot] 2026-04-23 14:49:35 +00:00
6 changed files with 52 additions and 6 deletions

View File

@@ -0,0 +1,40 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<div id="target" class="foo">target</div>
<div>bystander 1</div>
<div>bystander 2</div>
<div>bystander 3</div>
<script>
function settleAndReset(triggerElement) {
getComputedStyle(triggerElement).color;
getComputedStyle(triggerElement).color;
internals.resetStyleInvalidationCounters();
}
function addBystanders(parent, count) {
for (let i = 0; i < count; ++i) {
const bystander = document.createElement("div");
bystander.textContent = `bystander ${i + 4}`;
parent.appendChild(bystander);
}
}
test(() => {
const target = document.getElementById("target");
addBystanders(document.body, 25);
const sheet = new CSSStyleSheet();
sheet.replaceSync(".foo { color: rgb(255, 0, 0); }");
document.adoptedStyleSheets = [sheet];
println(`before disable: ${getComputedStyle(target).color}`);
settleAndReset(target);
sheet.disabled = true;
println(`after disable: ${getComputedStyle(target).color}`);
settleAndReset(target);
sheet.disabled = false;
println(`after re-enable: ${getComputedStyle(target).color}`);
});
</script>