jquery / sizzle

A sizzlin' hot selector engine.
https://sizzlejs.com
Other
6.29k stars 951 forks source link

Selector: Use Sizzle `:has` if `CSS.supports(selector(...))` non-compliant #486

Closed mgol closed 2 years ago

mgol commented 2 years ago

Sizzle 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 Sizzle 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:

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: https://github.com/w3c/csswg-drafts/issues/7280#issuecomment-1143852187 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 jquery/jquery#5098 Ref jquery/jquery#5107

+78 bytes

mgol commented 2 years ago

jQuery version of this PR for jQuery 4.0.0: https://github.com/jquery/jquery/pull/5107

mgol commented 2 years ago

I run tests on this PR with a CP from https://github.com/jquery/sizzle/pull/485 locally on the same browsers on which they're run on CI and all passed.