[css-nesting-ident] Enable relaxed syntax
I2S: https://groups.google.com/a/chromium.org/g/blink-dev/c/Ods7RbPlCjI
Fixed: 1427259
Change-Id: Icf6f434f9e993aee0b32d2046e096b1e183966b8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4917199
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1207558}
diff --git a/css/css-nesting/implicit-nesting-ident-recovery.html b/css/css-nesting/implicit-nesting-ident-recovery.html
new file mode 100644
index 0000000..f364832
--- /dev/null
+++ b/css/css-nesting/implicit-nesting-ident-recovery.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>CSS Nesting: Nesting, error recovery</title>
+<link rel="help" href="https://drafts.csswg.org/css-nesting-1/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #target1 {
+ display:block;
+ display:new-block;
+ color:green;
+ }
+ #target2 {
+ display:block;
+ display:hover {};
+ color:green;
+ }
+</style>
+<div id=target1>Green</div>
+<div id=target2>Green</div>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target1).color, 'rgb(0, 128, 0)');
+ }, 'Unknown declaration does not consume subsequent declaration');
+</script>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target2).color, 'rgb(0, 128, 0)');
+ }, 'Unknown declaration with blocks does not consume subsequent declaration');
+</script>
diff --git a/css/css-nesting/implicit-nesting-ident.html b/css/css-nesting/implicit-nesting-ident.html
new file mode 100644
index 0000000..d6d06b9
--- /dev/null
+++ b/css/css-nesting/implicit-nesting-ident.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>CSS Nesting: Implicit nesting (ident)</title>
+<link rel="help" href="https://drafts.csswg.org/css-nesting-1/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #main {
+ div {
+ color: green;
+ }
+ }
+</style>
+<div id=main>
+ <div id=target>
+ Green
+ </div>
+</main>
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)');
+ }, 'Nested rule starting with tag');
+</script>
diff --git a/css/css-syntax/custom-property-rule-ambiguity.html b/css/css-syntax/custom-property-rule-ambiguity.html
new file mode 100644
index 0000000..50728bc
--- /dev/null
+++ b/css/css-syntax/custom-property-rule-ambiguity.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<title>CSS Syntax: Rules that look like custom properties</title>
+<link rel="help" href="https://drafts.csswg.org/css-syntax/#consume-qualified-rule">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style id=stylesheet1>
+ .a { }
+ --x:hover { } /* Ambiguous "rule" */
+ .b { }
+</style>
+<script>
+ test(() => {
+ let rules = stylesheet1.sheet.rules;
+ assert_equals(rules.length, 2);
+ assert_equals(rules[0].selectorText, '.a');
+ assert_equals(rules[1].selectorText, '.b');
+ }, 'Rule that looks like a custom property declaration is ignored');
+</script>
+
+<!-- https://github.com/w3c/csswg-drafts/issues/9336 -->
+<style id=stylesheet2>
+ .a { }
+ --x:hover { ] } /* Ambiguous "rule" */
+ .b { }
+</style>
+<script>
+ test(() => {
+ let rules = stylesheet2.sheet.rules;
+ assert_equals(rules.length, 2);
+ assert_equals(rules[0].selectorText, '.a');
+ assert_equals(rules[1].selectorText, '.b');
+ }, 'Rule that looks like an invalid custom property declaration is ignored');
+</script>
+
+<style id=stylesheet3>
+ div {
+ .a { }
+ --x:hover { }
+ .b { }
+ }
+</style>
+<script>
+ test(() => {
+ let rules = stylesheet3.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].selectorText, 'div');
+ let div = rules[0];
+ let x = div.style.getPropertyValue('--x');
+ assert_equals(x, 'hover { }\n .b { }');
+ let childRules = div.cssRules;
+ assert_equals(childRules.length, 1);
+ assert_equals(childRules[0].selectorText, '.a');
+ }, 'Nested rule that looks like a custom property declaration');
+</script>
+
+<!-- https://github.com/w3c/csswg-drafts/issues/9336 -->
+
+<style id=stylesheet4>
+ div {
+ .a { }
+ --x:hover { ] }
+ .b { }
+ }
+</style>
+<script>
+ test(() => {
+ let rules = stylesheet4.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].selectorText, 'div');
+ let div = rules[0];
+ // There is no valid --x declaration, because mismatched ] is not allowed
+ // in custom properties.
+ let x = div.style.getPropertyValue('--x');
+ assert_equals(x, '');
+ // We should also not have restarted parsing as a nested style rule,
+ // and instead we should have "consumed the remnants of a bad declaration",
+ // which skips to the next semicolon (or end-of-block).
+ // So in other words, there should be no nested '.b.' child rule here.
+ let childRules = div.cssRules;
+ assert_equals(childRules.length, 1);
+ assert_equals(childRules[0].selectorText, '.a');
+ }, 'Nested rule that looks like an invalid custom property declaration');
+</script>
diff --git a/css/css-syntax/trailing-braces.html b/css/css-syntax/trailing-braces.html
new file mode 100644
index 0000000..ac2e8e6
--- /dev/null
+++ b/css/css-syntax/trailing-braces.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>CSS Syntax: trailing braces</title>
+<link rel="help" href="https://drafts.csswg.org/css-syntax-1/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id=style>
+ #target1 {
+ color:green;
+ color:red{};
+ color:red {};
+ }
+</style>
+<div id=target1>Green</div>
+<script>
+ test(() => {
+ let rules = style.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.color, 'green');
+ }, 'Trailing braces are not valid');
+</script>
diff --git a/css/css-syntax/var-with-blocks.html b/css/css-syntax/var-with-blocks.html
new file mode 100644
index 0000000..915a246
--- /dev/null
+++ b/css/css-syntax/var-with-blocks.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<title>CSS Syntax: {}-blocks in declaration values</title>
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/9317">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<!-- Standard properties -->
+
+<style id=plain_var>
+ .a {
+ color: rgb(2, 2, 2);
+ color:var(--x); /* Valid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = plain_var.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, 'var(--x)');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'Plain var()');
+</script>
+
+<style id=whole_value_block>
+ .a {
+ color: rgb(2, 2, 2);
+ color:{var(--x)}; /* Valid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = whole_value_block.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, '{var(--x)}');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'Whole-value block with var()');
+</script>
+
+<style id=whole_value_block_with_space>
+ .a {
+ color: rgb(2, 2, 2);
+ color: { var(--x) }; /* Valid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = whole_value_block_with_space.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, '{ var(--x) }');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'Whole-value block with var() (spaces)');
+</script>
+
+<style id=trailing_block>
+ .a {
+ color: rgb(2, 2, 2);
+ color:var(--x) { }; /* Invalid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = trailing_block.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, 'rgb(2, 2, 2)');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'Trailing block, leading var()');
+</script>
+
+<style id=leading_block>
+ .a {
+ color: rgb(2, 2, 2);
+ color:{ } var(--x); /* Invalid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = leading_block.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, 'rgb(2, 2, 2)');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'Leading block, trailing var()');
+</script>
+
+<style id=in_block_var_with_trailing_token>
+ .a {
+ color: rgb(2, 2, 2);
+ color:{ var(--x) } A; /* Invalid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = in_block_var_with_trailing_token.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, 'rgb(2, 2, 2)');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'In-block var() with trailing token');
+</script>
+
+<style id=in_block_var_with_leading_token>
+ .a {
+ color: rgb(2, 2, 2);
+ color:A { var(--x) }; /* Invalid */
+ background-color:rgb(1, 1, 1);
+ }
+</style>
+<script>
+ test(() => {
+ let rules = in_block_var_with_leading_token.sheet.rules;
+ assert_equals(rules.length, 1);
+ let declarations = rules[0].style;
+ assert_equals(declarations.color, 'rgb(2, 2, 2)');
+ assert_equals(declarations.backgroundColor, 'rgb(1, 1, 1)');
+ }, 'In-block var() with leading token');
+</script>
+
+<!-- Custom Properties -->
+
+<style id=plain_var_custom>
+ .a {
+ --y:var(--x); /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = plain_var_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), 'var(--x)');
+ }, 'Plain var() (custom property)');
+</script>
+
+<style id=whole_value_block_custom>
+ .a {
+ --y:{var(--x)}; /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = whole_value_block_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), '{var(--x)}');
+ }, 'Whole-value block with var() (custom property)');
+</script>
+
+<style id=whole_value_block_with_space_custom>
+ .a {
+ --y: { var(--x) }; /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = whole_value_block_with_space_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), '{ var(--x) }');
+ }, 'Whole-value block with var() (spaces, custom property)');
+</script>
+
+<style id=trailing_block_custom>
+ .a {
+ --y:var(--x) { }; /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = trailing_block_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), 'var(--x) { }');
+ }, 'Trailing block, leading var() (custom property)');
+</script>
+
+<style id=leading_block_custom>
+ .a {
+ --y:{ } var(--x); /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = leading_block_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), '{ } var(--x)');
+ }, 'Leading block, trailing var() (custom property)');
+</script>
+
+<style id=in_block_var_with_trailing_token_custom>
+ .a {
+ --y:{ var(--x) } A; /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = in_block_var_with_trailing_token_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), '{ var(--x) } A');
+ }, 'In-block var() with trailing token (custom property)');
+</script>
+
+<style id=in_block_var_with_leading_token_custom>
+ .a {
+ --y:A { var(--x) }; /* Valid */
+ }
+</style>
+<script>
+ test(() => {
+ let rules = in_block_var_with_leading_token_custom.sheet.rules;
+ assert_equals(rules.length, 1);
+ assert_equals(rules[0].style.getPropertyValue('--y'), 'A { var(--x) }');
+ }, 'In-block var() with leading token (custom property)');
+</script>