[csswg-drafts] Browsers do not really implement the "disallow modification" flag (#13650)

domenic has just created a new issue for https://github.com/w3c/csswg-drafts:

== Browsers do not really implement the "disallow modification" flag ==
https://drafts.csswg.org/cssom/#the-cssstylesheet-interface

Firefox and Chrome both don't perform the check for `insertRule()` and `deleteRule()`.

Chrome additionally doesn't perform the check for `replace()` and `replaceSync()`.

I haven't tested WebKit.

<details>
<summary>WPT</summary>

```html
<!doctype html>
<title>CSSStyleSheet.replace() disallow modification flag</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="help" href="https://drafts.csswg.org/cssom/#dom-cssstylesheet-replace">
<script>
"use strict";

promise_test(async () => {
  const sheet = new CSSStyleSheet();
  const promise = sheet.replace("p { color: red; }");

  assert_throws_dom("NotAllowedError", () => {
    sheet.insertRule("p { color: blue; }");
  }, "insertRule() should throw while replace() is in progress");

  await promise;

  // After the promise resolves, modification should be allowed again
  sheet.insertRule("p { color: green; }");
  assert_equals(sheet.cssRules.length, 2);
}, "insertRule() throws NotAllowedError while replace() is in progress");

promise_test(async () => {
  const sheet = new CSSStyleSheet();
  const promise = sheet.replace("p { color: red; }");

  assert_throws_dom("NotAllowedError", () => {
    sheet.deleteRule(0);
  }, "deleteRule() should throw while replace() is in progress");

  await promise;

  // After the promise resolves, modification should be allowed again
  sheet.deleteRule(0);
  assert_equals(sheet.cssRules.length, 0);
}, "deleteRule() throws NotAllowedError while replace() is in progress");

promise_test(async () => {
  const sheet = new CSSStyleSheet();
  const promise = sheet.replace("p { color: red; }");

  assert_throws_dom("NotAllowedError", () => {
    sheet.replaceSync("p { color: blue; }");
  }, "replaceSync() should throw while replace() is in progress");

  await promise;

  // After the promise resolves, modification should be allowed again
  sheet.replaceSync("p { color: green; }");
  assert_equals(sheet.cssRules[0].style.color, "green");
}, "replaceSync() throws NotAllowedError while replace() is in progress");

promise_test(async t => {
  const sheet = new CSSStyleSheet();
  const firstPromise = sheet.replace("p { color: red; }");

  await promise_rejects_dom(t, "NotAllowedError", sheet.replace("p { color: blue; }"));

  await firstPromise;

  // After the first promise resolves, replace should work again
  const result = await sheet.replace("p { color: green; }");
  assert_equals(result.cssRules[0].style.color, "green");
}, "replace() rejects with NotAllowedError while another replace() is in progress");
</script>
```

I'm happy to contribute the above WPT, but maybe people want to modify the spec instead?

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13650 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 13 March 2026 11:45:04 UTC