Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Selector: Use jQuery
:has
if CSS.supports(selector(...))
non-comp…
…liant 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 gh-5098 Closes gh-5107 Ref w3c/csswg-drafts#7676
- Loading branch information
Showing
5 changed files
with
97 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,38 @@ | ||
import isIE from "../var/isIE.js"; | ||
import whitespace from "../var/whitespace.js"; | ||
import support from "./support.js"; | ||
|
||
var rbuggyQSA = isIE && new RegExp( | ||
var rbuggyQSA = []; | ||
|
||
// Support: IE 9 - 11+ | ||
// IE's :disabled selector does not pick up the children of disabled fieldsets | ||
":enabled|:disabled|" + | ||
if ( isIE ) { | ||
rbuggyQSA.push( | ||
|
||
// Support: IE 11+ | ||
// IE 11 doesn't find elements on a `[name='']` query in some cases. | ||
// Adding a temporary attribute to the document before the selection works | ||
// around the issue. | ||
"\\[" + whitespace + "*name" + whitespace + "*=" + | ||
whitespace + "*(?:''|\"\")" | ||
// Support: IE 9 - 11+ | ||
// IE's :disabled selector does not pick up the children of disabled fieldsets | ||
":enabled", | ||
":disabled", | ||
|
||
); | ||
// Support: IE 11+ | ||
// IE 11 doesn't find elements on a `[name='']` query in some cases. | ||
// Adding a temporary attribute to the document before the selection works | ||
// around the issue. | ||
"\\[" + whitespace + "*name" + whitespace + "*=" + | ||
whitespace + "*(?:''|\"\")" | ||
); | ||
} | ||
|
||
if ( !support.cssSupportsSelector ) { | ||
|
||
// Support: Chrome 105+, Safari 15.4+ | ||
// `:has()` uses a forgiving selector list as an argument so our regular | ||
// `try-catch` mechanism fails to catch `:has()` with arguments not supported | ||
// natively like `:has(:contains("Foo"))`. Where supported & spec-compliant, | ||
// we now use `CSS.supports("selector(SELECTOR_TO_BE_TESTED)")` but outside | ||
// that, let's mark `:has` as buggy to always use jQuery traversal for | ||
// `:has()`. | ||
rbuggyQSA.push( ":has" ); | ||
} | ||
|
||
rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); | ||
|
||
export default rbuggyQSA; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import support from "../var/support.js"; | ||
|
||
try { | ||
/* eslint-disable no-undef */ | ||
|
||
// Support: Chrome 105+, Firefox 104+, Safari 15.4+ | ||
// Make sure forgiving mode is not used in `CSS.supports( "selector(...)" )`. | ||
// | ||
// `:is()` uses a forgiving selector list as an argument and is widely | ||
// implemented, so it's a good one to test against. | ||
support.cssSupportsSelector = CSS.supports( "selector(*)" ) && | ||
|
||
// `*` is needed as Safari & newer Chrome implemented something in between | ||
// for `:has()` - it throws in `qSA` if it only contains an unsupported | ||
// argument but multiple ones, one of which is supported, are fine. | ||
// We want to play safe in case `:is()` gets the same treatment. | ||
!CSS.supports( "selector(:is(*,:jqfake))" ); | ||
|
||
/* eslint-enable */ | ||
} catch ( e ) { | ||
support.cssSupportsSelector = false; | ||
} | ||
|
||
export default support; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters