CSS:Selector: Align with 3.x, remove the outer selector.js wrapper

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
This commit is contained in:
Michał Gołębiowski-Owczarek 2023-09-20 02:31:35 +02:00 committed by GitHub
parent 5f86959092
commit 53cf7244da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 39 additions and 23 deletions

View 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 ) ) {

View 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 $ };

View 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 ) {

View 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 );
}

View 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 );
}

View File

@ -1,6 +1,6 @@
import { whitespace } from "./whitespace.js";
export var rtrim = new RegExp(
export var rtrimCSS = new RegExp(
"^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$",
"g"
);

View 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();

View 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(), [],