Skip to content

[selectors] [css-conditional] Detecting :has() restrictions #7280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
emilio opened this issue May 16, 2022 · 4 comments
Closed

[selectors] [css-conditional] Detecting :has() restrictions #7280

emilio opened this issue May 16, 2022 · 4 comments

Comments

@emilio
Copy link
Collaborator

emilio commented May 16, 2022

Multiple implementations want to ship the :has() selector with a variety of limitations in order to prevent performance footguns and complexity:

However, since :has() has forgiving parsing like :is() / :where(), it's not possible to detect these limitations easily, and it won't be possible to do so if we ever remove these limitations.

For :is() / :where() it's not a problem since it's generally assumed that if the selector is valid outside of them it'll be valid inside of them... But for the limitations that folks are imposing on :has() (and which for the record I agree with) this is not true.

Perhaps we should special-case @supports selector(..) to not use forgiving parsing? Otherwise the only way to potentially detect this is with script (by reading back the serialization of :has() and see if the relevant selectors have been dropped).

cc @byung-woo @anttijk

@byung-woo
Copy link
Member

byung-woo commented May 17, 2022

Perhaps we should special-case @supports selector(..) to not use forgiving parsing?

I think this is a good way to detect the limitations without losing the benefits of forgiving parsing.

Currently, pseudo-elements are explicitly disallowed inside :is() (https://drafts.csswg.org/selectors-4/#matches).

If @supports can detect the limitation inside logical combinations, I think we can provide more clear limitation by wpt, something like:

@supports not selector(:is(::first-letter)) {
 #disallow_first_letter_inside_is { color: green }
}
@supports not selector(:has(:host)) {
 #disallow_host_inside_has { color: green }
}

How about others?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [selectors] [css-conditional] Detecting :has() restrictions, and agreed to the following:

  • RESOLVED: @supports uses non-forgiving parsing for all selectors
The full IRC log of that discussion <fantasai> Topic: [selectors] [css-conditional] Detecting :has() restrictions
<fantasai> github: https://github.com//issues/7280
<fantasai> emilio: It seems this is not going to have so many restrictions, so maybe not a big deal
<fantasai> emilio: In case we wanted to restrict stuff like :host
<fantasai> emilio: and then eventually potentially ...
<fantasai> emilio: not easy to detect which UAs would support it vs not
<fantasai> emilio: since :has() uses forgiving parsing, anything you throw at it is valid
<fantasai> emilio: It seems we're only going to restrict :has() inside :has()
<fantasai> emilio: doesn't seem useful but complex, but may still matter...
<fantasai> emilio: My point is that if we have any hope for unrestricting, it may be useful to be able to detect it when we do
<jensimmons> +1000
<fantasai> emilio: If you put @supports :has(:has()) ...
<fantasai> emilio: makes it a problem if you want to do something in the future
<jensimmons> =Q
<jensimmons> +q
<fantasai> emilio: you can always test the thing inside
<fantasai> TabAtkins: not true
<fantasai> TabAtkins: :is()-disallowed pseudo-elements, for example
<fantasai> TabAtkins: this sounds reasonable to me
<fantasai> TabAtkins: unsure about forgiving vs unforgiving
<astearns> ack jensimmons
<fantasai> jensimmons: I think it's a really good idea
<oriol> q+
<fantasai> jensimmons: Having @supports parse as valid a thing that the browser doesn't support
<fantasai> jensimmons: for the future, we need @supports to be accurate and true
<fantasai> emilio: For FF it's easy, just passing down a flag
<astearns> ack oriol
<fantasai> oriol: I wonder if rather than adding hack in supports we could say that if you have either :has() or whatever that has this forgiving syntax, and all of the selectors inside it are invalid, then it would also be invalid
<fantasai> oriol: It would be something like, if you have some invalid and some valid treat whole as invalid
<fantasai> oriol: So if you only have invalid ones, it would be invalid. If you have a mix, it would be valid
<emilio> oriol is saying that `:has(:random)` would be valid, but `:has(something, :random)` would be valid
<astearns> s/whole as invalid/whole as valid/
<fantasai> oriol: So if using :has(invalid) then is invalid, and detect that without having to make supports change the syntax
<fantasai> fantasai: OK, so I'm with jensimmons here. If the selector contains anything invalid, then it should return as invalid even if the invalidity is caught at a lower level
<fantasai> emilio: Some precedent here wrt -webkit- stuff
<fantasai> jensimmons: If this occurred to me as a developer, I wouldn't look it up. I would use @supports to detect support, e.g with color:red
<fantasai> emilio: Especially if CSS author, unlikely to jump to using JS to check
<fantasai> astearns: So proposed resolution is for @supports to use non-forgiving parsing for all selectors
<fantasai> TabAtkins: yes
<fantasai> strong +1
<fantasai> RESOLVED: @supports uses non-forgiving parsing for all selectors

@svgeesus
Copy link
Contributor

svgeesus commented Jul 29, 2022

It looks like this would affect at-supports-046.html which assumes forgiving parsing? (wpt results)

@fantasai
Copy link
Collaborator

fantasai commented Aug 4, 2022

@svgeesus No, that test is fine. This is about the contents of the selector() function.

fantasai added a commit that referenced this issue Aug 4, 2022
…or that do not invalidate the selector cause the selector to be unsupported nonetheless. #7280
@fantasai fantasai closed this as completed Aug 4, 2022
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 2, 2022
To detect invalid selector usage, always do unforgiving parsing for
all selectors inside @support according to the csswg issue resolution:
 w3c/csswg-drafts#7280 (comment)

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 3, 2022
To detect invalid selector usage, always do unforgiving parsing for
all selectors inside `@support selector()` according to the csswg issue resolution:
- w3c/csswg-drafts#7280

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 3, 2022
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:

w3c/csswg-drafts#7280 (comment)

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 3, 2022
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:

w3c/csswg-drafts#7280 (comment)

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 5, 2022
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:

w3c/csswg-drafts#7280 (comment)

Bug: 1358953, 1359396
Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
mgol added a commit to mgol/jquery that referenced this issue Sep 5, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Fixes jquerygh-5098
mgol added a commit to mgol/jquery that referenced this issue Sep 5, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Fixes jquerygh-5098
mgol added a commit to mgol/jquery that referenced this issue Sep 5, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Fixes jquerygh-5098
mgol added a commit to mgol/jquery that referenced this issue Sep 5, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Fixes jquerygh-5098
mgol added a commit to mgol/jquery that referenced this issue Sep 5, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Fixes jquerygh-5098
AdamMajer pushed a commit to openSUSE/cockpit that referenced this issue Sep 20, 2022
mgol added a commit to mgol/jquery that referenced this issue Sep 21, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Sep 21, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
marusak pushed a commit to marusak/cockpit that referenced this issue Sep 23, 2022
marusak pushed a commit to cockpit-project/cockpit that referenced this issue Sep 26, 2022
Rejecting CSS.supports(":is()") is the correct thing to do per
w3c/csswg-drafts#7280

Fixes #17724.
https://bugzilla.redhat.com/show_bug.cgi?id=2129055

Cherry-picked from main commit ce351ca.
mgol added a commit to mgol/jquery that referenced this issue Oct 3, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Oct 4, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Nov 17, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Dec 1, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Dec 13, 2022
jQuery has followed the following logic for selector handling for ages:
1. Modify the selector to adhere to scoping rules jQuery mandates.
2. Try `qSA` on the modified selector. If it succeeds, use the results.
3. If `qSA` threw an error, run the jQuery custom traversal instead.

It worked fine so far but now CSS has a concept of forgiving selector lists that
some selectors like `:is()` & `:has()` use. That means providing unrecognized
selectors as parameters to `:is()` & `:has()` no longer throws an error, it will
just return no results. That made browsers with native `:has()` support break
selectors using jQuery extensions inside, e.g. `:has(:contains("Item"))`.

Detecting support for selectors can also be done via:

```js
CSS.supports( "selector(SELECTOR_TO_BE_TESTED)" )
```
which returns a boolean. There was a recent spec change requiring this API to
always use non-forgiving parsing:
w3c/csswg-drafts#7280 (comment)
However, no browsers have implemented this change so far.

To solve this, two changes are being made:
1. In browsers supports the new spec change to `CSS.supports( "selector()" )`,
   use it before trying `qSA`.
2. Otherwise, add `:has` to the buggy selectors list.

Ref jquerygh-5098
Ref jquerygh-5107
Ref jquery/sizzle#486
Ref w3c/csswg-drafts#7676
mgol added a commit to mgol/jquery that referenced this issue Dec 17, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors,
like `:has()`, now have their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change]() made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquerygh-5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/jquery that referenced this issue Dec 17, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors,
like `:has()`, now have their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change]() made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquerygh-5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/jquery that referenced this issue Dec 17, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors,
like `:has()`, now have their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change]() made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquerygh-5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/jquery that referenced this issue Dec 17, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors,
like `:has()`, now had their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquerygh-5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/sizzle that referenced this issue Dec 17, 2022
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquery/jquery#5098 -
some selectors, like `:has()`, now had their parameters parsed in a forgiving
way, meaning that `:has(:fakepseudo)` no longer throws but just returns
0 results, breaking that Sizzle mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the Sizzle implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the Sizzle custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquery/jquery#5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/sizzle that referenced this issue Dec 17, 2022
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquery/jquery#5098 -
some selectors, like `:has()`, now had their parameters parsed in a forgiving
way, meaning that `:has(:fakepseudo)` no longer throws but just returns
0 results, breaking that Sizzle mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the Sizzle implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the Sizzle custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquery/jquery#5177
Ref w3c/csswg-drafts#7280
mgol added a commit to mgol/sizzle that referenced this issue Dec 17, 2022
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquery/jquery#5098 -
some selectors, like `:has()`, now had their parameters parsed in a forgiving
way, meaning that `:has(:fakepseudo)` no longer throws but just returns
0 results, breaking that Sizzle mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the Sizzle implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the Sizzle custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquery/jquery#5177
Ref w3c/csswg-drafts#7280
mgol added a commit to jquery/sizzle that referenced this issue Dec 19, 2022
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve jquery/jquery#5098 -
some selectors, like `:has()`, now had their parameters parsed in a forgiving
way, meaning that `:has(:fakepseudo)` no longer throws but just returns
0 results, breaking that Sizzle mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the Sizzle implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the Sizzle custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes jquery/jquery#5177
Closes gh-491
Ref w3c/csswg-drafts#7280
mgol added a commit to jquery/jquery that referenced this issue Dec 19, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve gh-5098 - some selectors,
like `:has()`, now had their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes gh-5177
Closes gh-5178
Ref w3c/csswg-drafts#7280
mgol added a commit to jquery/jquery that referenced this issue Dec 19, 2022
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using
`querySelectorAll` on the selector. This was to solve gh-5098 - some selectors,
like `:has()`, now had their parameters parsed in a forgiving way, meaning
that `:has(:fakepseudo)` no longer throws but just returns 0 results, breaking
that jQuery mechanism.

A recent spec change made `CSS.supports( "selector(SELECTOR)" )` always use
non-forgiving parsing, allowing us to use this API for what we've used
`try-catch` before.

To solve the issue on the spec side for older jQuery versions, `:has()`
parameters are no longer using forgiving parsing in the latest spec update
but our new mechanism is more future-proof anyway.

However, the jQuery implementation has a bug - in
`CSS.supports( "selector(SELECTOR)" )`, `SELECTOR` needs to be
a `<complex-selector>` and not a `<complex-selector-list>`. Which means that
selector lists now skip `qSA` and go to the jQuery custom traversal:
```js
CSS.supports("selector(div:valid, span)"); // false
CSS.supports("selector(div:valid)"); // true
CSS.supports("selector(span)"); // true
```

To solve this, this commit wraps the selector list passed to
`CSS.supports( "selector(:is(SELECTOR))" )` with `:is`, making it a single
selector again.

See:
* https://w3c.github.io/csswg-drafts/css-conditional-4/#at-supports-ext
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector
* https://w3c.github.io/csswg-drafts/selectors-4/#typedef-complex-selector-list

Fixes gh-5177
Closes gh-5178
Ref w3c/csswg-drafts#7280

(cherry picked from commit 09d988b)
aarongable pushed a commit to chromium/chromium that referenced this issue Feb 7, 2023
…ngParsing

Enable these two features by default.

CSSAtSupportsAlwaysNonForgivingParsing:
- Apply the csswg issue resolution: change '@supports' selector parsing.
- w3c/csswg-drafts#7280 (comment)

CSSPseudoHasNonForgivingParsing:
- Apply the csswg issue resolution: make ':has()' non-forgiving.
- w3c/csswg-drafts#7676 (comment)

Intent-to-ship: https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/RJrIxJA9LYw

Bug: 1359396, 1399744
Change-Id: I179f22074f5cf6c9c8d56e36a4e3360bfe892256
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4224863
Reviewed-by: Rune Lillesveen <[email protected]>
Commit-Queue: Byungwoo Lee <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1102139}
Loirooriol pushed a commit to Loirooriol/servo that referenced this issue Oct 30, 2023
mrobinson pushed a commit to Loirooriol/servo that referenced this issue Nov 2, 2023
mrobinson pushed a commit to Loirooriol/servo that referenced this issue Nov 3, 2023
mrobinson pushed a commit to servo/servo that referenced this issue Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants