Skip to content
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

[selectors] May new pseudos using forgiving parsing be introduced in the future? #8378

Closed
mgol opened this issue Jan 30, 2023 · 2 comments
Closed
Labels
Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered. selectors-4 Current Work

Comments

@mgol
Copy link

mgol commented Jan 30, 2023

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(...)" ) which was made always non-forgiving1, 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 reports 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 #7676 (comment) and the spec2 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 or any of the jQuery extensions like :contains() or :eq().

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.

Footnotes

  1. https://w3c.github.io/csswg-drafts/css-conditional-4/#dfn-support-selector

  2. https://drafts.csswg.org/selectors/#forgiving-selector

@tabatkins
Copy link
Member

We don't expect to introduce any more forgiving-selector-list functions, no. :is() and :where() suffice to express the semantics we need, and are short enough that we think it's fine to rely on authors nesting them into other places when they do need forgiving behavior.

(We're not binding our future selves to this, but this is our expectation. If we ever do extend it, we'll know about this potential issue ahead of time and do compat work for it.)

@tabatkins tabatkins added selectors-4 Current Work Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered. labels Jan 30, 2023
@mgol
Copy link
Author

mgol commented Jan 31, 2023

Thank you for a prompt reply!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered. selectors-4 Current Work
2 participants