Skip to content

Commit 25d1c08

Browse files
mfreed7chromium-wpt-export-bot
authored andcommitted
Disable @import in replace() and replaceSync()
The CSSWG resolved [1] that "@import doesn't parse in constructable stylesheets and as a result throw syntax errors". We have a comment [2] requesting clarification, but the working assumption is: - calling replace() with text that includes @import will ignore the @import, and issue a console warning. - calling replaceSync() with text that includes @import will ignore the @import, and issue a console warning. - calling insertRule() on any stylesheet with an @import rule will throw a SyntaxError. *Prior* to this CL, the behavior of Chromium was: - calling replace() with text that includes @import would work. The returned Promise would resolve once all @imports were loaded. Any invalid @import rules would cause a NetworkError to be thrown. - calling replaceSync() with text that includes @import would throw a "NotAllowed" exception. - calling insertRule() with an @import rule would throw a SyntaxError *for constructed stylesheets only*. No exception would be thrown for document.styleSheets. The Intent to Remove for this change is at [3]. [1] WICG/construct-stylesheets#119 (comment) [2] WICG/construct-stylesheets#119 (comment) [3] https://groups.google.com/a/chromium.org/g/blink-dev/c/RKG8oxp22RY/m/fdFnG1rGCgAJ Bug: 1055943 Change-Id: I0a8444289b137b4c2880be5231696bb526331107
1 parent b563442 commit 25d1c08

File tree

5 files changed

+58
-62
lines changed

5 files changed

+58
-62
lines changed

css/cssom/CSSStyleSheet-constructable.html

+48-39
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
test(() => {
5050
const sheet = new CSSStyleSheet({disabled: true, media: "screen, print"});
51-
assert_equals(sheet.title, null);
51+
assert_equals(sheet.title, "");
5252
assert_equals(sheet.ownerNode, null);
5353
assert_equals(sheet.ownerRule, null);
5454
assert_equals(sheet.media.length, 2);
@@ -66,7 +66,7 @@
6666
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
6767

6868
const sheet2 = new CSSStyleSheet({});
69-
assert_equals(sheet2.title, null);
69+
assert_equals(sheet2.title, "");
7070
assert_equals(sheet2.ownerNode, null);
7171
assert_equals(sheet2.ownerRule, null);
7272
assert_equals(sheet2.media.length, 0);
@@ -81,7 +81,7 @@
8181
assert_equals(sheet2.cssRules.length, 0);
8282

8383
const sheet3 = new CSSStyleSheet();
84-
assert_equals(sheet3.title, null);
84+
assert_equals(sheet3.title, "");
8585
assert_equals(sheet3.ownerNode, null);
8686
assert_equals(sheet3.ownerRule, null);
8787
assert_equals(sheet3.media.length, 0);
@@ -98,14 +98,14 @@
9898

9999
test(() => {
100100
const sheet = new CSSStyleSheet({title: "something"});
101-
assert_equals(sheet.title, null);
102-
}, "title cannot be set in the CSSStyleSheet constructor");
101+
assert_equals(sheet.title, "something");
102+
}, "title can be set in the CSSStyleSheet constructor");
103103

104104
promise_test(() => {
105105
const sheet = new CSSStyleSheet({disabled: true, media: "screen, print"});
106106
const promise_sheet = sheet.replace(redStyleTexts[0]);
107107
return promise_sheet.then(function(sheet) {
108-
assert_equals(sheet.title, null);
108+
assert_equals(sheet.title, "");
109109
assert_equals(sheet.ownerNode, null);
110110
assert_equals(sheet.ownerRule, null);
111111
assert_equals(sheet.media.length, 2);
@@ -535,24 +535,19 @@
535535
const style = document.createElement("style");
536536
style.textContent = ".target { color: white; }";
537537
span.shadowRoot.appendChild(style)
538-
// non-adopted styles should be ordered before adopted styles
539-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
538+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)", "non-adopted styles should be ordered before adopted styles");
540539

541540
span.shadowRoot.adoptedStyleSheets = [];
542-
// with no adopted styles in conflict, the non-adopted style should take effect
543-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 255, 255)");
541+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 255, 255)", "with no adopted styles in conflict, the non-adopted style should take effect");
544542

545543
span.shadowRoot.adoptedStyleSheets = [sheet];
546-
// the adopted style should be ordered after the non-adopted style
547-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
544+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)", "the adopted style should be ordered after the non-adopted style");
548545

