]> source.dussan.org Git - jquery.git/commitdiff
CSS:Selector: Align with 3.x, remove the outer `selector.js` wrapper
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Wed, 20 Sep 2023 00:31:35 +0000 (02:31 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Sep 2023 00:31:35 +0000 (02:31 +0200)
Bring some changes from `3.x-stable`:
* rename `rtrim` to `rtrimCSS` to distinguish from the previous `rtrim`
  regex used for `jQuery.trim`
* backport one `id` selector test that avoids the selector engine path

Other changes:
* remove the inner function wrapper from `selector.js` by renaming
  the imported `document.js` value
* use `jQuery.error` in `selectorError`
* make Selector tests pass in all-modules runs by fixing a sinon mistake
  in Core tests - Core tests had a spy set up for `jQuery.error` that wasn't
  cleaned up, influencing Selector tests when all were run together

Closes gh-5295

src/css/curCSS.js
src/selector.js
src/selector/rbuggyQSA.js
src/selector/selectorError.js
src/selector/tokenize.js
src/var/rtrim.js [deleted file]
src/var/rtrimCSS.js [new file with mode: 0644]
test/unit/core.js
test/unit/selector.js

index 16104d893f3252b029a7a7156a0c53f554f97908..b0f0a755516edd7787a4c4a4ff529f8846ff1d06 100644 (file)
@@ -2,7 +2,7 @@ import { jQuery } from "../core.js";
 import { isAttached } from "../core/isAttached.js";
 import { getStyles } from "./var/getStyles.js";
 import { rcustomProp } from "./var/rcustomProp.js";
-import { rtrim } from "../var/rtrim.js";
+import { rtrimCSS } from "../var/rtrimCSS.js";
 
 export function curCSS( elem, name, computed ) {
        var ret,
@@ -41,12 +41,12 @@ export function curCSS( elem, name, computed ) {
                        // allowing us to differentiate them without a performance penalty
                        // and returning `undefined` aligns with older jQuery.
                        //
-                       // rtrim treats U+000D CARRIAGE RETURN and U+000C FORM FEED
+                       // rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED
                        // as whitespace while CSS does not, but this is not a problem
                        // because CSS preprocessing replaces them with U+000A LINE FEED
                        // (which *is* CSS whitespace)
                        // https://www.w3.org/TR/css-syntax-3/#input-preprocessing
-                       ret = ret.replace( rtrim, "$1" ) || undefined;
+                       ret = ret.replace( rtrimCSS, "$1" ) || undefined;
                }
 
                if ( ret === "" && !isAttached( elem ) ) {
index 92bfcfed334dc7674f737c9a397a32ed72947724..d71e65ad4a99b4c02dec65dcde5559ead8553b49 100644 (file)
@@ -1,12 +1,12 @@
 import { jQuery } from "./core.js";
 import { nodeName } from "./core/nodeName.js";
-import { document } from "./var/document.js";
+import { document as preferredDoc } from "./var/document.js";
 import { indexOf } from "./var/indexOf.js";
 import { pop } from "./var/pop.js";
 import { push } from "./var/push.js";
 import { whitespace } from "./var/whitespace.js";
 import { rbuggyQSA } from "./selector/rbuggyQSA.js";
-import { rtrim } from "./var/rtrim.js";
+import { rtrimCSS } from "./var/rtrimCSS.js";
 import { isIE } from "./var/isIE.js";
 import { identifier } from "./selector/var/identifier.js";
 import { booleans } from "./selector/var/booleans.js";
@@ -27,10 +27,6 @@ import { toSelector } from "./selector/toSelector.js";
 import "./selector/escapeSelector.js";
 import "./selector/uniqueSort.js";
 
-var preferredDoc = document;
-
-( function() {
-
 var i,
        outermostContext,
 
@@ -167,7 +163,11 @@ function find( selector, context, results, seed ) {
 
                                        // Outside of IE, if we're not changing the context we can
                                        // use :scope instead of an ID.
-                                       if ( newContext !== context || isIE ) {
+                                       // Support: IE 11+
+                                       // IE sometimes throws a "Permission denied" error when strict-comparing
+                                       // two documents; shallow comparisons work.
+                                       // eslint-disable-next-line eqeqeq
+                                       if ( newContext != context || isIE ) {
 
                                                // Capture the context ID, setting it first if necessary
                                                if ( ( nid = context.getAttribute( "id" ) ) ) {
@@ -204,7 +204,7 @@ function find( selector, context, results, seed ) {
        }
 
        // All others
-       return select( selector.replace( rtrim, "$1" ), context, results, seed );
+       return select( selector.replace( rtrimCSS, "$1" ), context, results, seed );
 }
 
 /**
@@ -632,7 +632,7 @@ jQuery.expr = {
                        // spaces as combinators
                        var input = [],
                                results = [],
-                               matcher = compile( selector.replace( rtrim, "$1" ) );
+                               matcher = compile( selector.replace( rtrimCSS, "$1" ) );
 
                        return matcher[ jQuery.expando ] ?
                                markFunction( function( seed, matches, _context, xml ) {
@@ -1070,7 +1070,12 @@ function matcherFromTokens( tokens ) {
                        return indexOf.call( checkContext, elem ) > -1;
                }, implicitRelative, true ),
                matchers = [ function( elem, context, xml ) {
-                       var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+
+                       // Support: IE 11+
+                       // IE sometimes throws a "Permission denied" error when strict-comparing
+                       // two documents; shallow comparisons work.
+                       // eslint-disable-next-line eqeqeq
+                       var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || (
                                ( checkContext = context ).nodeType ?
                                        matchContext( elem, context, xml ) :
                                        matchAnyContext( elem, context, xml ) );
@@ -1104,7 +1109,7 @@ function matcherFromTokens( tokens ) {
                                                // If the preceding token was a descendant combinator, insert an implicit any-element `*`
                                                tokens.slice( 0, i - 1 )
                                                        .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
-                                       ).replace( rtrim, "$1" ),
+                                       ).replace( rtrimCSS, "$1" ),
                                        matcher,
                                        i < j && matcherFromTokens( tokens.slice( i, j ) ),
                                        j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
@@ -1369,6 +1374,4 @@ find.select = select;
 find.setDocument = setDocument;
 find.tokenize = tokenize;
 
-} )();
-
 export { jQuery, jQuery as $ };
index 7e4632c7fa8623595aedaeaaea504801671fbfa5..b056ffe752320ac46168f7f54b63d2ace6de843c 100644 (file)
@@ -2,6 +2,8 @@ import { isIE } from "../var/isIE.js";
 import { whitespace } from "../var/whitespace.js";
 import { support } from "./support.js";
 
+// Build QSA regex.
+// Regex strategy adopted from Diego Perini.
 export var rbuggyQSA = [];
 
 if ( isIE ) {
index 69770ec6a8f304122fd63bbd2da6c53ed4e71edb..da2b239f97fb922747d19a0cc0cb3d2c01c91865 100644 (file)
@@ -1,3 +1,5 @@
+import { jQuery } from "../core.js";
+
 export function selectorError( msg ) {
-       throw new Error( "Syntax error, unrecognized expression: " + msg );
+       jQuery.error( "Syntax error, unrecognized expression: " + msg );
 }
index 3c1e06c460f7d17f017c4819bafb07aac5cefc9f..fb25cb2074481055341488f36eb5077c81651d1c 100644 (file)
@@ -1,7 +1,7 @@
 import { jQuery } from "../core.js";
 import { rcomma } from "./var/rcomma.js";
 import { rleadingCombinator } from "./var/rleadingCombinator.js";
-import { rtrim } from "../var/rtrim.js";
+import { rtrimCSS } from "../var/rtrimCSS.js";
 import { createCache } from "./createCache.js";
 import { selectorError } from "./selectorError.js";
 import { filterMatchExpr } from "./filterMatchExpr.js";
@@ -42,7 +42,7 @@ export function tokenize( selector, parseOnly ) {
                                value: matched,
 
                                // Cast descendant combinators to space
-                               type: match[ 0 ].replace( rtrim, " " )
+                               type: match[ 0 ].replace( rtrimCSS, " " )
                        } );
                        soFar = soFar.slice( matched.length );
                }
diff --git a/src/var/rtrim.js b/src/var/rtrim.js
deleted file mode 100644 (file)
index aa20c96..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-import { whitespace } from "./whitespace.js";
-
-export var rtrim = new RegExp(
-       "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
-       "g"
-);
diff --git a/src/var/rtrimCSS.js b/src/var/rtrimCSS.js
new file mode 100644 (file)
index 0000000..f35b8a1
--- /dev/null
@@ -0,0 +1,6 @@
+import { whitespace } from "./whitespace.js";
+
+export var rtrimCSS = new RegExp(
+       "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
+       "g"
+);
index 666f0e8204f6c2b2c90851160d398737042b4be5..aa1f637dd34a324e97931076a5a308caaec509be 100644 (file)
@@ -1460,7 +1460,7 @@ QUnit.testUnlessIE( "jQuery.parseXML - error reporting", function( assert ) {
 
        var errorArg, lineMatch, line, columnMatch, column;
 
-       sinon.stub( jQuery, "error" );
+       this.sandbox.stub( jQuery, "error" );
 
        jQuery.parseXML( "<p>Not a <<b>well-formed</b> xml string</p>" );
        errorArg = jQuery.error.firstCall.lastArg.toLowerCase();
index cf36b1dbb4ab9226840f590aa8943aa36655e26a..d6f28e25b980bf48e24d854bb3d8470d41b16f23 100644 (file)
@@ -226,9 +226,9 @@ QUnit.test( "broken selectors throw", function( assert ) {
 } );
 
 QUnit.test( "id", function( assert ) {
-       assert.expect( 34 );
+       assert.expect( 35 );
 
-       var fiddle, a;
+       var fiddle, a, lengthtest;
 
        assert.t( "ID Selector", "#body", [ "body" ] );
        assert.t( "ID Selector w/ Element", "body#body", [ "body" ] );
@@ -283,6 +283,15 @@ QUnit.test( "id", function( assert ) {
 
        assert.t( "ID Selector on Form with an input that has a name of 'id'", "#lengthtest", [ "lengthtest" ] );
 
+       // Run the above test again but with `jQuery.find` directly to avoid the jQuery
+       // quick path that avoids running the selector engine.
+       lengthtest = jQuery.find( "#lengthtest" );
+       assert.strictEqual(
+               lengthtest && lengthtest[ 0 ],
+               document.getElementById( "lengthtest" ),
+               "ID Selector on Form with an input that has a name of 'id' - no quick path (#lengthtest)"
+       );
+
        assert.t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug trac-986
 
        assert.deepEqual( jQuery( "div#form", document.body ).get(), [],