Skip to content

unsupported pseudo: valid with selector list #5177

Closed
jquery/sizzle
#491

Description

@antti-manninen-vmv

Description

After upgrading to jQuery 3.6.2 pseudo selector :valid does not work in selector list with Firefox and Safari. Everything works with Chrome.

This worked in 3.6.1

jQuery('body').find('div:valid, span')

In 3.6.2 it gives following error:

Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: valid

This still works with old and new versions with Firefox and Safari:

jQuery('body').find('div:valid')

Activity

  1. mgol commented on Dec 17, 2022

    @mgol
    Member

    Thanks for the report!

    jQuery has a mechanism of - simplifying a bit - trying a provided selector against querySelectorAll in a try-catch and, if it fails, falling back to its own traversal mechanism inherited from Sizzle.

    In jQuery 3.6.2 we started using CSS.supports( "selector(SELECTOR)" ) (for a proper SELECTOR) before using querySelectorAll on the selector. This was to solve #5098 - some selectors, like :is(), now have their parameters parsed in a forgiving way, meaning that :is(: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. This change has only arrived in Firefox stable so far, though.

    Now, apparently, our implementation has a bug - in CSS.supports( "selector(SELECTOR)" ), SELECTOR needs to be a <complex-selector> and not a <complex-selector-list>. Which means:

    CSS.supports("selector(div:valid, span)"); // false
    CSS.supports("selector(div:valid)"); // true
    CSS.supports("selector(span)"); // true

    and explains your observations. See the live test case: https://jsbin.com/vesureh/1/edit?html,js,console

    Now, I only see this behavior in Firefox as that's the only browser passing our support test. In which version of Safari are you also seeing it? Please share a test case that breaks there.

    I see two ways of fixing this:

    1. Use CSS.supports() earlier, when we still have the selector split into groups.
    2. Use CSS.supports( "selector(:is(SELECTOR))" ) instead of CSS.supports( "selector(SELECTOR)" )

    The second solution definitely only makes sense only in browsers that implement non-forgiving parsing in CSS.supports( "selector(...)" ) but we're already limiting our usage to such browsers so we should be fine with it, I think.

    I'm tagging it for 3.6.3, we'll discuss this on our next team meeting.

  2. self-assigned this
    on Dec 17, 2022
  3. added
    Discuss in MeetingReserved for Issues and PRs that anyone would like to discuss in the weekly meeting.
    on Dec 17, 2022
  4. added this to the 3.6.3 milestone on Dec 17, 2022
  5. mgol commented on Dec 17, 2022

    @mgol
    Member

    BTW, in many cases, the only consequence of this bug would be performance issues as more selectors go through the jQuery selector engines instead of querySelectorAll. This one surfaced because jQuery doesn't support the :valid pseudo-class so such a selector can only work if the qSA code path is used.

  6. added a commit that references this issue on Dec 17, 2022
    3376c15
  7. added 5 commits that reference this issue on Dec 17, 2022
    4255ed6
    7f8a7a8
    71f6ecd
    d217318
    4ba83c9
  8. mgol commented on Dec 17, 2022

    @mgol
    Member

    PRs:

  9. added a commit that references this issue on Dec 17, 2022
    48b0c88
  10. antti-manninen-vmv commented on Dec 19, 2022

    @antti-manninen-vmv
    Author

    My mistake, Safari does not have this problem. I only saw it with Firefox.

    Thanks for quick handling of the problem!

  11. removed
    Discuss in MeetingReserved for Issues and PRs that anyone would like to discuss in the weekly meeting.
    on Dec 19, 2022
  12. added 4 commits that reference this issue on Dec 19, 2022
    7781b65
    09d988b
    8989500
    848de62
  13. mgol commented on Dec 19, 2022

    @mgol
    Member

    The fix landed on main (future jQuery 4.0.0) in 09d988b and on 3.x-stable (future jQuery 3.7.0) in 848de62.

    It also landed in Sizzle in jquery/sizzle@7781b65. Then, Sizzle got updated on 3.6-stable (future jQuery 3.6.3) in 8989500.

    The fix & all the backports are done.

  14. mgol commented on Dec 20, 2022

    @mgol
    Member

    @antti-manninen-vmv jQuery 3.6.3 containing the fix for this issue has been released: https://blog.jquery.com/2022/12/20/jquery-3-6-3-released-a-quick-selector-fix/. That's the only source difference from 3.6.2.

    Thanks for reporting it!

  15. khetaramsb commented on Jan 13, 2023

    @khetaramsb

    After upgrading jQuery from 3.6.0 to3.6.3 pseudo selector :before does not work in selector list with Firefox. Everything works with Chrome.

    This worked in 3.6.0
    jQuery(".inline-dialog-content:before").css({'left': 40});

    In 3.6.3 it gives following error:

    Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: before

  16. mgol commented on Jan 13, 2023

    @mgol
    Member

    @khetaramsb let's move the discussion to #5194.

  17. locked as resolved and limited conversation to collaborators on Sep 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions