Selector: Make selector lists work with `qSA` again
commit09d988b774e7ff4acfb69c0cde2dab373559aaca
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 19 Dec 2022 17:43:30 +0000 (19 18:43 +0100)
committerGitHub <noreply@github.com>
Mon, 19 Dec 2022 17:43:30 +0000 (19 18:43 +0100)
tree99e41463a57ab4a82c3198922f1df96ca0a33091
parent024d87195ac46690023e2b0b308d4406a8a5a27e
Selector: Make selector lists work with `qSA` again

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
src/selector.js
src/selector/rbuggyQSA.js
src/selector/support.js
test/unit/selector.js