Parsing all selectors unforgiving way for @supports selector()

To detect errors in forgiving parsing selectors (e.g. :is(), :has())
with '@supports selector()', CSSSelectorParser parses all selectors
unforgiving way to raise error while checking the selectors with
'@supports selector()` according to the csswg issue resolution:
- csswg-drafts/issues/7280#issuecomment-1143852187

An experimental feature flag 'CSSAtSupportsAlwaysNonForgivingParsing'
is added to enable this behavior when the experimental-web-platform-
features flag is enabled.

This is the chrome platform feature for the flag:
- https://chromestatus.com/feature/6177049203441664

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3872106
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Byungwoo Lee <blee@igalia.com>
Cr-Commit-Position: refs/heads/main@{#1043758}
diff --git a/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument-ref.html b/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument-ref.html
new file mode 100644
index 0000000..681ef4b
--- /dev/null
+++ b/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument-ref.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>CSS Conditional Test: @supports selector() detecting invalid in forgiving argument.</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<style>
+  div {
+    background-color:green;
+    height:100px;
+    width:100px;
+  }
+</style>
+<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
diff --git a/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument.html b/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument.html
new file mode 100644
index 0000000..7464844
--- /dev/null
+++ b/css/css-conditional/at-supports-selector-detecting-invalid-in-forgiving-argument.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>CSS Conditional Test: @supports selector() detecting invalid in forgiving argument.</title>
+<link rel="author" title="Byungwoo Lee" href="mailto:blee@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-conditional/#at-supports">
+<link rel="match" href="at-supports-selector-detecting-invalid-in-forgiving-argument-ref.html">
+<style>
+  div.invalid {
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  div.valid {
+    background-color: red;
+    height: 100px;
+    width: 100px;
+  }
+  @supports selector(:is(.a)) {
+    div.is.valid { background: green };
+  }
+  @supports selector(:where(.a)) {
+    div.where.valid { background: green };
+  }
+  @supports selector(:has(.a)) {
+    div.has.valid { background: green };
+  }
+  @supports selector(:is(:foo, .a)) {
+    div.is.invalid { background: red };
+  }
+  @supports selector(:where(:foo, .a)) {
+    div.where.invalid { background: red };
+  }
+  @supports selector(:has(:foo, .a)) {
+    div.has.invalid { background: red };
+  }
+</style>
+<p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+<div class="is valid"></div>
+<div class="where valid"></div>
+<div class="has valid"></div>
+<div class="is invalid"></div>
+<div class="where invalid"></div>
+<div class="has invalid"></div>
diff --git a/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-forgiving-argument.html b/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-forgiving-argument.html
new file mode 100644
index 0000000..4b83afc
--- /dev/null
+++ b/css/css-conditional/js/CSS-supports-selector-detecting-invalid-in-forgiving-argument.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS.supports() detecting invalid in forgiving argument</title>
+<link rel="help" href="https://www.w3.org/TR/css-conditional-4/#the-css-namespace">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  test(function() {
+    assert_equals(CSS.supports("selector(:is(:foo))"), false);
+    assert_equals(CSS.supports("selector(:is(.a, :foo))"), false);
+    assert_equals(CSS.supports("selector(:is(:foo, .a))"), false);
+    assert_equals(CSS.supports("selector(:is(:has(:foo, a), .b))"), false);
+    assert_equals(CSS.supports("selector(:where(:foo))"), false);
+    assert_equals(CSS.supports("selector(:where(.a, :foo))"), false);
+    assert_equals(CSS.supports("selector(:where(:foo, .a))"), false);
+    assert_equals(CSS.supports("selector(:where(:is(:foo, a), .b))"), false);
+    assert_equals(CSS.supports("selector(:has(:foo))"), false);
+    assert_equals(CSS.supports("selector(:has(.a, :foo))"), false);
+    assert_equals(CSS.supports("selector(:has(:foo, .a))"), false);
+    assert_equals(CSS.supports("selector(:has(:where(:foo, a), .b))"), false);
+  }, "Invalid selector can be detected with CSS.supports() even if it is dropped by forgiving parsing");
+
+  test(function() {
+    assert_equals(CSS.supports("selector(:is())"), false);
+    assert_equals(CSS.supports("selector(:where())"), false);
+    assert_equals(CSS.supports("selector(:has())"), false);
+  }, ":is(), :where() or :has() always fails without argument");
+
+  test(function() {
+    assert_equals(CSS.supports("selector(:has(:has(.a)))"), false);
+    assert_equals(CSS.supports("selector(:has(:has(.a), b))"), false);
+    assert_equals(CSS.supports("selector(.a, :has(:has(.b)))"), false);
+    assert_equals(CSS.supports("selector(:has(:is(:has(.a))))"), false);
+    assert_equals(CSS.supports("selector(:has(:is(:has(.a), .b)))"), false);
+    assert_equals(CSS.supports("selector(:has(:is(.a, :has(.b))))"), false);
+  }, ":has() always fails inside :has()");
+
+  test(function() {
+    assert_equals(CSS.supports("selector(:is(::after)"), false);
+    assert_equals(CSS.supports("selector(:is(::before)"), false);
+    assert_equals(CSS.supports("selector(:is(::first-letter)"), false);
+    assert_equals(CSS.supports("selector(:is(::first-line)"), false);
+    assert_equals(CSS.supports("selector(:where(::after)"), false);
+    assert_equals(CSS.supports("selector(:where(::before)"), false);
+    assert_equals(CSS.supports("selector(:where(::first-letter)"), false);
+    assert_equals(CSS.supports("selector(:where(::first-line)"), false);
+    assert_equals(CSS.supports("selector(:has(::after)"), false);
+    assert_equals(CSS.supports("selector(:has(::before)"), false);
+    assert_equals(CSS.supports("selector(:has(::first-letter)"), false);
+    assert_equals(CSS.supports("selector(:has(::first-line)"), false);
+  }, "Some pseudo elements always fail inside :is(), :where(), :has()");
+</script>