Skip to content

Commit

Permalink
Make forgiving selectors serialize.
Browse files Browse the repository at this point in the history
As per resolution in w3c/csswg-drafts#8356

Safari already does this. Expand the tests they tweaked to be useful
again (test that when non-forgiving parsing is used, then the selector
is invalid).

Differential Revision: https://phabricator.services.mozilla.com/D189666

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1856018
gecko-commit: 2cb6f84a4847fb9df32a8f37fe14deb1ae5602a5
gecko-reviewers: dshin
  • Loading branch information
emilio authored and moz-wptsync-bot committed Oct 4, 2023
1 parent dfda991 commit 3eed7dc
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 30 deletions.
13 changes: 7 additions & 6 deletions css/css-scoping/slotted-parsing.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
test_valid_selector("::slotted([attr]:hover)");
test_valid_selector("::slotted(:not(.a))");

test_valid_selector("::slotted(*):is()");
test_valid_selector("::slotted(*):is(:hover)");
test_valid_selector("::slotted(*):is(#id)");
test_valid_forgiving_selector("::slotted(*):is()");
test_valid_forgiving_selector("::slotted(*):is(:hover)");
test_valid_forgiving_selector("::slotted(*):is(#id)");

test_valid_selector("::slotted(*):where()");
test_valid_selector("::slotted(*):where(:hover)");
test_valid_selector("::slotted(*):where(#id)");
test_valid_forgiving_selector("::slotted(*):where()");
test_valid_forgiving_selector("::slotted(*):where(:hover)");
test_valid_forgiving_selector("::slotted(*):where(#id)");
test_valid_forgiving_selector("::slotted(*):where(::before)");

// Allow tree-abiding pseudo elements after ::slotted
test_valid_selector("::slotted(*)::before");
Expand Down
38 changes: 15 additions & 23 deletions css/selectors/is-where-parsing.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,20 @@
<link rel="help" href="https://drafts.csswg.org/selectors-4/#zero-matches">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style id="test-sheet">
random-selector { color: blue; }
</style>
<script src="/css/support/parsing-testcommon.js"></script>
<script>
let rule = document.getElementById("test-sheet").sheet.cssRules[0];
function assert_valid(expected_parseable, pattern, expected_pattern, description) {
test(function() {
for (let pseudo of ["is", "where"]) {
let selector = pattern.replace("{}", ":" + pseudo);
let expected_selector = selector;
if (expected_pattern != null)
expected_selector = expected_pattern.replace("{}", ":" + pseudo);
rule.selectorText = "random-selector";
rule.selectorText = selector;
(expected_parseable ? assert_equals : assert_not_equals)(
rule.selectorText,
expected_selector,
`${description}: ${selector}`
);
function assert_valid(valid, pattern, expected_pattern, description) {
for (let pseudo of ["is", "where"]) {
let selector = pattern.replace("{}", ":" + pseudo);
let expected_selector = selector;
if (expected_pattern != null)
expected_selector = expected_pattern.replace("{}", ":" + pseudo);
if (valid) {
test_valid_selector(selector, expected_selector);
} else {
test_valid_forgiving_selector(selector);
}
}, description);
}
}

assert_valid(true, "{}(div )", "{}(div)", "Trailing whitespace");
Expand All @@ -42,12 +35,11 @@
assert_valid(true, "{}(:hover, :active)", null, "Pseudo-classes inside");
assert_valid(true, "{}(div):hover", null, "Pseudo-classes after");
assert_valid(true, "{}(div)::before", null, "Pseudo-elements after");
// Should ask clarification from CSSWG
assert_valid(true, "{}(::before)", null, "Pseudo-elements inside");
assert_valid(false, "{}(::before)", null, "Pseudo-elements inside");

assert_valid(true, "{}(div) + bar", null, "Combinators after");
assert_valid(true, "::part(foo):is(:hover)", null, "After part with simple pseudo-class");
assert_valid(false, "::part(foo):is([attr='value'])", null, "After part with invalid selector after");
assert_valid(true, "::part(foo){}(:hover)", null, "After part with simple pseudo-class");
assert_valid(false, "::part(foo){}([attr='value'])", null, "After part with invalid selector after");

assert_valid(true, ":not({}(div))", null, "Nested inside :not, without combinators");
assert_valid(true, ":not({}(div .foo))", null, "Nested inside :not, with combinators");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<script src="/css/support/parsing-testcommon.js"></script>
<script>
test_invalid_selector('.a:has(.b:has(.c))');
test_valid_forgiving_selector(':has(:is(:has(*)))');
test_valid_forgiving_selector(':has(:where(:has(*)))');
test(() => {
// It's not easy to check that these are invalid because :is() and :where()
// use forgiving parsing. Check that they never match instead.
Expand Down
9 changes: 8 additions & 1 deletion css/support/parsing-testcommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ function test_invalid_value(property, value) {
}, "e.style['" + property + "'] = " + stringifiedValue + " should not set the property value");
}

function test_valid_forgiving_selector(selector) {
test_valid_selector(selector, selector, { onlyWhenForgiving: true });
}

// serializedSelector can be the expected serialization of selector,
// or an array of permitted serializations,
// or omitted if value should serialize as selector.
function test_valid_selector(selector, serializedSelector) {
function test_valid_selector(selector, serializedSelector, options) {
if (arguments.length < 2)
serializedSelector = selector;

Expand Down Expand Up @@ -85,6 +89,9 @@ function test_valid_selector(selector, serializedSelector) {
assert_equals(cssRules.length, 1, "Sheet should have 1 rule");

assert_equals(cssRules[0].selectorText, readSelector, "serialization should round-trip");

let supports = !options?.onlyWhenForgiving;
assert_equals(CSS.supports(`selector(${selector})`), supports, "CSS.supports() reports the expected value");
}, stringifiedSelector + " should be a valid selector");
}

Expand Down

0 comments on commit 3eed7dc

Please sign in to comment.