summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-syntax
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/css/css-syntax
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-syntax')
-rw-r--r--testing/web-platform/tests/css/css-syntax/META.yml4
-rw-r--r--testing/web-platform/tests/css/css-syntax/WEB_FEATURES.yml6
-rw-r--r--testing/web-platform/tests/css/css-syntax/anb-parsing.html125
-rw-r--r--testing/web-platform/tests/css/css-syntax/anb-serialization.html62
-rw-r--r--testing/web-platform/tests/css/css-syntax/at-rule-in-declaration-list.html76
-rw-r--r--testing/web-platform/tests/css/css-syntax/cdc-vs-ident-tokens.html28
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset-is-not-a-rule.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/.htaccess4
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/MANIFEST20
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16.htmlbin0 -> 1196 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16be.htmlbin0 -> 1206 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl-ascii-only.htmlbin0 -> 1198 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl.htmlbin0 -> 1188 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-charset-attribute-bogus.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-1250-charset-attribute-windows-1253.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus-charset-attribute-windows-1250.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16-ascii-only.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16be.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16.html23
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16be.html23
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus-at-charset-windows-1250.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-windows-1250-at-charset-windows-1253.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-no-decl.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-utf8-bom.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/page-windows-1252-http-windows-1251-css-utf8-bom.html17
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/MANIFEST15
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-bogus.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16-ascii-only.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16be.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16.cssbin0 -> 77 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16be.cssbin0 -> 77 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16.cssbin0 -> 52 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16be.cssbin0 -> 52 bytes
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css.headers1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css.headers1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css2
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css.headers1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/no-decl-ascii-only.css1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/no-decl.css1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css.headers1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom.css1
-rw-r--r--testing/web-platform/tests/css/css-syntax/charset/xml-stylesheet-page-windows-1251-charset-attribute-windows-1250.xhtml20
-rw-r--r--testing/web-platform/tests/css/css-syntax/custom-property-rule-ambiguity.html84
-rw-r--r--testing/web-platform/tests/css/css-syntax/decimal-points-in-numbers.html56
-rw-r--r--testing/web-platform/tests/css/css-syntax/declarations-trim-whitespace.html54
-rw-r--r--testing/web-platform/tests/css/css-syntax/escaped-eof.html46
-rw-r--r--testing/web-platform/tests/css/css-syntax/ident-three-code-points.html73
-rw-r--r--testing/web-platform/tests/css/css-syntax/inclusive-ranges.html60
-rw-r--r--testing/web-platform/tests/css/css-syntax/input-preprocessing.html46
-rw-r--r--testing/web-platform/tests/css/css-syntax/missing-semicolon-ref.html9
-rw-r--r--testing/web-platform/tests/css/css-syntax/missing-semicolon.html13
-rw-r--r--testing/web-platform/tests/css/css-syntax/non-ascii-codepoints.html81
-rw-r--r--testing/web-platform/tests/css/css-syntax/serialize-consecutive-tokens.html121
-rw-r--r--testing/web-platform/tests/css/css-syntax/support/missing-semicolon.css5
-rw-r--r--testing/web-platform/tests/css/css-syntax/trailing-braces.html20
-rw-r--r--testing/web-platform/tests/css/css-syntax/unclosed-constructs.html36
-rw-r--r--testing/web-platform/tests/css/css-syntax/unclosed-url-at-eof.html29
-rw-r--r--testing/web-platform/tests/css/css-syntax/unicode-range-selector.html20
-rw-r--r--testing/web-platform/tests/css/css-syntax/urange-parsing.html175
-rw-r--r--testing/web-platform/tests/css/css-syntax/url-whitespace-consumption.html32
-rw-r--r--testing/web-platform/tests/css/css-syntax/var-with-blocks.html219
-rw-r--r--testing/web-platform/tests/css/css-syntax/whitespace.html62
70 files changed, 1908 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-syntax/META.yml b/testing/web-platform/tests/css/css-syntax/META.yml
new file mode 100644
index 0000000000..359219c099
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/META.yml
@@ -0,0 +1,4 @@
+spec: https://drafts.csswg.org/css-syntax/
+suggested_reviewers:
+ - gregwhitworth
+ - tabatkins
diff --git a/testing/web-platform/tests/css/css-syntax/WEB_FEATURES.yml b/testing/web-platform/tests/css/css-syntax/WEB_FEATURES.yml
new file mode 100644
index 0000000000..5515467061
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/WEB_FEATURES.yml
@@ -0,0 +1,6 @@
+features:
+- name: nesting
+ files:
+ - custom-property-rule-ambiguity.html
+ - trailing-braces.html
+ - var-with-blocks.html
diff --git a/testing/web-platform/tests/css/css-syntax/anb-parsing.html b/testing/web-platform/tests/css/css-syntax/anb-parsing.html
new file mode 100644
index 0000000000..7fcc06e2c7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/anb-parsing.html
@@ -0,0 +1,125 @@
+<!doctype html>
+<title>An+B Parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { color: blue; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#the-anb-type">
+
+<script>
+
+function roundtripANB(str) {
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.selectorText = "foo";
+ rule.selectorText = `:nth-child(${str})`;
+ // Check for parse error.
+ if(rule.selectorText == "foo") return "parse error";
+ return rule.selectorText.slice(11, -1);
+}
+function testANB(input, expected) {
+ test(()=>{
+ assert_equals(roundtripANB(input), expected);
+ }, `"${input}" becomes "${expected}"`);
+}
+
+/* Just going down all the syntax clauses one-by-one */
+// odd | even |
+testANB("odd", "2n+1");
+testANB("even", "2n");
+// <integer> |
+testANB("1", "1");
+testANB("+1", "1");
+testANB("-1", "-1");
+//
+// <n-dimension> |
+testANB("5n", "5n");
+testANB("5N", "5n");
+// '+'?† n |
+testANB("+n", "n");
+testANB("n", "n");
+testANB("N", "n");
+testANB("+ n", "parse error");
+// -n |
+testANB("-n", "-n");
+testANB("-N", "-n");
+//
+// <ndashdigit-dimension> |
+testANB("5n-5", "5n-5");
+// '+'?† <ndashdigit-ident> |
+testANB("+n-5", "n-5");
+testANB("n-5", "n-5");
+testANB("+ n-5", "parse error");
+// <dashndashdigit-ident> |
+testANB("-n-5", "-n-5");
+//
+// <n-dimension> <signed-integer> |
+testANB("5n +5", "5n+5");
+testANB("5n -5", "5n-5");
+// '+'?† n <signed-integer> |
+testANB("+n +5", "n+5");
+testANB("n +5", "n+5");
+testANB("+n -5", "n-5");
+testANB("+ n +5", "parse error");
+testANB("n 5", "parse error");
+// -n <signed-integer> |
+testANB("-n +5", "-n+5");
+testANB("-n -5", "-n-5");
+testANB("-n 5", "parse error");
+//
+// <ndash-dimension> <signless-integer> |
+testANB("5n- 5", "5n-5");
+testANB("5n- -5", "parse error");
+testANB("5n- +5", "parse error");
+testANB("-5n- 5", "-5n-5");
+// '+'?† n- <signless-integer> |
+testANB("+n- 5", "n-5");
+testANB("n- 5", "n-5");
+testANB("+ n- 5", "parse error");
+testANB("n- +5", "parse error");
+testANB("n- -5", "parse error");
+// -n- <signless-integer> |
+testANB("-n- 5", "-n-5");
+testANB("-n- +5", "parse error");
+testANB("-n- -5", "parse error");
+//
+// <n-dimension> ['+' | '-'] <signless-integer>
+testANB("5n + 5", "5n+5");
+testANB("5n - 5", "5n-5");
+testANB("5n + +5", "parse error");
+testANB("5n + -5", "parse error");
+testANB("5n - +5", "parse error");
+testANB("5n - -5", "parse error");
+// '+'?† n ['+' | '-'] <signless-integer> |
+testANB("+n + 5", "n+5");
+testANB("n + 5", "n+5");
+testANB("+ n + 5", "parse error");
+testANB("+n - 5", "n-5");
+testANB("+n + +5", "parse error");
+testANB("+n + -5", "parse error");
+testANB("+n - +5", "parse error");
+testANB("+n - -5", "parse error");
+// -n ['+' | '-'] <signless-integer>
+testANB("-n + 5", "-n+5");
+testANB("-n - 5", "-n-5");
+testANB("-n + +5", "parse error");
+testANB("-n + -5", "parse error");
+testANB("-n - +5", "parse error");
+testANB("-n - -5", "parse error");
+
+/* Swapped ordering is invalid */
+testANB("1 - n", "parse error");
+testANB("0 - n", "parse error");
+testANB("-1 + n", "parse error");
+
+/* Odd space usage */
+testANB("2 n + 2", "parse error");
+testANB("- 2n", "parse error");
+testANB("+ 2n", "parse error");
+testANB("+2 n", "parse error");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/anb-serialization.html b/testing/web-platform/tests/css/css-syntax/anb-serialization.html
new file mode 100644
index 0000000000..787700cebf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/anb-serialization.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>An+B Serialization</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { color: blue; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#serializing-anb">
+
+<script>
+
+function roundtripANB(str) {
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.selectorText = "foo";
+ rule.selectorText = `:nth-child(${str})`;
+ // Check for parse error.
+ if(rule.selectorText == "foo") return "parse error";
+ return rule.selectorText.slice(11, -1);
+}
+function testANB(input, expected) {
+ test(()=>{
+ assert_equals(roundtripANB(input), expected);
+ }, `"${input}" becomes "${expected}"`);
+}
+
+/* A is 0, or omitted */
+testANB("1", "1");
+testANB("+1", "1");
+testANB("-1", "-1");
+testANB("0n + 0", "0");
+testANB("0n + 1", "1");
+testANB("0n - 1", "-1");
+
+/* A is 1 */
+testANB("1n", "n");
+testANB("1n - 0", "n");
+testANB("1n + 1", "n+1");
+testANB("1n - 1", "n-1");
+
+/* A is -1 */
+testANB("-1n", "-n");
+testANB("-1n - 0", "-n");
+testANB("-1n + 1", "-n+1");
+testANB("-1n - 1", "-n-1");
+
+/* A is implied via + or - */
+testANB("+n+1", "n+1");
+testANB("-n-1", "-n-1");
+
+/* B is 0 */
+testANB("n + 0", "n");
+testANB("n - 0", "n");
+
+/* A & B both nonzero */
+testANB("2n + 2", "2n+2");
+testANB("-2n - 2", "-2n-2");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/at-rule-in-declaration-list.html b/testing/web-platform/tests/css/css-syntax/at-rule-in-declaration-list.html
new file mode 100644
index 0000000000..f40975d27e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/at-rule-in-declaration-list.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<title>CSS Syntax Test: handle at-rules in declaration lists</title>
+<link rel="help" href="https://drafts.csswg.org/css-syntax/#consume-list-of-declarations">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style id="test_sheet">
+</style>
+<script>
+ function parseRule(rule_text) {
+ let sheet = test_sheet.sheet;
+ if (sheet.cssRules.length != 0)
+ sheet.deleteRule(0);
+ sheet.insertRule(rule_text);
+ return sheet.cssRules[0];
+ }
+
+ test(() => {
+ let rule = parseRule(`
+ div {
+ @at {}
+ color: green;
+ }
+ `);
+ assert_equals(rule.style.color, "green");
+ }, "Allow @-rule with block inside style rule");
+
+ test(() => {
+ let rule = parseRule(`
+ div {
+ @at at;
+ color: green;
+ }
+ `);
+ assert_equals(rule.style.color, "green");
+ }, "Allow @-rule with semi-colon inside style rule");
+
+ test(() => {
+ let rule = parseRule(`
+ @page {
+ @at {}
+ margin-top: 20px;
+ }
+ `);
+ assert_equals(rule.style.marginTop, "20px");
+ }, "Allow @-rule with block inside page rule");
+
+ test(() => {
+ let rule = parseRule(`
+ @page {
+ @at at;
+ margin-top: 20px;
+ }
+ `);
+ assert_equals(rule.style.marginTop, "20px");
+ }, "Allow @-rule with semi-colon inside page rule");
+
+ test(() => {
+ let rule = parseRule(`
+ @font-face {
+ @at {}
+ font-family: myfont;
+ }
+ `);
+ assert_equals(rule.style.fontFamily, "myfont");
+ }, "Allow @-rule with block inside font-face rule");
+
+ test(() => {
+ let rule = parseRule(`
+ @font-face {
+ @at at;
+ font-family: myfont;
+ }
+ `);
+ assert_equals(rule.style.fontFamily, "myfont");
+ }, "Allow @-rule with semi-colon inside font-face rule");
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/cdc-vs-ident-tokens.html b/testing/web-platform/tests/css/css-syntax/cdc-vs-ident-tokens.html
new file mode 100644
index 0000000000..02cfbe11ae
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/cdc-vs-ident-tokens.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>CDC versus Ident Token</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+-->
+
+--foo { color: blue; }
+
+</style>
+
+<meta name=author content="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-token">
+
+<!--
+The ordering of the checks in the HYPHEN-MINUS step is important;
+if you get it wrong, ident-token can swallow cdc-token.
+-->
+
+<script>
+
+test(()=>{
+ const rule = document.styleSheets[0].cssRules[0];
+ assert_equals(rule.selectorText, "--foo");
+}, "CDC-token is properly emitted, and not parsed as an ident.");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset-is-not-a-rule.html b/testing/web-platform/tests/css/css-syntax/charset-is-not-a-rule.html
new file mode 100644
index 0000000000..ff8d3298b6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset-is-not-a-rule.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>@charset isn't a valid rule and should be dropped</title>
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#charset-rule">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+@charset "utf-8";
+@charset "utf-8";
+foo { color: blue; }
+@charset "utf-8";
+</style>
+<script>
+test(()=>{
+ assert_equals(document.styleSheets[0].cssRules.length, 1)
+}, "@charset isn't a valid rule and shouldn't show up in the OM");
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/.htaccess b/testing/web-platform/tests/css/css-syntax/charset/.htaccess
new file mode 100644
index 0000000000..e14b20d395
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/.htaccess
@@ -0,0 +1,4 @@
+IndexOptions NameWidth=*
+AddDefaultCharset Off
+AddCharset bogus .bogus
+AddCharset windows-1250 .windows1250
diff --git a/testing/web-platform/tests/css/css-syntax/charset/MANIFEST b/testing/web-platform/tests/css/css-syntax/charset/MANIFEST
new file mode 100644
index 0000000000..4bc83f6e70
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/MANIFEST
@@ -0,0 +1,20 @@
+page-utf16-css-bomless-utf16be.html
+page-utf16-css-bomless-utf16.html
+page-utf16-css-no-decl-ascii-only.html
+page-utf16-css-no-decl.html
+page-windows-1251-charset-attribute-bogus.html
+page-windows-1251-css-at-charset-1250-charset-attribute-windows-1253.html
+page-windows-1251-css-at-charset-bogus-charset-attribute-windows-1250.html
+page-windows-1251-css-at-charset-bogus.html
+page-windows-1251-css-at-charset-utf16-ascii-only.html
+page-windows-1251-css-at-charset-utf16be.html
+page-windows-1251-css-at-charset-utf16.html
+page-windows-1251-css-at-charset-windows-1250-in-utf16be.html
+page-windows-1251-css-at-charset-windows-1250-in-utf16.html
+page-windows-1251-css-http-bogus-at-charset-windows-1250.html
+page-windows-1251-css-http-bogus.html
+page-windows-1251-css-http-windows-1250-at-charset-windows-1253.html
+page-windows-1251-css-no-decl.html
+page-windows-1251-css-utf8-bom.html
+dir support
+xml-stylesheet-page-windows-1251-charset-attribute-windows-1250.xhtml
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16.html b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16.html
new file mode 100644
index 0000000000..f98bc211b1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16.html
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16be.html b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16be.html
new file mode 100644
index 0000000000..1d4728322d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-bomless-utf16be.html
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl-ascii-only.html b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl-ascii-only.html
new file mode 100644
index 0000000000..56e09ace11
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl-ascii-only.html
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl.html b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl.html
new file mode 100644
index 0000000000..2ff52cf5d7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-utf16-css-no-decl.html
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-charset-attribute-bogus.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-charset-attribute-bogus.html
new file mode 100644
index 0000000000..939143a763
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-charset-attribute-bogus.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, charset attribute bogus</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/no-decl.css" charset="bogus">
+<div id=log></div>
+<div id=&#x0418;></div>
+<script>
+var elm = document.getElementById('\u0418');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-1250-charset-attribute-windows-1253.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-1250-charset-attribute-windows-1253.html
new file mode 100644
index 0000000000..df51dfa30c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-1250-charset-attribute-windows-1253.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, @charset windows-1250, charset attribute windows-1253</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-windows-1250.css" charset=windows-1253>
+<div id=log></div>
+<div id=&#x010C;></div>
+<script>
+var elm = document.getElementById('\u010C');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus-charset-attribute-windows-1250.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus-charset-attribute-windows-1250.html
new file mode 100644
index 0000000000..7521e85afe
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus-charset-attribute-windows-1250.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset bogus, charset attribute windows-1250</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-bogus.css" charset=windows-1250>
+<div id=log></div>
+<div id=&#x010C;></div>
+<script>
+var elm = document.getElementById('\u010C');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus.html
new file mode 100644
index 0000000000..2d7c3ef611
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-bogus.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, @charset bogus</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-bogus.css">
+<div id=log></div>
+<div id=&#x0418;></div>
+<script>
+var elm = document.getElementById('\u0418');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16-ascii-only.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16-ascii-only.html
new file mode 100644
index 0000000000..d65afd31f5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16-ascii-only.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset utf-16 (ASCII only)</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-utf16-ascii-only.css">
+<div id=log></div>
+<div id=foo></div>
+<script>
+var elm = document.getElementById('foo');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16.html
new file mode 100644
index 0000000000..04c1270e0c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset utf-16</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-utf16.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<script>
+var elm = document.getElementById('\ufffd');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16be.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16be.html
new file mode 100644
index 0000000000..4b2d48dbc1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-utf16be.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset utf-16be</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-utf16be.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<script>
+var elm = document.getElementById('\ufffd');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16.html
new file mode 100644
index 0000000000..463e3778f6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset windows-1250 in utf-16</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-windows-1250-in-utf16.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<div id=&#x0418;></div>
+<div id=&#x010c;></div>
+<script>
+var elm_fffd = document.getElementById('\ufffd');
+var elm_0418 = document.getElementById('\u0418');
+var elm_010c = document.getElementById('\u010c');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm_fffd, '').visibility, 'visible', 'selector U+FFFD matched (utf-8)');
+ assert_equals(getComputedStyle(elm_0418, '').visibility, 'hidden', 'selector U+0418 did not match (windows-1251)');
+ assert_equals(getComputedStyle(elm_010c, '').visibility, 'visible', 'selector U+010C matched (windows-1250)');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16be.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16be.html
new file mode 100644
index 0000000000..7de3f37d9b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-at-charset-windows-1250-in-utf16be.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS @charset windows-1250 in utf-16be</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/at-charset-windows-1250-in-utf16be.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<div id=&#x0418;></div>
+<div id=&#x010c;></div>
+<script>
+var elm_fffd = document.getElementById('\ufffd');
+var elm_0418 = document.getElementById('\u0418');
+var elm_010c = document.getElementById('\u010c');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm_fffd, '').visibility, 'visible', 'selector U+FFFD matched (utf-8)');
+ assert_equals(getComputedStyle(elm_0418, '').visibility, 'hidden', 'selector U+0418 did not match (windows-1251)');
+ assert_equals(getComputedStyle(elm_010c, '').visibility, 'visible', 'selector U+010C matched (windows-1250)');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus-at-charset-windows-1250.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus-at-charset-windows-1250.html
new file mode 100644
index 0000000000..2fcc56bca9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus-at-charset-windows-1250.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS HTTP bogus, @charset windows-1250</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/http-bogus-at-charset-windows-1250.bogus.css">
+<div id=log></div>
+<div id=&#x010C;></div>
+<script>
+var elm = document.getElementById('\u010C');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus.html
new file mode 100644
index 0000000000..e26501b9eb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-bogus.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS HTTP bogus</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/http-bogus.bogus.css">
+<div id=log></div>
+<div id=&#x0418;></div>
+<script>
+var elm = document.getElementById('\u0418');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-windows-1250-at-charset-windows-1253.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-windows-1250-at-charset-windows-1253.html
new file mode 100644
index 0000000000..3658e445f8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-http-windows-1250-at-charset-windows-1253.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS HTTP windows-1250, @charset windows-1253</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/http-windows-1250-at-charset-windows-1253.windows1250.css">
+<div id=log></div>
+<div id=&#x010C;></div>
+<script>
+var elm = document.getElementById('\u010C');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-no-decl.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-no-decl.html
new file mode 100644
index 0000000000..288f01efbd
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-no-decl.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS no decl</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/no-decl.css">
+<div id=log></div>
+<div id=&#x0418;></div>
+<script>
+var elm = document.getElementById('\u0418');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-utf8-bom.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-utf8-bom.html
new file mode 100644
index 0000000000..2c32f09151
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1251-css-utf8-bom.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1251, CSS UTF-8 BOM</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1251>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/utf8-bom.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<script>
+var elm = document.getElementById('\ufffd');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/page-windows-1252-http-windows-1251-css-utf8-bom.html b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1252-http-windows-1251-css-utf8-bom.html
new file mode 100644
index 0000000000..6a65942e16
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/page-windows-1252-http-windows-1251-css-utf8-bom.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS charset: page windows-1252, CSS-HTTP windows-1251, CSS UTF-8 BOM</title>
+<link rel=help href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding">
+<meta charset=windows-1252>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel=stylesheet href="support/utf8-bom-http-windows-1251.css">
+<div id=log></div>
+<div id=&#xfffd;></div>
+<script>
+var elm = document.getElementById('\ufffd');
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/MANIFEST b/testing/web-platform/tests/css/css-syntax/charset/support/MANIFEST
new file mode 100644
index 0000000000..9688e1f88d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/MANIFEST
@@ -0,0 +1,15 @@
+support at-charset-bogus.css
+support at-charset-utf16-ascii-only.css
+support at-charset-utf16be.css
+support at-charset-utf16.css
+support at-charset-windows-1250.css
+support at-charset-windows-1250-in-utf16be.css
+support at-charset-windows-1250-in-utf16.css
+support bomless-utf16be.css
+support bomless-utf16.css
+support http-bogus-at-charset-windows-1250.bogus.css
+support http-bogus.bogus.css
+support http-windows-1250-at-charset-windows-1253.windows1250.css
+support no-decl-ascii-only.css
+support no-decl.css
+support utf8-bom.css
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-bogus.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-bogus.css
new file mode 100644
index 0000000000..50f9b7779a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-bogus.css
@@ -0,0 +1,2 @@
+@charset "bogus";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16-ascii-only.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16-ascii-only.css
new file mode 100644
index 0000000000..e7f067e066
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16-ascii-only.css
@@ -0,0 +1,2 @@
+@charset "utf-16";
+#foo { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16.css
new file mode 100644
index 0000000000..e7dbf5784f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16.css
@@ -0,0 +1,2 @@
+@charset "utf-16";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16be.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16be.css
new file mode 100644
index 0000000000..cb51b419dc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-utf16be.css
@@ -0,0 +1,2 @@
+@charset "utf-16be";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16.css
new file mode 100644
index 0000000000..1132bfd193
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16.css
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16be.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16be.css
new file mode 100644
index 0000000000..38bb069784
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250-in-utf16be.css
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250.css b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250.css
new file mode 100644
index 0000000000..6c06db0e9c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/at-charset-windows-1250.css
@@ -0,0 +1,2 @@
+@charset "windows-1250";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16.css b/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16.css
new file mode 100644
index 0000000000..b5399b74bf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16.css
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16be.css b/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16be.css
new file mode 100644
index 0000000000..eaadad0135
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/bomless-utf16be.css
Binary files differ
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css
new file mode 100644
index 0000000000..6c06db0e9c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css
@@ -0,0 +1,2 @@
+@charset "windows-1250";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css.headers b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css.headers
new file mode 100644
index 0000000000..f08dbd94d1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus-at-charset-windows-1250.bogus.css.headers
@@ -0,0 +1 @@
+Content-Type: text/css; charset=bogus
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css
new file mode 100644
index 0000000000..ba2371f8b0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css
@@ -0,0 +1 @@
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css.headers b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css.headers
new file mode 100644
index 0000000000..f08dbd94d1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-bogus.bogus.css.headers
@@ -0,0 +1 @@
+Content-Type: text/css; charset=bogus
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css b/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css
new file mode 100644
index 0000000000..987dff3155
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css
@@ -0,0 +1,2 @@
+@charset "windows-1253";
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css.headers b/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css.headers
new file mode 100644
index 0000000000..c0993d2101
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/http-windows-1250-at-charset-windows-1253.windows1250.css.headers
@@ -0,0 +1 @@
+Content-Type: text/css; charset=windows-1250
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/no-decl-ascii-only.css b/testing/web-platform/tests/css/css-syntax/charset/support/no-decl-ascii-only.css
new file mode 100644
index 0000000000..0736f81397
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/no-decl-ascii-only.css
@@ -0,0 +1 @@
+#foo { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/no-decl.css b/testing/web-platform/tests/css/css-syntax/charset/support/no-decl.css
new file mode 100644
index 0000000000..ba2371f8b0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/no-decl.css
@@ -0,0 +1 @@
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css
new file mode 100644
index 0000000000..1dbf5cf2fc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css
@@ -0,0 +1 @@
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css.headers b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css.headers
new file mode 100644
index 0000000000..9a67b0fea4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom-http-windows-1251.css.headers
@@ -0,0 +1 @@
+Content-Type: text/css; charset=windows-1251
diff --git a/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom.css b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom.css
new file mode 100644
index 0000000000..1dbf5cf2fc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/support/utf8-bom.css
@@ -0,0 +1 @@
+# { visibility:hidden } \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/charset/xml-stylesheet-page-windows-1251-charset-attribute-windows-1250.xhtml b/testing/web-platform/tests/css/css-syntax/charset/xml-stylesheet-page-windows-1251-charset-attribute-windows-1250.xhtml
new file mode 100644
index 0000000000..512df7a0ba
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/charset/xml-stylesheet-page-windows-1251-charset-attribute-windows-1250.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<?xml-stylesheet href="support/no-decl.css" charset="windows-1250"?>
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<title>CSS charset: page windows-1251, charset attribute bogus</title>
+<link rel="help" href="https://drafts.csswg.org/css-syntax-3/#determine-the-fallback-encoding"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head><body>
+<div id="log"></div>
+<div id="foo"></div>
+<script>
+var elm = document.getElementById('foo');
+elm.id = '\u010C';
+var t = async_test();
+onload = t.step_func(function(){
+ assert_equals(getComputedStyle(elm, '').visibility, 'hidden');
+ this.done();
+});
+</script>
+</body></html>
diff --git a/testing/web-platform/tests/css/css-syntax/custom-property-rule-ambiguity.html b/testing/web-platform/tests/css/css-syntax/custom-property-rule-ambiguity.html
new file mode 100644
index 0000000000..50728bc94c
--- /dev/null
+++ b/testing/web-platform/tests/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/testing/web-platform/tests/css/css-syntax/decimal-points-in-numbers.html b/testing/web-platform/tests/css/css-syntax/decimal-points-in-numbers.html
new file mode 100644
index 0000000000..e59468678b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/decimal-points-in-numbers.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>decimal points in numbers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-number">
+
+<style>
+
+.foo {}
+
+</style>
+<script>
+
+function roundTripNumber(input) {
+ const rule = document.styleSheets[0].cssRules[0].style;
+ const fallback = "0";
+ rule.setProperty("line-height", fallback);
+ rule.setProperty("line-height", input);
+ const value = rule.getPropertyValue("line-height");
+ if(value == fallback) return false;
+ return value;
+}
+
+test(()=>{
+ assert_equals(roundTripNumber("1.0"), "1");
+}, "decimal point between digits is valid in a number");
+test(()=>{
+ assert_equals(roundTripNumber(".1"), "0.1");
+}, "decimal point before digits is valid in a number");
+test(()=>{
+ assert_not_equals(roundTripNumber("1."), "1");
+}, "decimal point after digits is invalid in a number");
+
+function roundTripDimension(input) {
+ const rule = document.styleSheets[0].cssRules[0].style;
+ const fallback = "0px";
+ rule.setProperty("width", fallback);
+ rule.setProperty("width", input);
+ const value = rule.getPropertyValue("width");
+ if(value == fallback) return false;
+ return value;
+}
+
+test(()=>{
+ assert_equals(roundTripDimension("1.0px"), "1px");
+}, "decimal point between digits is valid in a dimension");
+test(()=>{
+ assert_equals(roundTripDimension(".1px"), "0.1px");
+}, "decimal point before digits is valid in a dimension");
+test(()=>{
+ assert_not_equals(roundTripDimension("1.px"), "1px");
+}, "decimal point after digits is invalid in a dimension");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/declarations-trim-whitespace.html b/testing/web-platform/tests/css/css-syntax/declarations-trim-whitespace.html
new file mode 100644
index 0000000000..a7d69d149e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/declarations-trim-whitespace.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Declarations trim whitespace from their beginning/ending</title>
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-declaration">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+ <style id="style-el">
+ #foo {
+ --foo-1:bar;
+ --foo-2: bar;
+ --foo-3:bar ;
+ --foo-4: bar ;
+ --foo-5: bar !important;
+ --foo-6: bar !important ;
+ --foo-7:bar!important;
+ --foo-8:bar!important ;
+ --foo-9:bar
+ }
+ </style>
+ <p id=foo>foo</p>
+ <script>
+ let stylesheet = getComputedStyle(document.querySelector("#foo"));
+ let canonical = "bar";
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-1"), canonical);
+ }, "--foo-1:bar;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-2"), canonical);
+ }, "--foo-2: bar;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-3"), canonical);
+ }, "--foo-3:bar ;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-4"), canonical);
+ }, "--foo-4: bar ;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-5"), canonical);
+ }, "--foo-5: bar !important;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-6"), canonical);
+ }, "--foo-6: bar !important ;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-7"), canonical);
+ }, "--foo-7:bar!important;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-8"), canonical);
+ }, "--foo-8:bar!important ;");
+ test(function() {
+ assert_equals(stylesheet.getPropertyValue("--foo-9"), canonical);
+ }, "--foo-9:bar (then ws until end of rule)");
+ </script>
diff --git a/testing/web-platform/tests/css/css-syntax/escaped-eof.html b/testing/web-platform/tests/css/css-syntax/escaped-eof.html
new file mode 100644
index 0000000000..b4450ea730
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/escaped-eof.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<title>Escaped EOF</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-escaped-code-point">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-string-token">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-token">
+
+<style>foo { --foo:foo\</style>
+<style>foo { --foo:1foo\</style>
+<style>foo { --foo:url(foo\</style>
+<style>foo { --foo:"foo\</style>
+
+<script>
+test(()=>{
+ assert_throws_dom("SyntaxError", ()=>{document.querySelector("#123");}, "numeric hash token is invalid in a selector");
+ document.querySelector("#foo\\"); // escaped-EOF in a hash token is valid in a selector
+}, "Escaped EOF turns into a U+FFFD in a hash token, makes it 'ID' type.");
+
+test(()=>{
+ const sh = document.styleSheets[0];
+ const val = sh.cssRules[0].style.getPropertyValue("--foo");
+ assert_equals("foo\ufffd", val);
+}, "Escaped EOF turns into a U+FFFD in an ident token.");
+
+test(()=>{
+ const sh = document.styleSheets[1];
+ const val = sh.cssRules[0].style.getPropertyValue("--foo");
+ assert_equals("1foo\ufffd", val);
+}, "Escaped EOF turns into a U+FFFD in a dimension token.");
+
+test(()=>{
+ const sh = document.styleSheets[2];
+ const val = sh.cssRules[0].style.getPropertyValue("--foo");
+ assert_equals("url(foo\ufffd)", val);
+}, "Escaped EOF turns into a U+FFFD in a url token.");
+
+test(()=>{
+ const sh = document.styleSheets[3];
+ const val = sh.cssRules[0].style.getPropertyValue("--foo");
+ assert_equals(`"foo"`, val);
+}, "Escaped EOF in a string is ignored.");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/ident-three-code-points.html b/testing/web-platform/tests/css/css-syntax/ident-three-code-points.html
new file mode 100644
index 0000000000..36faef9357
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/ident-three-code-points.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<title>Testing valid ident based on first three code points</title>
+
+<link rel="author" title="Greg Whitworth" href="gwhit@microsoft.com" />
+<link rel="help" href="https://drafts.csswg.org/css-syntax-3/#would-start-an-identifier" />
+<style>
+ main div {
+ background-color:red;
+ }
+
+ div[name=one],
+ div[name=two] {
+ background: green;
+ }
+
+ #1 {
+ background-color:red;
+ }
+
+ #-2 {
+ background-color:red;
+ }
+
+ #--3 {
+ background-color:green;
+ }
+
+ #---4 {
+ background-color:green;
+ }
+
+ #a {
+ background-color:green;
+ }
+
+ #-b {
+ background-color:green;
+ }
+
+ #--c {
+ background-color:green;
+ }
+
+ #---d {
+ background-color:green;
+ }
+</style>
+<body>
+ <main>
+ <div id="1" class="item" name="one">test1</div>
+ <div id="-2" class="item" name="two">test2</div>
+ <div id="--3" class="item" name="three">test3</div>
+ <div id="---4" class="item" name="four">test4</div>
+
+ <div id="a" class="item" name="five">test A</div>
+ <div id="-b" class="item" name="six">test B</div>
+ <div id="--c" class="item" name="seven">test C</div>
+ <div id="---d" class="item" name="eight">test D</div>
+ </main>
+
+ <script>
+ var items = document.getElementsByClassName('item');
+
+ for(var i=0; i < items.length; i++) {
+ test(function() {
+ assert_equals(window.getComputedStyle(items[i]).getPropertyValue('background-color'), "rgb(0, 128, 0)");
+ }, items[i].getAttribute('name') + " should be green");
+ }
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-syntax/inclusive-ranges.html b/testing/web-platform/tests/css/css-syntax/inclusive-ranges.html
new file mode 100644
index 0000000000..ac486bde56
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/inclusive-ranges.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<title>Inclusive Ranges</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { z-index: 0; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#digit">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#non-printable-code-point">
+
+<script>
+
+function roundtripIdent(str) {
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.selectorText = "original-ident";
+ rule.selectorText = str;
+ // Check for parse error.
+ if(rule.selectorText == "original-ident") return "parse error";
+ return rule.selectorText;
+}
+function roundtripInteger(str) {
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.style.zIndex = "12345";
+ rule.style.zIndex = str;
+ // Check for parse error.
+ if(rule.style.zIndex == "12345") return "parse error";
+ return rule.style.zIndex;
+}
+function testInteger(input, expected) {
+ test(()=>{
+ assert_equals(roundtripInteger(input), expected);
+ }, `"${input}" becomes "${expected}"`);
+}
+function testIdent(input, expected) {
+ test(()=>{
+ assert_equals(roundtripIdent(input), expected);
+ }, `"${input}" becomes "${expected}"`);
+}
+
+/* Digits are the inclusive range 0-9 */
+for(var i = 0; i <= 9; i++) {
+ testInteger(i+"", i+"");
+}
+
+/* Non-printables are the inclusive ranges 0-8, b, e-1f, or 7f */
+// 0 never shows up due to preprocessing, so start at 1
+for(var i = 1; i <= 8; i++) {
+ testIdent("foo"+String.fromCodePoint(i), "parse error");
+}
+testIdent("foo"+String.fromCodePoint(0xb), "parse error");
+for(var i = 0xe; i <= 0x1f; i++) {
+ testIdent("foo"+String.fromCodePoint(i), "parse error");
+}
+testIdent("foo" + String.fromCodePoint(0x7f), "parse error");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/input-preprocessing.html b/testing/web-platform/tests/css/css-syntax/input-preprocessing.html
new file mode 100644
index 0000000000..9ef9a73082
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/input-preprocessing.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<title>Input Preprocessing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { color: blue; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#input-preprocessing">
+
+<script>
+
+function roundtripIdent(str) {
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.selectorText = "original-ident";
+ rule.selectorText = str;
+ // Check for parse error.
+ if(rule.selectorText == "original-ident") return "parse error";
+ return rule.selectorText;
+}
+function testParsing(input, expected) {
+ test(()=>{
+ assert_equals(roundtripIdent(input), expected);
+ }, `"${input}" becomes "${expected}"`);
+}
+
+/* Can't figure out how to test the newline normalization... */
+
+/* NULL becomes FFFD */
+testParsing("foo\x00", "foo\ufffd");
+testParsing("f\x00oo", "f\ufffdoo");
+testParsing("\x00foo", "\ufffdfoo");
+testParsing("\x00", "\ufffd");
+testParsing("\x00\x00\x00", "\ufffd\ufffd\ufffd");
+
+/* surrogates become FFFD */
+testParsing("foo\ud800", "foo\ufffd");
+testParsing("f\ud800oo", "f\ufffdoo");
+testParsing("\ud800foo", "\ufffdfoo");
+testParsing("\ud800", "\ufffd");
+testParsing("\ud800\ud800\ud800", "\ufffd\ufffd\ufffd");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/missing-semicolon-ref.html b/testing/web-platform/tests/css/css-syntax/missing-semicolon-ref.html
new file mode 100644
index 0000000000..ef8251e9e1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/missing-semicolon-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Missing semicolon at end of block should not keep declaration from being applied</title>
+ </head>
+ <body>
+ <div style="color: green;">Test passes if this paragraph is green.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/css-syntax/missing-semicolon.html b/testing/web-platform/tests/css/css-syntax/missing-semicolon.html
new file mode 100644
index 0000000000..d8e70e6315
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/missing-semicolon.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Missing semicolon at end of block should not keep declaration from being applied</title>
+ <link rel="author" title="Steinar H. Gunderson" href="mailto:sesse@chromium.org">
+ <link rel="help" href="https://crbug.com/1413840">
+ <link rel="match" href="missing-semicolon-ref.html">
+ <link rel="stylesheet" href="support/missing-semicolon.css">
+ </head>
+ <body>
+ <div class="c">Test passes if this paragraph is green.</div>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/css/css-syntax/non-ascii-codepoints.html b/testing/web-platform/tests/css/css-syntax/non-ascii-codepoints.html
new file mode 100644
index 0000000000..c416955d4e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/non-ascii-codepoints.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<title>Non-ASCII codepoints</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#non-ascii-ident-code-point">
+
+<script>
+function validIdentChar(cp) {
+ // Reset to a known-good ident
+ document.head.style.animationName = "foo";
+ // Then change to a name containing the char
+ document.head.style.animationName = "f"+String.fromCodePoint(cp)+"oo";
+ // And see if it actually changed.
+ return document.head.style.animationName != "foo";
+}
+
+function testValid(cp) {
+ test(()=>{
+ assert_true(validIdentChar(cp));
+ }, `Codepoint U+${cp.toString(16)} is a valid 'non-ASCII ident codepoint'.`)
+}
+
+function testInvalid(cp) {
+ // Just skip if the codepoint is outside the possible range.
+ if(cp > 0x1ffff) return;
+ test(()=>{
+ assert_false(validIdentChar(cp));
+ }, `Codepoint U+${cp.toString(16)} is not a 'non-ASCII ident codepoint'.`)
+}
+
+function testValidRanges(ranges) {
+ // Takes an array of codepoints or codepoints ranges,
+ // and tests whether the start, end, and middle of
+ // each range is valid, and confirms that the
+ // start/end of the regions between them are invalid.
+
+ for(const range of ranges) {
+ if(typeof range == "number") {
+ testValid(range);
+ continue;
+ }
+ testValid(range[0]);
+ if(range[1] - range[0] > 1) {
+ testValid(Math.floor((range[0]+range[1])/2));
+ }
+ testValid(range[1]);
+ }
+ testInvalid(0x80);
+ var lastTested = 0x80;
+ for(const range of ranges) {
+ if(typeof range == "number") {
+ if(range-1 != lastTested) testInvalid(range-1);
+ testInvalid(range+1);
+ lastTested = range+1;
+ continue;
+ }
+ if(range[0]-1 != lastTested) testInvalid(range[0]-1);
+ testInvalid(range[1]+1);
+ lastTested = range[1]+1;
+ }
+
+}
+
+testValidRanges([
+ 0xb7,
+ [0xc0, 0xd6],
+ [0xd8, 0xf6],
+ [0xf8, 0x37d],
+ [0x37f, 0x1fff],
+ [0x200c, 0x200d],
+ [0x203f, 0x2040]
+ [0x2070, 0x218f],
+ [0x2c00, 0x2fef],
+ [0x3001, 0xd7ff],
+ [0xf900, 0xfdcf],
+ [0xfdf0, 0xfffd],
+ [0x10000, 0x1ffff],
+]);
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/css/css-syntax/serialize-consecutive-tokens.html b/testing/web-platform/tests/css/css-syntax/serialize-consecutive-tokens.html
new file mode 100644
index 0000000000..f6e220de64
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/serialize-consecutive-tokens.html
@@ -0,0 +1,121 @@
+<!doctype html>
+<title>Serialization of consecutive tokens.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#serialization">
+<body>
+<!--
+ The serialization chapter provides a table listing all the combinations of consecutive tokens that will,
+ if naively serialized next to each other,
+ produce a different set of tokens when re-parsed.
+ The spec requires that a comment must be inserted between such tokens in the serialization,
+ to ensure that they round-trip correctly.
+-->
+
+<script>
+
+function testTokenPairs(t1, t2) {
+ const b = document.body;
+ test(()=>{
+ b.style.setProperty("--t1", t1);
+ b.style.setProperty("--t2", t2);
+ b.style.setProperty("--result", "var(--t1)var(--t2)");
+ const result = getComputedStyle(b).getPropertyValue("--result");
+ assert_equals(result.slice(0, t1.length), t1, `Result must start with ${t1}`);
+ assert_equals(result.slice(-t2.length), t2, `Result must end with ${t2}`);
+ assert_not_equals(result, t1+t2, `Result must have a comment between ${t1} and ${t2}`);
+ }, `Serialization of consecutive ${t1} and ${t2} tokens.`);
+}
+testTokenPairs("foo", "bar");
+testTokenPairs("foo", "bar()");
+testTokenPairs("foo", "url(bar)");
+testTokenPairs("foo", "-");
+testTokenPairs("foo", "123");
+testTokenPairs("foo", "123%");
+testTokenPairs("foo", "123em");
+testTokenPairs("foo", "-->");
+testTokenPairs("foo", "()");
+
+testTokenPairs("@foo", "bar");
+testTokenPairs("@foo", "bar()");
+testTokenPairs("@foo", "url(bar)");
+testTokenPairs("@foo", "-");
+testTokenPairs("@foo", "123");
+testTokenPairs("@foo", "123%");
+testTokenPairs("@foo", "123em");
+testTokenPairs("@foo", "-->");
+
+testTokenPairs("#foo", "bar");
+testTokenPairs("#foo", "bar()");
+testTokenPairs("#foo", "url(bar)");
+testTokenPairs("#foo", "-");
+testTokenPairs("#foo", "123");
+testTokenPairs("#foo", "123%");
+testTokenPairs("#foo", "123em");
+testTokenPairs("#foo", "-->");
+
+testTokenPairs("123foo", "bar");
+testTokenPairs("123foo", "bar()");
+testTokenPairs("123foo", "url(bar)");
+testTokenPairs("123foo", "-");
+testTokenPairs("123foo", "123");
+testTokenPairs("123foo", "123%");
+testTokenPairs("123foo", "123em");
+testTokenPairs("123foo", "-->");
+
+testTokenPairs("#", "bar");
+testTokenPairs("#", "bar()");
+testTokenPairs("#", "url(bar)");
+testTokenPairs("#", "-");
+testTokenPairs("#", "123");
+testTokenPairs("#", "123%");
+testTokenPairs("#", "123em");
+
+testTokenPairs("-", "bar");
+testTokenPairs("-", "bar()");
+testTokenPairs("-", "url(bar)");
+testTokenPairs("-", "-");
+testTokenPairs("-", "123");
+testTokenPairs("-", "123%");
+testTokenPairs("-", "123em");
+
+testTokenPairs("123", "bar");
+testTokenPairs("123", "bar()");
+testTokenPairs("123", "url(bar)");
+testTokenPairs("123", "123");
+testTokenPairs("123", "123%");
+testTokenPairs("123", "123em");
+testTokenPairs("123", "%");
+
+testTokenPairs("@", "bar");
+testTokenPairs("@", "bar()");
+testTokenPairs("@", "url(bar)");
+testTokenPairs("@", "-");
+
+testTokenPairs(".", "123");
+testTokenPairs(".", "123%");
+testTokenPairs(".", "123em");
+
+testTokenPairs("+", "123");
+testTokenPairs("+", "123%");
+testTokenPairs("+", "123em");
+
+testTokenPairs("/", "*");
+
+// Test that interior comments are preserved, but exterior ones are not.
+function testComments(text, t1, expected) {
+ const b = document.body;
+ test(()=>{
+ b.style.setProperty("--t1", t1);
+ b.style.setProperty("--result", text);
+ const result = getComputedStyle(b).getPropertyValue("--result");
+ assert_equals(result, expected);
+ }, `Comments are handled correctly when computing ${text} using t1:${t1}.`);
+}
+testComments("a/* comment */b", "", "a/* comment */b");
+testComments("a/* comment */var(--t1)", "b", "a/**/b");
+testComments("var(--t1)b", "a/* comment */", "a/**/b");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/support/missing-semicolon.css b/testing/web-platform/tests/css/css-syntax/support/missing-semicolon.css
new file mode 100644
index 0000000000..0d9a0bbda7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/support/missing-semicolon.css
@@ -0,0 +1,5 @@
+.c {
+ /* This { needs to be there to send Chromium into a different path. */
+ color: red;
+ color: green
+}
diff --git a/testing/web-platform/tests/css/css-syntax/trailing-braces.html b/testing/web-platform/tests/css/css-syntax/trailing-braces.html
new file mode 100644
index 0000000000..ac2e8e61b9
--- /dev/null
+++ b/testing/web-platform/tests/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/testing/web-platform/tests/css/css-syntax/unclosed-constructs.html b/testing/web-platform/tests/css/css-syntax/unclosed-constructs.html
new file mode 100644
index 0000000000..3d7940387c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/unclosed-constructs.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>Unclosed Constructs Are Valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#rule-defs">
+
+<!--
+Tests that unclosed constructs are valid and match grammars,
+because grammar-matching only sees the "block",
+not the opening/closing characters themselves.
+-->
+
+<script>
+
+function validSelector(str) {
+ try {
+ document.querySelector(str);
+ return true;
+ } catch(e) {
+ return false;
+ }
+}
+function shouldBeValid(str) {
+ test(()=>{
+ assert_true(validSelector(str));
+ }, `"${str}" is a valid selector`)
+}
+
+shouldBeValid("[foo]");
+shouldBeValid("[foo");
+shouldBeValid(":nth-child(1)");
+shouldBeValid(":nth-child(1");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/unclosed-url-at-eof.html b/testing/web-platform/tests/css/css-syntax/unclosed-url-at-eof.html
new file mode 100644
index 0000000000..7157896d97
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/unclosed-url-at-eof.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>Unclosed URL At EOF</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-url-token">
+
+<div id=test1-control style="background-image:url(foo)"></div>
+<div id=test1-experiment style="background-image:url(foo"></div>
+
+<div id=test2-control style="background-image:url()"></div>
+<div id=test2-experiment style="background-image:url("></div>
+
+<script>
+
+test(()=>{
+ const control = document.querySelector("#test1-control");
+ const experiment = document.querySelector("#test1-experiment");
+ assert_equals(control.style.backgroundImage, experiment.style.backgroundImage);
+}, "Unclosed url token at EOF is valid.");
+
+test(()=>{
+ const control = document.querySelector("#test2-control");
+ const experiment = document.querySelector("#test2-experiment");
+ assert_equals(control.style.backgroundImage, experiment.style.backgroundImage);
+}, "Unclosed empty url token at EOF is valid.");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/unicode-range-selector.html b/testing/web-platform/tests/css/css-syntax/unicode-range-selector.html
new file mode 100644
index 0000000000..db09540bb0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/unicode-range-selector.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Unicode range is not a token, and doesn't cause confusion in selectors</title>
+<link name="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-syntax/#urange">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ a { color: red }
+ u+a { color: green }
+</style>
+<u></u><a></a>
+<script>
+ test(function() {
+ assert_equals(
+ getComputedStyle(document.querySelector("a")).color,
+ "rgb(0, 128, 0)"
+ );
+ }, "Unicode range is not a token, and doesn't cause confusion in selectors");
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/urange-parsing.html b/testing/web-platform/tests/css/css-syntax/urange-parsing.html
new file mode 100644
index 0000000000..d01f6a54c3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/urange-parsing.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<title>Urange Parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+@font-face {
+ font-family: foo;
+ src: url(http://example.com);
+}
+
+.error {}
+
+</style>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#urange-syntax">
+
+<script>
+
+function testUrange(input, expected) {
+ test(()=>{
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.style.setProperty("unicode-range", "U+1357");
+ rule.style.setProperty("unicode-range", input);
+ assert_equals(rule.style.getPropertyValue("unicode-range").toUpperCase(), expected.toUpperCase());
+ }, `"${input}" => "${expected}"`)
+}
+function testInvalidUrange(input) {
+ test(()=>{
+ const rule = document.styleSheets[0].cssRules[0];
+ rule.style.setProperty("unicode-range", "U+1357");
+ rule.style.setProperty("unicode-range", input);
+ assert_equals(rule.style.getPropertyValue("unicode-range").toUpperCase(), "U+1357");
+ }, `"${input}" is invalid`);
+}
+
+/* First exercise all the clauses individually */
+//<urange> =
+// u '+' <ident-token> '?'* |
+/* comments can go between tokens */
+testUrange("u/**/+/**/a/**/?", "U+A0-AF");
+/* capitalization doesn't matter */
+testUrange("u+abc", "U+ABC");
+testUrange("U+abc", "U+ABC");
+testUrange("u+ABC", "U+ABC");
+testUrange("U+ABC", "U+ABC");
+testUrange("u+AbC", "U+ABC");
+/* only hex */
+testInvalidUrange("u+efg");
+/* no spacing */
+testInvalidUrange("u+ abc");
+testInvalidUrange("u +abc");
+testInvalidUrange("u + abc");
+testInvalidUrange("U + a b c");
+/* 1-6 characters */
+testUrange("u+a", "U+A");
+testUrange("u+aa", "U+AA");
+testUrange("u+aaa", "U+AAA");
+testUrange("u+aaaa", "U+AAAA");
+testUrange("u+aaaaa", "U+AAAAA");
+testInvalidUrange("u+aaaaaaa");
+/* Or ? at the end, still up to 6 */
+testUrange("u+a?", "U+A0-AF");
+testUrange("u+a??", "U+A00-AFF");
+testUrange("u+a???", "U+A000-AFFF");
+testUrange("u+a????", "U+A0000-AFFFF");
+testInvalidUrange("u+aaaaaa?");
+testInvalidUrange("u+aaaaa??");
+testInvalidUrange("u+aaaa???");
+testInvalidUrange("u+aaa????");
+testInvalidUrange("u+aa?????");
+testInvalidUrange("u+a??????");
+/* no characters after ? */
+testInvalidUrange("u+a?a");
+// Too large!
+testInvalidUrange("u+aaaaaa");
+testInvalidUrange("u+a?????");
+
+// u <dimension-token> '?'* |
+testUrange("u/**/+0a/**/?", "U+A0-AF");
+testUrange("u+0a", "U+A");
+testUrange("U+0a0", "U+A0");
+testUrange("u+0aaaaa", "U+AAAAA");
+testInvalidUrange("u+0aaaaaa");
+testUrange("u+0a0000", "U+A0000");
+testInvalidUrange("u+0a00000");
+testInvalidUrange("u+0aaaaa0");
+testUrange("u+00000a", "U+A");
+testInvalidUrange("u+00000aa");
+testInvalidUrange("u+00000a0")
+testInvalidUrange("u+000000a");
+testUrange("u+0a????", "U+A0000-AFFFF");
+testInvalidUrange("u+0a?????");
+testInvalidUrange("u+00a????");
+// Too large!
+testInvalidUrange("u+22222a");
+// Scinot!
+testUrange("u+1e9a", "U+1E9A");
+
+// u <number-token> '?'* |
+testUrange("u/**/+0/**/?", "U+0-F");
+testInvalidUrange("u/**/0");
+testUrange("u+0", "U+0");
+testUrange("u+00", "U+0");
+testUrange("u+000", "U+0");
+testUrange("u+0000", "U+0");
+testUrange("u+00000", "U+0");
+testUrange("u+000000", "U+0");
+testInvalidUrange("u+0000000");
+testUrange("u+00000?", "U+0-F");
+testUrange("u+0?????", "U+0-FFFFF");
+testInvalidUrange("u+0?a");
+testInvalidUrange("u+000000?");
+testInvalidUrange("u+00000??");
+testInvalidUrange("u+0??????");
+// Scinot!
+testUrange("u+1e3", "U+1E3");
+testUrange("u+1e-20", "U+1E-20");
+// Too large!
+testInvalidUrange("u+222222");
+testInvalidUrange("u+2?????");
+
+// u <number-token> <dimension-token> |
+testUrange("u/**/+0/**/-0a", "U+0-A");
+testUrange("u+0-0a", "U+0-A");
+testUrange("u+000000-0aaaaa", "U+0-AAAAA");
+testInvalidUrange("u+0000000-0a");
+testInvalidUrange("u+0-0aaaaaa");
+testInvalidUrange("u+0-000000a");
+testInvalidUrange("u+0+0a");
+testInvalidUrange("u+0?-0a");
+testInvalidUrange("u+0-0a?");
+// Too large!
+testInvalidUrange("u+222222-22222a");
+
+// u <number-token> <number-token> |
+testUrange("u/**/+0/**/-1", "U+0-1");
+testUrange("u+0-1", "U+0-1");
+testInvalidUrange("u-0-1");
+testInvalidUrange("u-0+1");
+testInvalidUrange("u+0+1");
+testUrange("u+000000-000001", "U+0-1");
+testInvalidUrange("u+0000000-1");
+testInvalidUrange("u+0-0000001");
+testUrange("u+0-10ffff", "U+0-10FFFF");
+// Too large!
+testInvalidUrange("u+0-110000");
+testInvalidUrange("u+0-222222");
+
+// u '+' '?'+
+testUrange("u/**/+/**/?", "U+0-F");
+testUrange("u+?", "U+0-F");
+testUrange("u+?????", "u+0-FFFFF");
+testInvalidUrange("u+???????");
+testInvalidUrange("u+?a");
+// U+FFFFFF is too large!
+testInvalidUrange("u+??????");
+
+
+/* Finally, verify that u+a is properly parsed
+ as IDENT(u) DELIM(+) IDENT(a) in other contexts */
+
+test(()=>{
+ const rule = document.styleSheets[0].cssRules[1];
+ // Establish that it works with whitespace...
+ rule.selectorText = "u + a";
+ assert_equals(rule.selectorText, "u + a");
+ // And then again without...
+ rule.selectorText = ".error";
+ rule.selectorText = "u+a";
+ assert_equals(rule.selectorText, "u + a");
+}, "u+a is a valid selector");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/url-whitespace-consumption.html b/testing/web-platform/tests/css/css-syntax/url-whitespace-consumption.html
new file mode 100644
index 0000000000..2fd55873d9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/url-whitespace-consumption.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>url whitespace consumption</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+.foo {}
+
+</style>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#consume-ident-like-token">
+
+<script>
+
+function roundTripUrl(input) {
+ const rule = document.styleSheets[0].cssRules[0].style;
+ const fallback = 'url("fallback")';
+ rule.setProperty("background-image", fallback);
+ rule.setProperty("background-image", input);
+ const value = rule.getPropertyValue("background-image");
+ if(value == fallback) return false;
+ return value;
+}
+
+test(()=>{
+ assert_equals(roundTripUrl('url("foo")'), 'url("foo")');
+ assert_equals(roundTripUrl('url( "foo")'), 'url("foo")');
+ assert_equals(roundTripUrl('url("foo" )'), 'url("foo")');
+}, "whitespace is optional between url( token and the string token");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-syntax/var-with-blocks.html b/testing/web-platform/tests/css/css-syntax/var-with-blocks.html
new file mode 100644
index 0000000000..915a2467e3
--- /dev/null
+++ b/testing/web-platform/tests/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>
diff --git a/testing/web-platform/tests/css/css-syntax/whitespace.html b/testing/web-platform/tests/css/css-syntax/whitespace.html
new file mode 100644
index 0000000000..bc7aa7ebda
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/whitespace.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>CSS Whitespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#whitespace">
+
+<div class=a><b></b></div>
+<div id=foo></div>
+
+<!--
+CSS's definition of "whitespace" matches HTML,
+and includes only the five ASCII characters
+U+0009, U+000A, U+000C, U+000D, and U+0020.
+The rest of Unicode's whitespace characters,
+many of which are recognized as whitespace by JS,
+are not valid whitespace in CSS.
+-->
+
+<script>
+
+function isWhitespace(codepoint) {
+ const char = String.fromCodePoint(codepoint);
+ const codepointName = "U+" + codepoint.toString(16).padStart(4, "0");
+ test(()=>{
+ const withSpace = document.querySelector(".a b");
+ const withChar = document.querySelector(`.a${char}b`);
+ assert_equals(withSpace, withChar);
+ }, `${codepointName} is CSS whitespace`);
+}
+function isNotWhitespace(codepoint) {
+ const char = String.fromCodePoint(codepoint);
+ const codepointName = "U+" + codepoint.toString(16).padStart(4, "0");
+ test(()=>{
+ const withSpace = document.querySelector(".a b");
+ document.querySelector("#foo").setAttribute("class", `.a${char}b`);
+ try {
+ var withChar = document.querySelector(`.a${char}b`);
+ } catch(e) {
+ assert_true(true, `${codepointName} isn't valid in a selector at all`);
+ return;
+ }
+ assert_not_equals(withSpace, withChar);
+ }, `${codepointName} is *not* CSS whitespace`);
+}
+
+// CSS Whitespace characters
+var whitespace = [0x9, 0xa, 0xc, 0xd, 0x20];
+
+// Unicode Whitespace characters not recognized by CSS
+// https://en.wikipedia.org/wiki/Whitespace_character#Unicode
+var notWhitespace = [0xb, 0x85, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x2928, 0x2029, 0x202f, 0x205f, 0x3000, 0x180e, 0x200b, 0x200c, 0x200d, 0x2060, 0xfeff];
+
+for(var codepoint of whitespace) {
+ isWhitespace(codepoint);
+}
+for(var codepoint of notWhitespace) {
+ isNotWhitespace(codepoint);
+}
+
+</script>