549546
sheet.disabled = true;
550-
// with the adopted sheet disabled, the non-adopted style should take effect
551-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 255, 255)");
547+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 255, 255)", "with the adopted sheet disabled, the non-adopted style should take effect");
552548

553549
sheet.disabled = false;
554-
// the adopted sheet re-enabled, it should take effect again.
555-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
550+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)", "the adopted sheet re-enabled, it should take effect again");
556551
}, 'Adopted sheets are ordered after non-adopted sheets in the shadow root')
557552

558553
test(() => {
@@ -574,41 +569,36 @@
574569
const style = document.createElement("style");
575570
style.textContent = ".target { color: white; }";
576571
span.appendChild(style)
577-
// non-adopted styles should be ordered before adopted styles
578-
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)");
572+
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)", "non-adopted styles should be ordered before adopted styles");
579573

580574
document.adoptedStyleSheets = [];
581-
// with no adopted styles in conflict, the non-adopted style should take effect
582-
assert_equals(getComputedStyle(span).color, "rgb(255, 255, 255)");
575+
assert_equals(getComputedStyle(span).color, "rgb(255, 255, 255)", "with no adopted styles in conflict, the non-adopted style should take effect");
583576

584577
document.adoptedStyleSheets = [sheet];
585-
// the adopted style should be ordered after the non-adopted style
586-
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)");
578+
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)", "the adopted style should be ordered after the non-adopted style");
587579

588580
sheet.disabled = true;
589-
// with the adopted sheet disabled, the non-adopted style should take effect
590-
assert_equals(getComputedStyle(span).color, "rgb(255, 255, 255)");
581+
assert_equals(getComputedStyle(span).color, "rgb(255, 255, 255)", "with the adopted sheet disabled, the non-adopted style should take effect");
591582

592583
sheet.disabled = false;
593-
// the adopted sheet re-enabled, it should take effect again.
594-
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)")
584+
assert_equals(getComputedStyle(span).color, "rgb(255, 0, 0)", "the adopted sheet re-enabled, it should take effect again")
595585
}, 'Adopted sheets are ordered after non-adopted sheets in the document')
596586

597587
const import_text = '@import url("support/constructable-import.css");';
598588

599-
test(() => {
600-
assert_throws_dom("NotAllowedError", () => { (new CSSStyleSheet).replaceSync(import_text) });
601-
}, 'CSSStyleSheet.replaceSync throws exception when there is import rule inside');
602-
603589
test(() => {
604590
assert_throws_dom("NotAllowedError", () => { (new CSSStyleSheet).insertRule(import_text) });
605591
}, 'Inserting an @import rule through insertRule on a constructed stylesheet throws an exception');
606592

