-
Notifications
You must be signed in to change notification settings - Fork 711
[selectors] [css-conditional] Detecting :has() restrictions #7280
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
Comments
I think this is a good way to detect the limitations without losing the benefits of forgiving parsing. Currently, pseudo-elements are explicitly disallowed inside If
How about others? |
The CSS Working Group just discussed
The full IRC log of that discussion<fantasai> Topic: [selectors] [css-conditional] Detecting :has() restrictions<fantasai> github: https://github.com//issues/7280 <fantasai> emilio: It seems this is not going to have so many restrictions, so maybe not a big deal <fantasai> emilio: In case we wanted to restrict stuff like :host <fantasai> emilio: and then eventually potentially ... <fantasai> emilio: not easy to detect which UAs would support it vs not <fantasai> emilio: since :has() uses forgiving parsing, anything you throw at it is valid <fantasai> emilio: It seems we're only going to restrict :has() inside :has() <fantasai> emilio: doesn't seem useful but complex, but may still matter... <fantasai> emilio: My point is that if we have any hope for unrestricting, it may be useful to be able to detect it when we do <jensimmons> +1000 <fantasai> emilio: If you put @supports :has(:has()) ... <fantasai> emilio: makes it a problem if you want to do something in the future <jensimmons> =Q <jensimmons> +q <fantasai> emilio: you can always test the thing inside <fantasai> TabAtkins: not true <fantasai> TabAtkins: :is()-disallowed pseudo-elements, for example <fantasai> TabAtkins: this sounds reasonable to me <fantasai> TabAtkins: unsure about forgiving vs unforgiving <astearns> ack jensimmons <fantasai> jensimmons: I think it's a really good idea <oriol> q+ <fantasai> jensimmons: Having @supports parse as valid a thing that the browser doesn't support <fantasai> jensimmons: for the future, we need @supports to be accurate and true <fantasai> emilio: For FF it's easy, just passing down a flag <astearns> ack oriol <fantasai> oriol: I wonder if rather than adding hack in supports we could say that if you have either :has() or whatever that has this forgiving syntax, and all of the selectors inside it are invalid, then it would also be invalid <fantasai> oriol: It would be something like, if you have some invalid and some valid treat whole as invalid <fantasai> oriol: So if you only have invalid ones, it would be invalid. If you have a mix, it would be valid <emilio> oriol is saying that `:has(:random)` would be valid, but `:has(something, :random)` would be valid <astearns> s/whole as invalid/whole as valid/ <fantasai> oriol: So if using :has(invalid) then is invalid, and detect that without having to make supports change the syntax <fantasai> fantasai: OK, so I'm with jensimmons here. If the selector contains anything invalid, then it should return as invalid even if the invalidity is caught at a lower level <fantasai> emilio: Some precedent here wrt -webkit- stuff <fantasai> jensimmons: If this occurred to me as a developer, I wouldn't look it up. I would use @supports to detect support, e.g with color:red <fantasai> emilio: Especially if CSS author, unlikely to jump to using JS to check <fantasai> astearns: So proposed resolution is for @supports to use non-forgiving parsing for all selectors <fantasai> TabAtkins: yes <fantasai> strong +1 <fantasai> RESOLVED: @supports uses non-forgiving parsing for all selectors |
It looks like this would affect at-supports-046.html which assumes forgiving parsing? (wpt results) |
@svgeesus No, that test is fine. This is about the contents of the |
…or that do not invalidate the selector cause the selector to be unsupported nonetheless. #7280
To detect invalid selector usage, always do unforgiving parsing for all selectors inside @support according to the csswg issue resolution: w3c/csswg-drafts#7280 (comment) Bug: 1358953, 1359396 Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
To detect invalid selector usage, always do unforgiving parsing for all selectors inside `@support selector()` according to the csswg issue resolution: - w3c/csswg-drafts#7280 Bug: 1358953, 1359396 Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
To detect errors in forgiving parsing selectors (e.g. :is(), :has()) with '@supports selector()', CSSSelectorParser parses all selectors unforgiving way to raise error while checking the selectors with '@supports selector()` according to the csswg issue resolution: w3c/csswg-drafts#7280 (comment) Bug: 1358953, 1359396 Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
To detect errors in forgiving parsing selectors (e.g. :is(), :has()) with '@supports selector()', CSSSelectorParser parses all selectors unforgiving way to raise error while checking the selectors with '@supports selector()` according to the csswg issue resolution: w3c/csswg-drafts#7280 (comment) Bug: 1358953, 1359396 Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
To detect errors in forgiving parsing selectors (e.g. :is(), :has()) with '@supports selector()', CSSSelectorParser parses all selectors unforgiving way to raise error while checking the selectors with '@supports selector()` according to the csswg issue resolution: w3c/csswg-drafts#7280 (comment) Bug: 1358953, 1359396 Change-Id: If203c8d6124edbf67b1ebf0f58cf1a01b31c90a6
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 jquerygh-5098
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 jquerygh-5098
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 jquerygh-5098
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 jquerygh-5098
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 jquerygh-5098
Rejecting CSS.supports(":is()") is the correct thing to do per w3c/csswg-drafts#7280 Fixes cockpit-project#17724.
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
Rejecting CSS.supports(":is()") is the correct thing to do per w3c/csswg-drafts#7280 Fixes cockpit-project#17724. https://bugzilla.redhat.com/show_bug.cgi?id=2129055 Cherry-picked from main commit ce351ca.
Rejecting CSS.supports(":is()") is the correct thing to do per w3c/csswg-drafts#7280 Fixes #17724. https://bugzilla.redhat.com/show_bug.cgi?id=2129055 Cherry-picked from main commit ce351ca.
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
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. Ref jquerygh-5098 Ref jquerygh-5107 Ref jquery/sizzle#486 Ref w3c/csswg-drafts#7676
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors, like `:has()`, now have 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 jquerygh-5177 Ref w3c/csswg-drafts#7280
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors, like `:has()`, now have 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 jquerygh-5177 Ref w3c/csswg-drafts#7280
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquerygh-5098 - some selectors, like `:has()`, now have 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 jquerygh-5177 Ref w3c/csswg-drafts#7280
jQuery 3.6.2 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquerygh-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 jquerygh-5177 Ref w3c/csswg-drafts#7280
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquery/jquery#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 Sizzle 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 Sizzle 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 Sizzle 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 jquery/jquery#5177 Ref w3c/csswg-drafts#7280
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquery/jquery#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 Sizzle 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 Sizzle 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 Sizzle 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 jquery/jquery#5177 Ref w3c/csswg-drafts#7280
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquery/jquery#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 Sizzle 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 Sizzle 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 Sizzle 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 jquery/jquery#5177 Ref w3c/csswg-drafts#7280
Sizzle 2.3.7 started using `CSS.supports( "selector(SELECTOR)" )` before using `querySelectorAll` on the selector. This was to solve jquery/jquery#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 Sizzle 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 Sizzle 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 Sizzle 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 jquery/jquery#5177 Closes gh-491 Ref w3c/csswg-drafts#7280
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
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 (cherry picked from commit 09d988b)
…ngParsing Enable these two features by default. CSSAtSupportsAlwaysNonForgivingParsing: - Apply the csswg issue resolution: change '@supports' selector parsing. - w3c/csswg-drafts#7280 (comment) CSSPseudoHasNonForgivingParsing: - Apply the csswg issue resolution: make ':has()' non-forgiving. - w3c/csswg-drafts#7676 (comment) Intent-to-ship: https://groups.google.com/u/1/a/chromium.org/g/blink-dev/c/RJrIxJA9LYw Bug: 1359396, 1399744 Change-Id: I179f22074f5cf6c9c8d56e36a4e3360bfe892256 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4224863 Reviewed-by: Rune Lillesveen <[email protected]> Commit-Queue: Byungwoo Lee <[email protected]> Cr-Commit-Position: refs/heads/main@{#1102139}
As per spec, see w3c/csswg-drafts#7280 Differential Revision: https://phabricator.services.mozilla.com/D156468
As per spec, see w3c/csswg-drafts#7280 Differential Revision: https://phabricator.services.mozilla.com/D156468
As per spec, see w3c/csswg-drafts#7280 Differential Revision: https://phabricator.services.mozilla.com/D156468
As per spec, see w3c/csswg-drafts#7280 Differential Revision: https://phabricator.services.mozilla.com/D156468
Multiple implementations want to ship the
:has()
selector with a variety of limitations in order to prevent performance footguns and complexity:However, since
:has()
has forgiving parsing like:is()
/:where()
, it's not possible to detect these limitations easily, and it won't be possible to do so if we ever remove these limitations.For
:is()
/:where()
it's not a problem since it's generally assumed that if the selector is valid outside of them it'll be valid inside of them... But for the limitations that folks are imposing on:has()
(and which for the record I agree with) this is not true.Perhaps we should special-case
@supports selector(..)
to not use forgiving parsing? Otherwise the only way to potentially detect this is with script (by reading back the serialization of:has()
and see if the relevant selectors have been dropped).cc @byung-woo @anttijk
The text was updated successfully, but these errors were encountered: