Update web-platform-tests to revision b'ee6da9d71d0268d7fdb04e8e5b26858f46ee0cc4'

This commit is contained in:
WPT Sync Bot 2022-01-20 04:38:55 +00:00 committed by cybai
parent 4401622eb1
commit b77ad115f6
16832 changed files with 270819 additions and 87621 deletions

View file

@ -8,7 +8,6 @@
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#all-shorthand">
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="all-prop-001-ref.html">
<meta name="flags" content="">
<meta name="assert" content="Test passes if 'all' resets properties other than 'direction' and 'unicode-bidi'.">
<style>
.test {

View file

@ -7,7 +7,6 @@
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#all-shorthand">
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="">
<meta name="assert" content="all:inherit should cause display:inherit so the red divs will display inline/horizontal (like their parent span) rather than block/vertical (like the default UA style for a div).">
<style>
.inline {

View file

@ -5,7 +5,6 @@
<title>CSS Cascade: "color" property preceded by "all: initial"</title>
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="reference/ref-green-text.html">
<meta name="flags" content="">
<meta name="assert" content="Own 'color', preceded by 'all: inherit', overrides inherited 'color'.">
<style>
.outer {

View file

@ -5,7 +5,6 @@
<title>CSS Cascade: "color" property preceded by "all: initial"</title>
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="reference/ref-green-text.html">
<meta name="flags" content="">
<meta name="assert" content="Own 'color', preceded by 'all: initial', overrides inherited 'color'.">
<style>
.outer {

View file

@ -5,7 +5,6 @@
<title>CSS Cascade: "color" property preceded by "all: revert"</title>
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="reference/ref-green-text.html">
<meta name="flags" content="">
<meta name="assert" content="Own 'color', preceded by 'all: revert', overrides inherited 'color'.">
<style>
.outer {

View file

@ -5,7 +5,6 @@
<title>CSS Cascade: "color" property preceded by "all: unset"</title>
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#all-shorthand">
<link rel="match" href="reference/ref-green-text.html">
<meta name="flags" content="">
<meta name="assert" content="Own 'color', preceded by 'all: unset', overrides inherited 'color'.">
<style>
.outer {

View file

@ -0,0 +1,36 @@
<!doctype html>
<title>CSS Cascade Layers IDL tests</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layer-apis">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
<style>
@layer bar, baz;
@import url('data:text/css,') layer(qux);
@layer foo { }
</style>
<script>
'use strict';
idl_test(
['css-cascade'],
['cssom'],
idl_array => {
try {
self.statement = document.styleSheets[0].cssRules.item(0);
self.layeredImport = document.styleSheets[0].cssRules.item(1);
self.block = document.styleSheets[0].cssRules.item(2);
} catch (e) {
// Will be surfaced when any rule is undefined below.
}
idl_array.add_objects({
CSSLayerBlockRule: ['block'],
CSSLayerStatementRule: ['statement'],
CSSImportRule: ['layeredImport']
});
}
);
</script>

View file

@ -8,7 +8,6 @@
<link rel="help" href="https://drafts.csswg.org/css-cascade/#importance">
<link rel="match" href="important-prop-ref.html">
<meta name="assert" content="Test passes if normal rules are overridden by animations, important rules override animations, and !important declarations are ignored in animations.">
<meta name="flags" content="">
<style>
@keyframes override {
from, to {

View file

@ -7,7 +7,6 @@
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#initial">
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#initial">
<link rel="match" href="initial-color-background-001-ref.html">
<meta name="flags" content="">
<meta name="assert" content="initial is not the same as inherit. color:initial results in non-red. background-color:initial results in transparent.">
<style>
body {

View file

@ -26,9 +26,9 @@ var testCases = [
{
title: 'A2 Anonymous layers',
style: `
target { color: red; }
target { color: green; }
@layer {
target { color: green; }
target { color: red; }
}
`,
},
@ -36,9 +36,9 @@ var testCases = [
title: 'A3 Anonymous layers',
style: `
@layer {
target { color: green; }
target { color: red; }
}
target { color: red; }
target { color: green; }
`,
},
{
@ -56,12 +56,11 @@ var testCases = [
title: 'A5 Anonymous layers',
style: `
@layer {
target { color: red; }
target { color: green; }
@layer {
target { color: green; }
target { color: red; }
}
}
target { color: red; }
`,
},
{
@ -69,11 +68,10 @@ var testCases = [
style: `
@layer {
@layer {
target { color: green; }
target { color: red; }
}
target { color: red; }
target { color: green; }
}
target { color: red; }
`,
},
{
@ -87,9 +85,9 @@ var testCases = [
}
@layer {
@layer {
target { color: green; }
target { color: red; }
}
target { color: red; }
target { color: green; }
}
`,
},
@ -106,9 +104,9 @@ var testCases = [
}
@layer {
@layer {
target { color: green; }
target { color: red; }
}
target { color: red; }
target { color: green; }
}
`,
},
@ -124,10 +122,10 @@ var testCases = [
@layer {
@layer {
@layer {
target { color: green; }
target { color: red; }
}
}
target { color: red; }
target { color: green; }
}
`,
},
@ -143,9 +141,9 @@ var testCases = [
title: 'B2 Named layers',
style: `
@layer A {
target { color: green; }
target { color: red; }
}
target { color: red; }
target { color: green; }
`,
},
{
@ -157,7 +155,6 @@ var testCases = [
@layer A {
target { color: green; }
}
target { color: red; }
`,
},
{
@ -178,9 +175,9 @@ var testCases = [
title: 'B5 Named layers',
style: `
@layer A {
target { color: red; }
target { color: green; }
@layer A {
target { color: green; }
target { color: red; }
}
}
`,
@ -365,11 +362,11 @@ var testCases = [
style: `
@layer A {
@layer {
target { color: green; }
target { color: red; }
}
}
@layer A {
target { color: red; }
target { color: green; }
}
`,
},
@ -508,11 +505,10 @@ var testCases = [
},
];
for (var i = 0; i < testCases.length; ++i) {
var testCase = testCases[i];
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
for (let testCase of testCases) {
const styleElement = document.createElement('style');
styleElement.textContent = testCase['style'];
document.head.append(styleElement);
test(function () {
var targets = document.querySelectorAll('target');
@ -521,7 +517,7 @@ for (var i = 0; i < testCases.length; ++i) {
testCase['title'] + ", target '" + target.classList[0] + "'");
}, testCase['title']);
document.head.removeChild(documentStyle)
styleElement.remove();
}
</script>
</body>

View file

@ -0,0 +1,150 @@
<!DOCTYPE html>
<title>Resolving @counter-style name conflicts with cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target, #reference {
font-family: monospace;
width: min-content;
}
#reference::before {
content: '0000';
}
@counter-style three {
system: cyclic;
symbols: '000';
}
@counter-style four {
system: cyclic;
symbols: '0000';
}
</style>
<ul>
<li id="target"></li>
<li id="reference"></li>
</ul>
<script>
// In all tests, #target::before should have 4 characters, same as #reference.
const testCases = [
{
title: '@counter-style unlayered overrides layered',
style: `
#target::before {
content: counter(dont-care, custom-counter-style);
}
@counter-style custom-counter-style {
system: extends four;
}
@layer {
@counter-style custom-counter-style {
system: extends three;
}
}
`
},
{
title: '@counter-style override between layers',
style: `
@layer base, override;
#target::before {
content: counter(dont-care, custom-counter-style);
}
@layer override {
@counter-style custom-counter-style {
system: extends four;
}
}
@layer base {
@counter-style custom-counter-style {
system: extends three;
}
}
`
},
{
title: '@counter-style override update with appended sheet 1',
style: `
@layer base, override;
#target::before {
content: counter(dont-care, custom-counter-style);
}
@layer override {
@counter-style custom-counter-style {
system: extends four;
}
}
`,
append: `
@layer base {
@counter-style custom-counter-style {
system: extends three;
}
}
`
},
{
title: '@counter-style override update with appended sheet 2',
style: `
@layer base, override;
#target::before {
content: counter(dont-care, custom-counter-style);
}
@layer base {
@counter-style custom-counter-style {
system: extends three;
}
}
`,
append: `
@layer override {
@counter-style custom-counter-style {
system: extends four;
}
}
`
},
];
for (let testCase of testCases) {
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
var appendedStyle;
if (testCase['append']) {
document.body.offsetLeft; // Force style update
appendedStyle = document.createElement('style');
appendedStyle.appendChild(document.createTextNode(testCase['append']));
document.head.appendChild(appendedStyle);
}
test(function () {
assert_equals(getComputedStyle(target).width,
getComputedStyle(reference).width);
}, testCase['title']);
if (appendedStyle)
appendedStyle.remove();
documentStyle.remove();
}
</script>

View file

@ -0,0 +1,190 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: at-rule and style invalidation on layer order changes</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="stylesheet" href="/fonts/ahem.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#reference {
color: green;
font: 20px/1 ahem;
width: max-content;
--foo: green;
}
</style>
<div id=target>Lorem ipsum</div>
<div id=reference>Lorem ipsum</div>
<script>
const testCases = [
{
title: 'Insert layer invalidates style',
sheets: [
'',
`
@layer first {
#target { color: green; }
}
@layer second {
#target { color: red; }
}
`,
],
update: function(sheets) {
sheets[0].insertRule('@layer second {}', 0);
},
property: 'color',
},
{
title: 'Delete layer invalidates style',
sheets: [
'@layer second {}',
`
@layer first {
#target { color: red; }
}
@layer second {
#target { color: green; }
}
`,
],
update: function(sheets) {
sheets[0].deleteRule(0);
},
property: 'color',
},
{
title: 'Insert layer invalidates @font-face',
sheets: [
'',
`
@layer first {
@font-face {
font-family: custom;
src: local('Ahem'), url('/fonts/Ahem.ttf');
}
}
@layer second {
@font-face {
font-family: custom;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
#target { font: 20px/1 custom; width: max-content; }
`,
],
update: async function(sheets) {
await document.fonts.load('20px/1 ahem');
await document.fonts.load('20px/1 custom');
document.body.offsetLeft; // Force style recalc
sheets[0].insertRule('@layer second {}', 0);
await document.fonts.load('20px/1 custom');
},
property: 'width',
},
{
title: 'Delete layer invalidates @font-face',
sheets: [
'@layer second {}',
`
@layer first {
@font-face {
font-family: custom;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
@layer second {
@font-face {
font-family: custom;
src: local('Ahem'), url('/fonts/Ahem.ttf');
}
}
#target { font: 20px/1 custom; width: max-content; }
`,
],
update: async function(sheets) {
await document.fonts.load('20px/1 ahem');
await document.fonts.load('20px/1 custom');
document.body.offsetLeft; // Force style recalc
sheets[0].deleteRule(0);
await document.fonts.load('20px/1 custom');
},
property: 'width',
},
{
title: 'Insert layer invalidates @property',
sheets: [
'',
`
@layer first {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
}
@layer second {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
`,
],
update: function(sheets) {
sheets[0].insertRule('@layer second {}', 0);
},
property: '--foo',
},
{
title: 'Delete layer invalidates @property',
sheets: [
'@layer second {}',
`
@layer first {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
@layer second {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
}
`,
],
update: function(sheets) {
sheets[0].deleteRule(0);
},
property: '--foo',
},
];
for (let testCase of testCases) {
promise_test(async test => {
const styleElements = testCase.sheets.map(sheet => {
const element = document.createElement('style');
element.appendChild(document.createTextNode(sheet));
document.head.appendChild(element);
return element;
});
test.add_cleanup(() => {
for (let element of styleElements)
element.remove();
});
const sheets = styleElements.map(element => element.sheet);
await testCase.update(sheets);
const actual = getComputedStyle(target).getPropertyValue(testCase.property);
const expected = getComputedStyle(reference).getPropertyValue(testCase.property);
assert_equals(actual, expected);
}, testCase.title);
}
</script>

View file

@ -0,0 +1,141 @@
<!DOCTYPE html>
<title>Resolving @keyframe name conflicts with cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target {
font-size: 20px;
width: min-content;
}
</style>
<div id="target">Test</div>
<script>
// In all tests, width of #target should be 80px.
const testCases = [
{
title: '@font-face unlayered overrides layered',
style: `
#target {
font-family: custom-font;
}
@font-face {
font-family: custom-font;
src: url('/fonts/Ahem.ttf');
}
@layer {
@font-face {
font-family: custom-font;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
`
},
{
title: '@font-face override between layers',
style: `
@layer base, override;
#target {
font-family: custom-font;
}
@layer override {
@font-face {
font-family: custom-font;
src: url('/fonts/Ahem.ttf');
}
}
@layer base {
@font-face {
font-family: custom-font;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
`
},
{
title: '@font-face override update with appended sheet 1',
style: `
@layer base, override;
#target {
font-family: custom-font;
}
@layer override {
@font-face {
font-family: custom-font;
src: url('/fonts/Ahem.ttf');
}
}
`,
append: `
@layer base {
@font-face {
font-family: custom-font;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
`
},
{
title: '@font-face override update with appended sheet 2',
style: `
@layer base, override;
#target {
font-family: custom-font;
}
@layer base {
@font-face {
font-family: custom-font;
src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff');
}
}
`,
append: `
@layer override {
@font-face {
font-family: custom-font;
src: url('/fonts/Ahem.ttf');
}
}
`
},
];
for (let testCase of testCases) {
promise_test(async () => {
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
var appendedStyle;
if (testCase['append']) {
document.body.offsetLeft; // Force style update
appendedStyle = document.createElement('style');
appendedStyle.appendChild(document.createTextNode(testCase['append']));
document.head.appendChild(appendedStyle);
}
await document.fonts.load('20px/1 custom-font');
assert_equals(getComputedStyle(target).width, '80px');
if (appendedStyle)
appendedStyle.remove();
documentStyle.remove();
}, testCase['title']);
}
</script>

View file

@ -57,24 +57,24 @@ const testCases = [
{
title: 'A1 Layer rules with import',
style: `
@import url(basic-red.css);
@import url(basic-green.css);
@layer {
target { color: green; }
target { color: red; }
}
`
},
{
title: 'A2 Layer rules with import',
style: `
@import url(layer-green.css);
target { color: red; }
@import url(layer-red.css);
target { color: green; }
`
},
{
title: 'A3 Layer rules with import',
style: `
@import url(layer-green.css);
@import url(basic-red.css);
@import url(basic-green.css);
@import url(layer-red.css);
`
},
{
@ -92,8 +92,8 @@ const testCases = [
{
title: 'B1 Anonymous imports',
style: `
@import url(basic-green.css) layer;
target { color: red; }
@import url(basic-red.css) layer;
target { color: green; }
`
},
{
@ -122,8 +122,8 @@ const testCases = [
{
title: 'C1 Named imports',
style: `
@import url(basic-green.css) layer(A);
target { color: red; }
@import url(basic-red.css) layer(A);
target { color: green; }
`
},
{
@ -145,9 +145,9 @@ const testCases = [
{
title: 'C4 Named imports',
style: `
@import url(layer-green.css) layer(A);
@import url(layer-red.css) layer(A);
@layer A {
target { color: red; }
target { color: green; }
}
`
},
@ -192,8 +192,8 @@ const testCases = [
title: 'C9 Named imports',
style: `
@import url(basic-red.css) layer(A);
@import url(basic-green.css) layer(B.A);
@import url(basic-red.css) layer(B);
@import url(basic-red.css) layer(B.A);
@import url(basic-green.css) layer(B);
`
},
{
@ -252,6 +252,18 @@ const testCases = [
}
`
},
{
title: 'E1 Named imports establish layer even with network errors',
style: `
@import "nonexist.css" layer(A);
@layer B {
target { color: green; }
}
@layer A {
target { color: red; }
}
`,
},
];
for (let testCase of testCases) {
@ -260,18 +272,21 @@ for (let testCase of testCases) {
const styleText = testCase['style'].replaceAll(/url\((.+?)\)/g, (match, p1) => {
return `url(data:text/css,${ encodeURI(imports[p1]) })`;
});
styleElement.appendChild(document.createTextNode(styleText));
styleElement.textContent = styleText;
await new Promise(resolve => {
styleElement.onload = resolve;
document.head.appendChild(styleElement);
styleElement.onerror = resolve;
document.head.append(styleElement);
});
const targets = document.querySelectorAll('target');
for (target of targets)
assert_equals(window.getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title'] + ", target '" + target.classList[0] + "'");
document.head.removeChild(styleElement);
try {
const targets = document.querySelectorAll('target');
for (target of targets)
assert_equals(window.getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title'] + ", target '" + target.classList[0] + "'");
} finally {
styleElement.remove();
}
}, testCase['title']);
}
</script>

View file

@ -0,0 +1,138 @@
<!DOCTYPE html>
<title>Resolving @keyframe name conflicts with cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target, #reference {
width: 100px;
height: 100px;
}
#reference {
background-color: green;
}
</style>
<div id="target"></div>
<div id="reference"></div>
<script>
// In all tests, background color of #target should be green, same as #reference
const testCases = [
{
title: '@keyframes unlayered overrides layered',
style: `
#target {
animation: anim 1s paused;
}
@keyframes anim {
from { background-color: green; }
}
@layer {
@keyframes anim {
from { background-color: red; }
}
}
`
},
{
title: '@keyframes override between layers',
style: `
@layer base, override;
#target {
animation: anim 1s paused;
}
@layer override {
@keyframes anim {
from { background-color: green; }
}
}
@layer base {
@keyframes anim {
from { background-color: red; }
}
}
`
},
{
title: '@keyframes override update with appended sheet 1',
style: `
@layer base, override;
#target {
animation: anim 1s paused;
}
@layer override {
@keyframes anim {
from { background-color: green; }
}
}
`,
append: `
@layer base {
@keyframes anim {
from { background-color: red; }
}
}
`
},
{
title: '@keyframes override update with appended sheet 2',
style: `
@layer base, override;
#target {
animation: anim 1s paused;
}
@layer base {
@keyframes anim {
from { background-color: red; }
}
}
`,
append: `
@layer override {
@keyframes anim {
from { background-color: green; }
}
}
`
},
];
for (let testCase of testCases) {
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
var appendedStyle;
if (testCase['append']) {
document.body.offsetLeft; // Force style update
appendedStyle = document.createElement('style');
appendedStyle.appendChild(document.createTextNode(testCase['append']));
document.head.appendChild(appendedStyle);
}
test(function () {
assert_equals(getComputedStyle(target).backgroundColor,
getComputedStyle(reference).backgroundColor);
}, testCase['title']);
if (appendedStyle)
appendedStyle.remove();
documentStyle.remove();
}
</script>

View file

@ -0,0 +1,169 @@
<!DOCTYPE html>
<html>
<head>
<title>CSS Cascade Layers: Media queries</title>
<meta name="assert" content="CSS Cascade Layers nested in Media Queries">
<link rel="author" title="Antti Koivisto" href="mailto:antti@apple.com">
<link rel="help" href="https://www.w3.org/TR/css-cascade-5/#layering">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<iframe width=300 height=300 frameborder=0></iframe>
<div id="log"></div>
<script>
const imports = {
"basic-green.css": `
target { color: green; }
`,
"basic-red.css": `
target { color: red; }
`,
"empty.css": "",
};
// For 300px wide iframe the target should be red and for 500px green.
const testCases = [
{
title: 'A1 Basic',
style: `
@layer { target { color: red } }
@media (min-width: 500px) {
@layer {
target { color: green; }
}
}
`
},
{
title: 'A2 Basic',
style: `
@media (min-width: 500px) {
@layer {
target { color: green; }
}
}
@media (max-width: 300px) {
@layer {
target { color: red; }
}
}
`
},
{
title: 'B1 Basic import',
style: `
@import url(basic-red.css) layer;
@import url(basic-green.css) layer (min-width: 500px);
`
},
{
title: 'B2 Basic import',
style: `
@import url(basic-green.css) layer (min-width: 500px);
@import url(basic-red.css) layer (max-width: 300px);
`
},
{
title: 'C1 Reordering',
style: `
@media (max-width: 300px) {
@layer B {
target { color: green; }
}
@layer A {
target { color: red; }
}
}
@media (min-width: 500px) {
@layer A {
target { color: red; }
}
@layer B {
target { color: green; }
}
}
`
},
{
title: 'C2 Reordering',
style: `
@media (max-width: 300px) {
@layer B { }
@layer A { target { color: red; } }
}
@media (min-width: 500px) {
@layer A { target { color: red; } }
@layer B { }
}
@layer B {
target { color: green; }
}
`
},
{
title: 'C3 Reordering',
style: `
@media (max-width: 300px) {
@layer B, A;
}
@media (min-width: 500px) {
@layer A, B;
}
@layer A {
target { color: red; }
}
@layer B {
target { color: green; }
}
`
},
{
title: 'C4 Reordering',
style: `
@import url(empty.css) layer(B) (max-width: 300px);
@import url(empty.css) layer(A) (max-width: 300px);
@import url(empty.css) layer(A) (min-width: 500px);
@import url(empty.css) layer(B) (min-width: 500px);
@layer A {
target { color: red; }
}
@layer B {
target { color: green; }
}
`
},
];
let iframe = document.querySelector("iframe");
for (let testCase of testCases) {
promise_test(async t => {
const styleText = testCase['style'].replaceAll(/url\((.+?)\)/g, (match, p1) => {
return `url(data:text/css,${ encodeURI(imports[p1]) })`;
});
iframe.width = 300;
await new Promise(resolve => {
iframe.onload = resolve;
iframe.srcdoc = `
<style>
${styleText}
</style>
<target></target>
`;
});
const target = iframe.contentDocument.querySelector('target');
assert_equals(getComputedStyle(target).color, 'rgb(255, 0, 0)', testCase['title']);
iframe.width = 500;
assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)', testCase['title']);
}, testCase['title']);
}
</script>
</body>
</html>

View file

@ -0,0 +1,154 @@
<!DOCTYPE html>
<title>Resolving @property name conflicts with cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target, #reference {
width: 100px;
height: 100px;
}
#reference {
background-color: green;
}
</style>
<div id="target"></div>
<div id="reference"></div>
<script>
// In all tests, background color of #target should be green, same as #reference
const testCases = [
{
title: '@property unlayered overrides layered',
style: `
#target {
background-color: var(--foo);
}
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
@layer {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
`
},
{
title: '@property override between layers',
style: `
@layer base, override;
#target {
background-color: var(--foo);
}
@layer override {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
}
@layer base {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
`
},
{
title: '@property override update with appended sheet 1',
style: `
@layer base, override;
#target {
background-color: var(--foo);
}
@layer override {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
}
`,
append: `
@layer base {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
`
},
{
title: '@property override update with appended sheet 2',
style: `
@layer base, override;
#target {
background-color: var(--foo);
}
@layer base {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: red;
}
}
`,
append: `
@layer override {
@property --foo {
syntax: '<color>';
inherits: false;
initial-value: green;
}
}
`
},
];
for (let testCase of testCases) {
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
var appendedStyle;
if (testCase['append']) {
document.body.offsetLeft; // Force style update
appendedStyle = document.createElement('style');
appendedStyle.appendChild(document.createTextNode(testCase['append']));
document.head.appendChild(appendedStyle);
}
test(function () {
assert_equals(getComputedStyle(target).backgroundColor,
getComputedStyle(reference).backgroundColor);
}, testCase['title']);
if (appendedStyle)
appendedStyle.remove();
documentStyle.remove();
}
</script>

View file

@ -0,0 +1,104 @@
<!DOCTYPE html>
<title>The CSSOM API for Cascade Layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layer-apis">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const testCases = [
{
style: `@layer foo { }`,
expectedNames: ['foo'],
title: 'Basic layer block name',
},
{
style: `@layer { }`,
expectedNames: [''],
title: 'Anonymous layer block name',
},
{
style: `
@layer foo;
`,
expectedNames: [['foo']],
title: 'Basic layer statement name',
},
{
style: `
@layer foo, bar;
`,
expectedNames: [['foo', 'bar']],
title: 'Layer statement with multiple names',
},
{
style: `
@layer outer {
@layer foo.bar { }
}
@layer outer.foo.bar { }
`,
expectedNames: ['outer', 'foo.bar', 'outer.foo.bar'],
title: 'Nested layer block names',
},
{
style: `
@layer outer {
@layer foo.bar, baz;
}
@layer outer.foo.bar, outer.baz;
`,
expectedNames: ['outer', ['foo.bar', 'baz'], ['outer.foo.bar', 'outer.baz']],
title: 'Nested layer statement name lists',
},
{
style: `
@import url('data:text/css,') layer;
`,
expectedNames: [''],
title: 'Import into anonymous layer',
},
{
style: `
@import url('data:text/css,') layer(foo);
`,
expectedNames: ['foo'],
title: 'Import into named layer',
},
{
style: `
@import url('data:text/css,');
`,
expectedNames: [null],
title: 'Import without layer',
},
];
for (let testCase of testCases) {
const style = document.createElement('style');
style.appendChild(document.createTextNode(testCase.style));
document.head.appendChild(style);
test(function () {
assert_implements(window.CSSLayerBlockRule);
assert_implements(window.CSSLayerStatementRule);
let index = 0;
function compareNames(ruleOrSheet) {
if (ruleOrSheet instanceof CSSLayerBlockRule)
assert_equals(ruleOrSheet.name, testCase.expectedNames[index++]);
else if (ruleOrSheet instanceof CSSImportRule)
assert_equals(ruleOrSheet.layerName, testCase.expectedNames[index++]);
else if (ruleOrSheet instanceof CSSLayerStatementRule)
assert_array_equals(ruleOrSheet.nameList, testCase.expectedNames[index++]);
if (ruleOrSheet.cssRules) {
for (let i = 0; i < ruleOrSheet.cssRules.length; ++i)
compareNames(ruleOrSheet.cssRules.item(i));
}
}
compareNames(style.sheet);
assert_equals(index, testCase.expectedNames.length);
}, testCase.title);
style.remove();
}
</script>

View file

@ -0,0 +1,183 @@
<!DOCTYPE html>
<title>Resolving @scroll-timeline name conflicts with cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<style>
#scroller {
overflow: scroll;
width: 100px;
height: 100px;
}
#scroller div {
height: 200px;
}
@keyframes expand {
from { width: 100px; }
to { width: 200px; }
}
#target, #reference {
height: 100px;
}
#reference {
width: 150px;
}
#target {
animation: expand 10s linear;
height: 100px;
}
</style>
<div id="scroller">
<div></div>
</div>
<div id="target"></div>
<div id="reference"></div>
<script>
// In all tests, width of #target should be 150px, same as #reference
const testCases = [
{
title: '@scroll-timeline unlayered overrides layered',
style: `
#target {
animation-timeline: timeline;
}
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 50px;
}
@layer {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 100px;
}
}
`
},
{
title: '@scroll-timeline override between layers',
style: `
@layer base, override;
#target {
animation-timeline: timeline;
}
@layer override {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 50px;
}
}
@layer base {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 100px;
}
}
`
},
{
title: '@scroll-timeline override update with appended sheet 1',
style: `
@layer base, override;
#target {
animation-timeline: timeline;
}
@layer override {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 50px;
}
}
`,
append: `
@layer base {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 100px;
}
}
`
},
{
title: '@scroll-timeline override update with appended sheet 2',
style: `
@layer base, override;
#target {
animation-timeline: timeline;
}
@layer base {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 100px;
}
}
`,
append: `
@layer override {
@scroll-timeline timeline {
source: selector(#scroller);
start: 0px;
end: 50px;
}
}
`
},
];
for (let testCase of testCases) {
promise_test(async function() {
assert_true(
CSS.supports('animation-timeline', 'foo'),
'This test requires @scroll-timeline support');
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
var appendedStyle;
if (testCase['append']) {
document.body.offsetLeft; // Force style update
appendedStyle = document.createElement('style');
appendedStyle.appendChild(document.createTextNode(testCase['append']));
document.head.appendChild(appendedStyle);
}
scroller.scrollTop = 25;
await waitForNextFrame();
assert_equals(getComputedStyle(target).width,
getComputedStyle(reference).width);
if (appendedStyle)
appendedStyle.remove();
documentStyle.remove();
}, testCase['title']);
}
</script>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<title>::slotted rules should be associated with the correct cascade layers</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="host">
<div id="target"></target>
</div>
<script>
const host = document.getElementById('host');
host.attachShadow({mode: 'open'}).innerHTML = `
<style>
@layer {
::slotted(*) {
background-color: green !important;
}
}
::slotted(*) {
background-color: red !important;
}
</style>
<slot></slot>
`;
</script>

View file

@ -0,0 +1,190 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: Empty layer statements before import rules</title>
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-cascade-5/#layering">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="target"></div>
<div id="reference" style="color: green"></div>
<script>
// In all test cases, the 'color' property value of #target should be green.
const testCases = [
{
title: 'length and item',
style: `
@layer first, second;
@import url(data:text/css,);
@layer second {
#target { color: green; }
}
@layer first {
#target { color: red; }
}
`,
operations: function(sheet) {
assert_equals(sheet.cssRules.length, 4);
assert_equals(sheet.cssRules.item(0).cssText, '@layer first, second;');
assert_equals(sheet.cssRules.item(1).cssText, `@import url("data:text/css,");`);
assert_equals(sheet.cssRules.item(2).cssText,
'@layer second {\n #target { color: green; }\n}');
assert_equals(sheet.cssRules.item(3).cssText,
'@layer first {\n #target { color: red; }\n}');
}
},
{
title: 'insertRule before imports',
style: `
@import url(data:text/css,);
@layer second {
#target { color: green; }
}
@layer first {
#target { color: red; }
}
`,
operations: function(sheet) {
sheet.insertRule('@layer first, second', 0);
}
},
{
title: 'insertRule after imports',
style: `
@layer first, second;
@import url(data:text/css,);
@layer first {
#target { color: red; }
}
`,
operations: function(sheet) {
sheet.insertRule('@layer second { #target { color: green; } }', 2);
}
},
{
title: 'insert other rules to pre-import layer statements fails',
style: `
@layer first, second;
@import url(data:text/css,);
@layer second {
#target { color: green; }
}
@layer first {
#target { color: red; }
}
`,
operations: function(sheet) {
assert_throws_dom('HierarchyRequestError',
() => sheet.insertRule('#target { color: red !important; }', 0));
assert_throws_dom('HierarchyRequestError',
() => sheet.insertRule('#target { color: red !important; }', 1));
}
},
{
title: 'insert other rules before the first layer statement without imports',
style: `
@layer first, second;
@layer second {
#target { color: red !important; }
}
`,
operations: function(sheet) {
sheet.insertRule(`@layer first {
#target { color: green !important; }
}`, 0);
}
},
{
title: 'deleteRule before imports',
style: `
@layer second, first;
@import url(data:text/css,);
@layer first {
#target { color: red; }
}
@layer second {
#target { color: green; }
}
`,
operations: function(sheet) {
sheet.deleteRule(0);
}
},
{
title: 'deleteRule after imports',
style: `
@layer first, second;
@import url(data:text/css,);
@layer second {
#target { color: green; }
}
@layer first {
#target { color: red; }
}
#target {
color: red;
}
`,
operations: function(sheet) {
sheet.deleteRule(4);
}
},
{
title: 'replaceSync clears stale layer statements',
style: `
@layer second, first;
@layer second {
#target { color: green; }
}
@layer first {
#target { color: red; }
}
`,
operations: function(sheet) {
sheet.replaceSync(`
@layer first {
#target { color: red; }
}
@layer second {
#target { color: green; }
}
`);
},
constructedStyleSheet: true
}
];
const target = document.getElementById('target');
const reference = document.getElementById('reference');
for (let testCase of testCases) {
promise_test(async t => {
let styleElement;
let sheet;
if (!testCase.constructedStyleSheet) {
styleElement = document.createElement('style');
styleElement.textContent = testCase.style;
await new Promise(resolve => {
styleElement.onload = resolve;
styleElement.onerror = resolve;
document.head.append(styleElement);
});
sheet = styleElement.sheet;
} else {
sheet = new CSSStyleSheet();
sheet.replaceSync(testCase.style);
document.adoptedStyleSheets = [sheet];
}
try {
testCase.operations(sheet);
assert_equals(getComputedStyle(target).color, getComputedStyle(reference).color);
} finally {
if (styleElement)
styleElement.remove();
document.adoptedStyleSheets = [];
}
}, testCase.title);
}
</script>

View file

@ -0,0 +1,18 @@
<!doctype html>
<title>Test important style in anonymous layers with stylesheet sharing</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="layer-stylesheet-sharing-ref.html">
<style>
target {
display: block;
width: 100px;
height: 100px;
}
</style>
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green !important}}">
<style>
@layer A { target { background-color: red !important} }
</style>
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green !important}}">
<target></target>

View file

@ -0,0 +1,10 @@
<!doctype html>
<style>
target {
display: block;
width: 100px;
height: 100px;
background-color: green;
}
</style>
<target></target>

View file

@ -0,0 +1,20 @@
<!doctype html>
<title>Test anonymous layers with stylesheet sharing</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1730123">
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="match" href="layer-stylesheet-sharing-ref.html">
<style>
target {
display: block;
width: 100px;
height: 100px;
}
</style>
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green}}">
<style>
@layer A { target { background-color: red } }
</style>
<link rel=stylesheet href="data:text/css,@layer{target{background-color:green}}">
<target></target>

View file

@ -0,0 +1,60 @@
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#cascade-sort">
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#target, #reference {
width: 100px;
height: 100px;
}
#reference {
background-color: green;
}
</style>
<div id="target"></div>
<div id="reference"></div>
<script>
// In all tests, #target should have green background color, same as #reference
const testCases = [
{
title: 'Normal inline style > normal layered style',
style: '@layer { #target { background-color: red; }}',
inlineStyle: 'background-color: green'
},
{
title: 'Normal inline style < important layered style',
style: '@layer { #target { background-color: green !important; }}',
inlineStyle: 'background-color: red'
},
{
title: 'Important inline style > normal layered style',
style: '@layer { #target { background-color: red; }}',
inlineStyle: 'background-color: green !important'
},
{
title: 'Important inline style > important layered style',
style: '@layer { #target { background-color: red !important; }}',
inlineStyle: 'background-color: green !important'
},
];
for (let testCase of testCases) {
var documentStyle = document.createElement('style');
documentStyle.appendChild(document.createTextNode(testCase['style']));
document.head.appendChild(documentStyle);
target.style = testCase['inlineStyle'];
test(function () {
assert_equals(getComputedStyle(target).backgroundColor,
getComputedStyle(reference).backgroundColor);
}, testCase['title']);
documentStyle.remove();
}
</script>

View file

@ -0,0 +1,79 @@
<!doctype html>
<meta charset="utf-8">
<title>@import rule with layer parsing / serialization</title>
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#at-import">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function setupSheet(rule) {
const style = document.createElement("style");
document.head.append(style);
const {sheet} = style;
const {cssRules} = sheet;
assert_equals(cssRules.length, 0, "Sheet should have no rules");
sheet.insertRule(rule);
assert_equals(cssRules.length, 1, "Sheet should have 1 rule");
return {sheet, cssRules};
}
function test_valid_layer_import(rule, serialized) {
if (serialized === undefined)
serialized = rule;
test(function() {
const {sheet, cssRules} = setupSheet(rule);
const serialization = cssRules[0].cssText;
assert_equals(serialization, serialized, 'serialization should be canonical');
const media = cssRules[0].media;
assert_equals(media.length, 0, 'layer() should be valid');
sheet.deleteRule(0);
assert_equals(cssRules.length, 0, 'Sheet should have no rule');
sheet.insertRule(serialization);
assert_equals(cssRules.length, 1, 'Sheet should have 1 rule');
assert_equals(cssRules[0].cssText, serialization, 'serialization should round-trip');
}, rule + ' should be a valid layered import rule');
}
function test_invalid_layer_import(rule) {
test(function() {
const {sheet, cssRules} = setupSheet(rule);
const media = cssRules[0].media;
assert_not_equals(media.length, 0,
'invalid layer declaration should be parsed as <general-enclosed> media query');
sheet.deleteRule(0);
assert_equals(cssRules.length, 0, 'Sheet should have no rule');
}, rule + ' should still be a valid import rule with an invalid layer declaration');
}
test_valid_layer_import('@import url("nonexist.css") layer;');
test_valid_layer_import('@import url("nonexist.css") layer(A);');
test_valid_layer_import('@import url("nonexist.css") layer(A.B);');
test_valid_layer_import('@import url(nonexist.css) layer;',
'@import url("nonexist.css") layer;');
test_valid_layer_import('@import url(nonexist.css) layer(A);',
'@import url("nonexist.css") layer(A);');
test_valid_layer_import('@import url(nonexist.css) layer(A.B);',
'@import url("nonexist.css") layer(A.B);');
test_valid_layer_import('@import "nonexist.css" layer;',
'@import url("nonexist.css") layer;');
test_valid_layer_import('@import "nonexist.css" layer(A);',
'@import url("nonexist.css") layer(A);');
test_valid_layer_import('@import "nonexist.css" layer(A.B);',
'@import url("nonexist.css") layer(A.B);');
test_invalid_layer_import('@import url("nonexist.css") layer();');
test_invalid_layer_import('@import url("nonexist.css") layer(A B);');
test_invalid_layer_import('@import url("nonexist.css") layer(A . B);');
test_invalid_layer_import('@import url("nonexist.css") layer(A, B, C);');
</script>

View file

@ -0,0 +1,25 @@
<!doctype html>
<meta charset="utf-8">
<title>@layer rule parsing / serialization</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#layering">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/parsing-testcommon.js"></script>
<script>
test_valid_rule("@layer A;");
test_valid_rule("@layer A, B, C;");
test_valid_rule("@layer A.A;");
test_valid_rule("@layer A, B.C.D, C;");
test_invalid_rule("@layer;");
test_invalid_rule("@layer A . A;");
test_valid_rule("@layer {\n}");
test_valid_rule("@layer A {\n}");
test_valid_rule("@layer A.B {\n}");
test_invalid_rule("@layer A . B {\n}");
test_invalid_rule("@layer A, B, C {\n}");
</script>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#preshint">
<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
.test {
height: 100px;
background-color: green;
}
#target1 {
width: 100px;
}
@layer {
#target3 {
width: 100px;
}
}
</style>
<img class=test id=target1 width=200>
<img class=test id=target2 width=200 style="width: 100px">
<img class=test id=target3 width=200>
<script>
test(() => {
assert_equals(getComputedStyle(target1).width, '100px');
}, 'Presentational hints have lower precedence than regular author style sheets');
test(() => {
assert_equals(getComputedStyle(target2).width, '100px');
}, 'Presentational hints have lower precedence than the style attribute');
test(() => {
assert_equals(getComputedStyle(target3).width, '100px');
}, 'Presentational hints have lower precedence than layered style');
</script>

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' from one explicit layer to another</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
}
@layer {
#target { background-color: green; }
}
@layer {
#target {
background-color: red;
background-color: revert-layer;
}
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' from the implicit outer layer to explicit</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
}
@layer {
#target { background-color: green; }
}
#target {
background-color: red;
background-color: revert-layer;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'all: revert-layer'</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
@layer {
#target {
width: 100px;
height: 100px;
background-color: green;
}
}
@layer {
#target {
width: 200px;
height: 200px;
background-color: red;
}
#target {
all: revert-layer;
}
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' to previous context</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
background-color: red;
background-color: revert-layer;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>
<script>
target.attachShadow({mode: 'open'}).innerHTML = `
<style>
:host {
background-color: green;
}
</style>
`;
</script>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: important 'revert-layer'</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
}
@layer {
#target { background-color: green; }
}
@layer {
#target {
background-color: red;
background-color: red !important;
background-color: revert-layer !important;
}
}
@layer {
#target {
background-color: red;
background-color: red !important;
}
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' reverts origin when no lower priority declarations in the same origin</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#outer {
background-color: red;
width: 100px;
height: 100px;
overflow: hidden;
}
#inner {
color: green;
background-color: green;
display: inline;
display: revert-layer; /* This should behave as 'revert', setting 'display' to 'block' */
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="outer">
<div id="inner">
This<br>
is<br>
filler<br>
text.<br>
This<br>
is<br>
filler<br>
text.
</div>
</div>

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' chain</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
}
@layer {
#target { background-color: green; }
}
@layer {
#target {
background-color: red;
background-color: revert-layer;
}
}
@layer {
#target {
background-color: red;
background-color: revert-layer;
}
}
@layer {
#target {
background-color: red;
background-color: revert-layer;
}
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' triggers a smooth transition</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@layer revert-to, revert-from;
@layer revert-from {
#target {
font-size: 10px;
transition: font-size 2s linear -1s;
}
#target.reverted {
font-size: revert-layer;
}
}
@layer revert-to {
#target { font-size: 20px; }
}
</style>
<div id="target"></div>
<script>
function raf() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
promise_test(async () => {
const target = document.getElementById('target');
getComputedStyle(target).getPropertyValue('font-size');
await raf();
target.classList.toggle('reverted');
const result = getComputedStyle(target).getPropertyValue('font-size');
assert_equals(result, '15px');
}, "'revert-layer' should revert font-size to 20px and trigger a smooth transition");
</script>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' from the style attribute to other style sheets</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
background-color: green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target" style="background-color: red; background-color: revert-layer"></div>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' from animation origin to author origin</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 150px;
height: 100px;
background-color: green;
animation: anim linear 2s -1s paused;
}
@keyframes anim {
from { width: 50px; }
to { width: revert-layer; }
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: 'revert-layer' from animation origin to author origin on custom property</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: var(--x);
--x: 150px;
height: 100px;
background-color: green;
animation: anim linear 2s -1s paused;
}
@property --x {
syntax: '<length>';
initial-value: 0px;
inherits: false;
}
@keyframes anim {
from { --x: 50px; }
to { --x: revert-layer; }
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target"></div>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<title>CSS Cascade Layers: important 'revert-layer' from the style attribute to other style sheets</title>
<link rel="help" href="https://drafts.csswg.org/css-cascade-5/#revert-layer">
<link rel="author" href="mailto:xiaochengh@chromium.org">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<style>
#target {
width: 100px;
height: 100px;
background-color: green !important;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="target" style="background-color: red !important; background-color: revert-layer !important"></div>

View file

@ -7,7 +7,6 @@
<link rel="help" href="https://www.w3.org/TR/css-cascade-4/#default">
<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="">
<meta name="assert" content="On a <div>, display:revert should compute to display:block per the default styles for <div>s in the UA stylesheet.">
<style>
#outer {

View file

@ -8,7 +8,6 @@
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#inherit-initial">
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#inherit-initial">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="">
<meta name="assert" content="color:unset is the same as color:inherit since color is an inherited property. background-color:unset is the same as background-color:initial since background-color is a non-inherited property.">
<style>
.square {

View file

@ -7,7 +7,6 @@
<link rel="help" href="http://www.w3.org/TR/css-cascade-3/#inherit-initial">
<link rel="help" href="http://www.w3.org/TR/css-cascade-4/#inherit-initial">
<link rel="match" href="reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="">
<meta name="assert" content="display:unset should be the same as display:initial since 'display' is not an inherited property. display:unset should be the same as display:inline since 'inline' is the initial value of 'display'.">
<style>
.square {