593+
test(() => {
594+
assert_throws_dom("NotAllowedError", () => { document.styleSheets[0].insertRule(import_text) });
595+
}, 'Inserting an @import rule through insertRule on a document stylesheet throws an exception');
596+
607597
async_test(t => {
608598
const importUrl = "support/constructable-import.css";
609599
const sheet = new CSSStyleSheet();
610600

611-
assert_throws_dom("NotAllowedError", () => { sheet.replaceSync(`@import url("${importUrl}");`) });
601+
sheet.replaceSync(`@import url("${importUrl}");`);
612602

613603
const timeAfterReplaceSync = performance.now();
614604
let link = document.createElement("link");
@@ -632,27 +622,46 @@
632622
const sheet = new CSSStyleSheet();
633623
span.shadowRoot.adoptedStyleSheets = [sheet];
634624
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
635-
// Replace and assert that the imported rule is applied.
625+
// Replace and assert that the imported rule is NOT applied.
636626
const sheet_promise = sheet.replace(import_text);
637627
return sheet_promise.then((sheet) => {
638-
assert_equals(sheet.cssRules.length, 1);
639-
assert_equals(sheet.cssRules[0].cssText, import_text);
640-
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
628+
// replace() ignores @import rules:
629+
assert_equals(sheet.cssRules.length, 0);
630+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
641631
}).catch((reason) => {
642632
assert_unreached(`Promise was rejected (${reason}) when it should have been resolved`);
643633
});
644-
}, 'CSSStyleSheet.replace allows import rule inside');
634+
}, 'CSSStyleSheet.replace allows, but ignores, import rule inside');
635+
636+
637+
test(() => {
638+
const span = document.createElement("span");
639+
thirdSection.appendChild(span);
640+
const shadowDiv = attachShadowDiv(span);
641+
const sheet = new CSSStyleSheet();
642+
span.shadowRoot.adoptedStyleSheets = [sheet];
643+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
644+
// Replace and assert that the imported rule is NOT applied.
645+
try {
646+
sheet.replaceSync(import_text);
647+
// replaceSync() ignores @import rules:
648+
assert_equals(sheet.cssRules.length, 0);
649+
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
650+
} catch(reason) {
651+
assert_unreached(`replaceSync threw an exception (${reason}) when it shouldn't have`);
652+
}
653+
}, 'CSSStyleSheet.replaceSync allows, but ignores, import rule inside');
645654

646655
promise_test(() => {
647656
const sheet = new CSSStyleSheet();
648657
const sheet_promise = sheet.replace("@import url('not-there.css');");
649658

650659
return sheet_promise.then((sheet) => {
651-
assert_unreached("Promise was resolved when it should have been rejected");
660+
// No exception here
652661
}).catch((reason) => {
653-
assert_equals(reason.name, "NetworkError");
662+
assert_unreached("Promise was rejected");
654663
});
655-
}, 'CSSStyleSheet.replace returns rejected promise on failed imports');
664+
}, 'CSSStyleSheet.replace does not reject on failed imports');
656665

657666
test(() => {
658667
const span = document.createElement("span");

css/cssom/insertRule-from-script-ref.html

-6
This file was deleted.

css/cssom/insertRule-from-script.html

-12
This file was deleted.

css/cssom/insertRule-namespace-no-index.html

+8-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@
3232

3333
test(function() {
3434
assert_equals(sheet.cssRules.length, 3);
35-
sheet.insertRule("@import url(\"support/a-green.css\");");
36-
assert_equals(sheet.cssRules.length, 4);
37-
}, "insertRule with namespace and omitted index argument should insert import");
35+
try {
36+
sheet.insertRule("@import url(\"support/a-green.css\");");
37+
assert_unreached("insertRule with @import should throw");
38+
} catch (e) {
39+
assert_true(true,"insertRule with @import should throw");
40+
}
41+
assert_equals(sheet.cssRules.length, 3);
42+
}, "insertRule of @import with namespace and omitted index argument should throw");
3843
</script>
3944
</body>
4045
</html>

html/semantics/scripting-1/the-script-element/css-module/import-css-module-basic.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
const iframe = document.createElement("iframe");
2323
iframe.src = "resources/css-module-at-import-iframe.html";
2424
iframe.onload = test.step_func_done(function () {
25-
assert_equals(iframe.contentDocument.load_error, "NotAllowedError");
25+
assert_equals(iframe.contentDocument.load_error, undefined);
2626
assert_not_equals(getComputedStyle(iframe.contentDocument.querySelector('#test'))
2727
.backgroundColor, "rgb(255, 0, 0)",
2828
"CSS module @import should not succeed");
2929
});
3030
document.body.appendChild(iframe);
31-
}, "An @import CSS Module should not load");
31+
}, "An @import CSS Module should not load, but should not throw an exception");
3232

3333
async_test(function (test) {
3434
const iframe = document.createElement("iframe");

0 commit comments

Comments
 (0)