blob: 7df1820c0437edbe0edfe4d7bb25c02f832dd3bc [file] [log] [blame]
<!DOCTYPE html>
<title>CSSStyleSheet constructor and adoptedStyleSheets</title>
<link rel="author" title="Rakina Zata Amni" href="mailto:rakina@chromium.org">
<link rel="help" href="https://wicg.github.io/construct-stylesheets/">
<script src = '/resources/testharness.js'></script>
<script src = '/resources/testharnessreport.js'></script>
<section id="firstSection">
<div>
<span class="green"></span>
<span class="red"></span>
<span class="blue"></span>
<span class="white"></span>
<span class="yellow"></span>
</div>
</section>
<section id="secondSection"></section>
<section id="thirdSection"></section>
<script>
'use strict';
const greenStyleText = ".green { color: green; }";
const redStyleTexts = [".red { color: red; }", ".red + span + span { color: red; }"];
const blueStyleTexts = [".blue { color: blue; }", ".blue + span + span { color: blue; }"];
const whiteStyleText = "* { color: white; }";
const yellowStyleText = ".yellow { color: yellow; }";
const firstDiv = document.querySelector('#firstSection > div');
const secondDiv = firstDiv.cloneNode(true);
const shadowRoot = document.querySelector('#secondSection').attachShadow({mode: 'open'});
shadowRoot.appendChild(secondDiv);
const greenSpan = firstDiv.children[0];
const redSpan = firstDiv.children[1];
const blueSpan = firstDiv.children[2];
const whiteSpan = firstDiv.children[3];
const yellowSpan = firstDiv.children[4];
const greenShadowSpan = secondDiv.children[0];
const redShadowSpan = secondDiv.children[1];
const blueShadowSpan = secondDiv.children[2];
const whiteShadowSpan = secondDiv.children[3];
const yellowShadowSpan = secondDiv.children[4];
test(() => {
assert_equals(document.adoptedStyleSheets.length, 0);
}, "document.adoptedStyleSheets should initially have length 0.");
test(() => {
const sheet = new CSSStyleSheet({title: "Red", disabled: true, media: "screen, print"});
assert_equals(sheet.title, "Red");
assert_equals(sheet.ownerNode, null);
assert_equals(sheet.ownerRule, null);
assert_equals(sheet.media.length, 2);
assert_equals(sheet.media.item(0), "screen");
assert_equals(sheet.media.item(1), "print");
assert_true(sheet.disabled);
assert_equals(sheet.cssRules.length, 0);
sheet.insertRule(redStyleTexts[0]);
assert_equals(sheet.cssRules.length, 1);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[0]);
sheet.insertRule(redStyleTexts[1]);
assert_equals(sheet.cssRules.length, 2);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
const sheet2 = new CSSStyleSheet({});
assert_equals(sheet2.title, "")
assert_equals(sheet2.ownerNode, null);
assert_equals(sheet2.ownerRule, null);
assert_equals(sheet2.media.length, 0);
assert_false(sheet2.disabled);
assert_equals(sheet2.cssRules.length, 0);
sheet2.insertRule(redStyleTexts[1]);
assert_equals(sheet2.cssRules.length, 1);
assert_equals(sheet2.cssRules[0].cssText, redStyleTexts[1]);
sheet2.deleteRule(0);
assert_equals(sheet2.cssRules.length, 0);
const sheet3 = new CSSStyleSheet();
assert_equals(sheet3.title, "")
assert_equals(sheet3.ownerNode, null);
assert_equals(sheet3.ownerRule, null);
assert_equals(sheet3.media.length, 0);
assert_false(sheet3.disabled);
assert_equals(sheet3.cssRules.length, 0);
sheet3.insertRule(redStyleTexts[1]);
assert_equals(sheet3.cssRules.length, 1);
assert_equals(sheet3.cssRules[0].cssText, redStyleTexts[1]);
sheet3.deleteRule(0);
assert_equals(sheet3.cssRules.length, 0);
}, 'new CSSStyleSheet produces empty CSSStyleSheet');
promise_test(() => {
const sheet = new CSSStyleSheet({title: "Red", disabled: true, media: "screen, print"});
const promise_sheet = sheet.replace(redStyleTexts[0]);
return promise_sheet.then(function(sheet) {
assert_equals(sheet.title, "Red");
assert_equals(sheet.ownerNode, null);
assert_equals(sheet.ownerRule, null);
assert_equals(sheet.media.length, 2);
assert_equals(sheet.media.item(0), "screen");
assert_equals(sheet.media.item(1), "print");
assert_true(sheet.disabled);
assert_equals(sheet.cssRules.length, 1);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[0]);
sheet.insertRule(redStyleTexts[1]);
assert_equals(sheet.cssRules.length, 2);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
});
}, 'CSSStyleSheet.replace produces Promise<CSSStyleSheet>');
function createAllSheetsPromise() {
const greenSheet = new CSSStyleSheet();
const redSheet = new CSSStyleSheet({media: "screen, print"});
const blueSheet = new CSSStyleSheet({title: "Blue", disabled: true});
const whiteSheet = new CSSStyleSheet({title: "White", alternate: true});
const yellowSheet = new CSSStyleSheet({disabled: false});
const greenPromise = greenSheet.replace(greenStyleText);
const redPromise = redSheet.replace(redStyleTexts[0] + redStyleTexts[1]);
const bluePromise = blueSheet.replace(blueStyleTexts[0] + blueStyleTexts[1]);
const whitePromise = whiteSheet.replace(whiteStyleText);
const yellowPromise = yellowSheet.replace(yellowStyleText);
return [greenPromise, redPromise, bluePromise, whitePromise, yellowPromise];
}
promise_test(() => {
return Promise.all(createAllSheetsPromise()).then(values => {
const greenStyleSheet = values[0];
const redStyleSheet = values[1];
const blueStyleSheet = values[2];
const whiteStyleSheet = values[3];
const yellowStyleSheet = values[4];
// Lists of style sheets can be created, assigned and read.
document.adoptedStyleSheets = [whiteStyleSheet];
// alternate stylesheets aren't applied when title != current preferable name
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
document.adoptedStyleSheets = [greenStyleSheet, blueStyleSheet];
// disabled stylesheets aren't applied
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 128, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
document.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(255, 255, 0)");
document.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 128, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(255, 255, 0)");
});
}, 'Constructed style sheets can be applied on document');
promise_test(() => {
return Promise.all(createAllSheetsPromise()).then(values => {
const greenStyleSheet = values[0];
const redStyleSheet = values[1];
const blueStyleSheet = values[2];
const whiteStyleSheet = values[3];
const yellowStyleSheet = values[4];
shadowRoot.adoptedStyleSheets = [whiteStyleSheet];
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
shadowRoot.adoptedStyleSheets = [greenStyleSheet, blueStyleSheet];
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
shadowRoot.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet];
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(255, 255, 0)");
shadowRoot.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet];
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(255, 255, 0)");
});
}, 'Constructed style sheets can be applied on shadow root');
promise_test(() => {
const plainSheet = new CSSStyleSheet();
const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
return redStyleSheetPromise.then(function(redStyleSheet) {
document.adoptedStyleSheets = [redStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
redStyleSheet.insertRule(redStyleTexts[1]);
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
redStyleSheet.deleteRule(1);
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
redStyleSheet.cssRules[0].style.color = "white";
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 255, 255)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
});
}, 'Changes to constructed stylesheets through CSSOM is reflected');
promise_test(() => {
const plainSheet = new CSSStyleSheet();
const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
return redStyleSheetPromise.then(function(redStyleSheet) {
document.adoptedStyleSheets = [redStyleSheet];
shadowRoot.adoptedStyleSheets = [redStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
shadowRoot.adoptedStyleSheets[0].insertRule(redStyleTexts[1]);
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
});
}, 'Constructed stylesheet can be used and modified in multiple TreeScopes');
promise_test(() => {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const thirdDiv = firstDiv.cloneNode(true);
iframe.contentDocument.body.appendChild(thirdDiv);
const greenIframeSpan = thirdDiv.children[0];
const redIframeSpan = thirdDiv.children[1];
const blueIframeSpan = thirdDiv.children[2];
const whiteIframeSpan = thirdDiv.children[3];
const yellowIframeSpan = thirdDiv.children[4];
const plainSheet = new CSSStyleSheet();
const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
return redStyleSheetPromise.then(function(redStyleSheet) {
assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = [redStyleSheet]; });
assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowIframeSpan).color, "rgb(0, 0, 0)");
document.adoptedStyleSheets = [redStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
document.adoptedStyleSheets[0].insertRule(redStyleTexts[1]);
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
});
}, 'Stylesheets constructed on the main Document cannot be used in iframes');
promise_test(() => {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const thirdDiv = firstDiv.cloneNode(true);
iframe.contentDocument.body.appendChild(thirdDiv);
const greenIframeSpan = thirdDiv.children[0];
const redIframeSpan = thirdDiv.children[1];
const blueIframeSpan = thirdDiv.children[2];
const whiteIframeSpan = thirdDiv.children[3];
const yellowIframeSpan = thirdDiv.children[4];
// Make sure both the main Document and the iframe are not styled
const emptyStyleSheet = new CSSStyleSheet();
document.adoptedStyleSheets = [emptyStyleSheet];
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowIframeSpan).color, "rgb(0, 0, 0)");
const iframePlainSheet = new iframe.contentWindow.CSSStyleSheet();
const iframeRedStyleSheetPromise = iframePlainSheet.replace(redStyleTexts[0]);
return iframeRedStyleSheetPromise.then(function(iframeRedStyleSheet) {
assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [iframeRedStyleSheet]; });
assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
iframe.contentDocument.adoptedStyleSheets = [iframeRedStyleSheet];
assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redIframeSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(yellowIframeSpan).color, "rgb(0, 0, 0)");
iframe.contentDocument.adoptedStyleSheets[0].insertRule(redStyleTexts[1]);
assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(redIframeSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
assert_equals(getComputedStyle(whiteIframeSpan).color, "rgb(255, 0, 0)");
assert_equals(getComputedStyle(yellowIframeSpan).color, "rgb(0, 0, 0)");
});
}, 'Stylesheet constructed on iframe cannot be used in the main Document');
</script>
<div id="divNonConstructed" class="nonConstructed">
</div>
<script>
`use strict`;
const shadowRootNonConstructed = divNonConstructed.attachShadow({mode:'open'})
nonConstructedStyle = document.createElement("style");
shadowRootNonConstructed.appendChild(nonConstructedStyle);
nonConstructedStyle.sheet.insertRule(".nonConstructed { color: red; }", 0);
const nonConstructedStyleSheet = nonConstructedStyle.sheet;
test(() => {
assert_equals(getComputedStyle(divNonConstructed).color, "rgb(0, 0, 0)");
assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [nonConstructedStyleSheet]; });
}, 'Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet is in the same document tree as the AdoptedStyleSheets');
test(() => {
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframeDiv = iframe.contentDocument.createElement("div");
iframeDiv.classList.add("nonConstructed");
iframe.contentDocument.body.appendChild(iframeDiv);
assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = [nonConstructedStyleSheet]; });
assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
iframeStyle = iframe.contentDocument.createElement("style");
iframe.contentDocument.body.appendChild(iframeStyle);
iframeStyle.sheet.insertRule(".nonConstructedSpan { color: red; }");
const iframeStyleSheet = iframeStyle.sheet;
nonConstructedSpan = document.createElement("span");
nonConstructedSpan.classList.add(".nonConstructedSpan");
divNonConstructed.appendChild(nonConstructedSpan);
assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [iframeStyleSheet]; });
assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
}, 'Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet and the AdoptedStyleSheets are in different document trees');
function attachShadowDiv(host) {
const shadowRoot = host.attachShadow({mode: 'open'});
const shadowDiv = document.createElement("div");
shadowRoot.appendChild(shadowDiv);
return shadowDiv;
}
test(() => {
// Attach a div inside a shadow root with the class ".red".
const span = document.createElement("span");
thirdSection.appendChild(span);
const shadowDiv = attachShadowDiv(span);
shadowDiv.classList.add("red");
// Create empty stylesheet.
const sheet = new CSSStyleSheet();
span.shadowRoot.adoptedStyleSheets = [sheet];
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
// Replace the stylesheet text that will color it red.
sheet.replaceSync(redStyleTexts[0]);
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
assert_equals(sheet.cssRules.length, 1);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[0]);
sheet.insertRule(redStyleTexts[1]);
assert_equals(sheet.cssRules.length, 2);
assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
}, 'CSSStyleSheet.replaceSync replaces stylesheet text synchronously');
const import_text = '@import url("support/constructable-import.css");';
test(() => {
assert_throws("NotAllowedError", () => { (new CSSStyleSheet).replaceSync(import_text) });
}, 'CSSStyleSheet.replaceSync throws exception when there is import rule inside');
test(() => {
assert_throws("NotAllowedError", () => { (new CSSStyleSheet).insertRule(import_text) });
}, 'Inserting an @import rule through insertRule on a constructed stylesheet throws an exception');
promise_test(() => {
const span = document.createElement("span");
thirdSection.appendChild(span);
const shadowDiv = attachShadowDiv(span);
const sheet = new CSSStyleSheet();
span.shadowRoot.adoptedStyleSheets = [sheet];
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
// Replace and assert that the imported rule is applied.
const sheet_promise = sheet.replace(import_text);
return sheet_promise.then((sheet) => {
assert_equals(sheet.cssRules.length, 1);
assert_equals(sheet.cssRules[0].cssText, import_text);
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
});
}, 'CSSStyleSheet.replace allows import rule inside');
promise_test(() => {
const sheet = new CSSStyleSheet();
const sheet_promise = sheet.replace("import url('not-there.css');");
return sheet_promise.catch((reason) => {
assert_equals(reason.name, "NotAllowedError");
});
}, 'CSSStyleSheet.replace returns rejected promise on failed imports');
test(() => {
const span = document.createElement("span");
thirdSection.appendChild(span);
const shadowDiv = attachShadowDiv(span);
const sheet = new CSSStyleSheet();
span.shadowRoot.adoptedStyleSheets = [sheet];
const newSpan = span.cloneNode(true);
assert_equals(newSpan.shadowRoot, null);
}, 'Cloning a shadow host will not clone shadow root, and also adoptedStyleSheets');
test(() => {
const span = document.createElement("span");
thirdSection.appendChild(span);
const shadowDiv = attachShadowDiv(span);
const sheet = new CSSStyleSheet();
span.shadowRoot.adoptedStyleSheets = [sheet];
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const newSpan = iframe.contentDocument.importNode(span, true);
iframe.contentDocument.body.appendChild(newSpan);
assert_equals(newSpan.shadowRoot, null);
}, 'Importing a shadow host will not copy shadow root, and also adoptedStyleSheets');
test(() => {
const span = document.createElement("span");
thirdSection.appendChild(span);
const shadowDiv = attachShadowDiv(span);
const sheet = new CSSStyleSheet();
sheet.replaceSync("* { color: red; }");
span.shadowRoot.adoptedStyleSheets = [sheet];
assert_equals(getComputedStyle(shadowDiv).color, "rgb(255, 0, 0)");
const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.contentDocument.adoptNode(span);
iframe.contentDocument.body.appendChild(span);
assert_not_equals(span.shadowRoot, null);
assert_equals(span.shadowRoot.adoptedStyleSheets.length, 1);
assert_equals(span.shadowRoot.adoptedStyleSheets[0], sheet);
assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
}, 'Adopting a shadow host will move adoptedStyleSheets but it is not applied');
</script>