[csswg-drafts] [selectors] May new pseudos using forgiving parsing be introduced in the future? (#8378)

mgol has just created a new issue for https://github.com/w3c/csswg-drafts:

== [selectors] May new pseudos using forgiving parsing be introduced in the future? ==
In #7676, I reported the forgiving nature of `:has()` to be breaking jQuery. tl;dr is jQuery uses try-catch on some version of the selector passed to `qSA` and does its own traversal when it throws as a fallback. With the help of some support tests, a regex is constructed that identifies buggy selectors which don't get passed through `qSA` at all and go straight to the jQuery traversal.

`:has()` has been since made non-forgiving but during the discussion it was suggested that jQuery shouldn't rely on try-catch as some selectors may be forgiving and the fact there's no error thrown doesn't mean the selector works natively. [We were directed to use `CSS.supports( "selector(...)" )`](https://github.com/w3c/csswg-drafts/issues/7676#issuecomment-1235472172) which was made always non-forgiving[^spec-non-forgiving-supports], the spec change that only made it to Firefox stable so far. jQuery 3.6.2 implemented this change in browsers with spec-compliant `CSS.supports( "selector(...)" )` (i.e., currently just Firefox). jQuery 3.6.3 changed that to `CSS.supports( "selector(:is(...))" )` as bare `selector(...)` doesn't support selector lists which jQuery accepts as input.

However, we didn't take into account that those two approaches differ and `qSA` is way more forgiving than `CSS.supports( "selector(...)" )`, even beyond `:is()` & `:where()`. For example, native `qSA( ":before" )` returns 0 results but does not throw while `CSS.supports( "selector(:is(:before))" )` is `false`. The same for unterminated brackets: `qSA( "[attr=val" )` works and returns valid results but both `CSS.supports( "selector(:is([attr=val))" )` and `CSS.supports( "selector([attr=val)" )` are `false`. We've already gotten [multiple](https://github.com/jquery/jquery/issues/5194) [reports](https://github.com/jquery/jquery/issues/5194#issuecomment-1406546151) about these differences.

Due to the above issues, we're considering reverting to the previous behavior and relying on `qSA` in `try-catch` and just marking `:has()` as buggy in all browsers where it's still forgiving (i.e. now both Chrome & Safari but that should change soon). However, we'd feel safer hearing some assurances that we won't hit a similar issue with other pseudos that we've just gone through with `:has()`. The comment https://github.com/w3c/csswg-drafts/issues/7676#issuecomment-1341347244 and the spec[^spec-forgiving-selector] suggest the list is fixed and no future selectors will ever use forgiving parsing other than `:is()` or `:where()` but I wanted to double check. We'd only have problems if such a pseudo matched another one implemented by jQuery, i.e. roughly anything from [Selectors Level 3](https://www.w3.org/TR/selectors-3/) or any of the [jQuery extensions](https://api.jquery.com/category/selectors/jquery-selector-extensions/) like [`:contains()`](https://api.jquery.com/contains-selector/) or [`:eq()`](https://api.jquery.com/eq-selector/).

jQuery doesn't currently plan to implement `:is()` or `:where()` in its custom traversal; if it one day does, it will be a complete rewrite of the selector module so this discussion will likely be irrelevant.

[^spec-non-forgiving-supports]: https://w3c.github.io/csswg-drafts/css-conditional-4/#dfn-support-selector
[^spec-forgiving-selector]: https://drafts.csswg.org/selectors/#forgiving-selector

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/8378 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Monday, 30 January 2023 22:08:34 UTC