Build: Take core-js-bundle from the external directory as well
[jquery.git] / src / selector.js
blobf7e8d9b60735847f5cd09c72d2111c41758a6086
1 import jQuery from "./core.js";
2 import nodeName from "./core/nodeName.js";
3 import document from "./var/document.js";
4 import documentElement from "./var/documentElement.js";
5 import indexOf from "./var/indexOf.js";
6 import pop from "./var/pop.js";
7 import push from "./var/push.js";
8 import whitespace from "./selector/var/whitespace.js";
9 import rbuggyQSA from "./selector/rbuggyQSA.js";
10 import isIE from "./var/isIE.js";
12 // The following utils are attached directly to the jQuery object.
13 import "./selector/contains.js";
14 import "./selector/escapeSelector.js";
15 import "./selector/uniqueSort.js";
17 var preferredDoc = document,
18         matches = documentElement.matches || documentElement.msMatchesSelector;
20 ( function() {
22 var i,
23         Expr,
24         outermostContext,
26         // Local document vars
27         document,
28         documentElement,
29         documentIsHTML,
31         // Instance-specific data
32         expando = jQuery.expando,
33         dirruns = 0,
34         done = 0,
35         classCache = createCache(),
36         tokenCache = createCache(),
37         compilerCache = createCache(),
38         nonnativeSelectorCache = createCache(),
40         booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" +
41                 "loop|multiple|open|readonly|required|scoped",
43         // Regular expressions
45         // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
46         identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
47                 "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
49         // Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors
50         attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
52                 // Operator (capture 2)
53                 "*([*^$|!~]?=)" + whitespace +
55                 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
56                 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" +
57                 whitespace + "*\\]",
59         pseudos = ":(" + identifier + ")(?:\\((" +
61                 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
62                 // 1. quoted (capture 3; capture 4 or capture 5)
63                 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
65                 // 2. simple (capture 6)
66                 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
68                 // 3. anything else (capture 2)
69                 ".*" +
70                 ")\\)|)",
72         // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
73         rwhitespace = new RegExp( whitespace + "+", "g" ),
74         rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
76         rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
77         rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" +
78                 whitespace + "*" ),
79         rdescend = new RegExp( whitespace + "|>" ),
81         rpseudo = new RegExp( pseudos ),
82         ridentifier = new RegExp( "^" + identifier + "$" ),
84         matchExpr = {
85                 ID: new RegExp( "^#(" + identifier + ")" ),
86                 CLASS: new RegExp( "^\\.(" + identifier + ")" ),
87                 TAG: new RegExp( "^(" + identifier + "|[*])" ),
88                 ATTR: new RegExp( "^" + attributes ),
89                 PSEUDO: new RegExp( "^" + pseudos ),
90                 CHILD: new RegExp(
91                         "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" +
92                                 whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" +
93                                 whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
94                 bool: new RegExp( "^(?:" + booleans + ")$", "i" ),
96                 // For use in libraries implementing .is()
97                 // We use this for POS matching in `select`
98                 needsContext: new RegExp( "^" + whitespace +
99                         "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
100                         "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
101         },
103         rinputs = /^(?:input|select|textarea|button)$/i,
104         rheader = /^h\d$/i,
106         // Easily-parseable/retrievable ID or TAG or CLASS selectors
107         rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
109         rsibling = /[+~]/,
111         // CSS escapes
112         // https://www.w3.org/TR/CSS21/syndata.html#escaped-characters
113         runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace +
114                 "?|\\\\([^\\r\\n\\f])", "g" ),
115         funescape = function( escape, nonHex ) {
116                 var high = "0x" + escape.slice( 1 ) - 0x10000;
118                 if ( nonHex ) {
120                         // Strip the backslash prefix from a non-hex escape sequence
121                         return nonHex;
122                 }
124                 // Replace a hexadecimal escape sequence with the encoded Unicode code point
125                 // Support: IE <=11+
126                 // For values outside the Basic Multilingual Plane (BMP), manually construct a
127                 // surrogate pair
128                 return high < 0 ?
129                         String.fromCharCode( high + 0x10000 ) :
130                         String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
131         },
133         // Used for iframes; see `setDocument`.
134         // Support: IE 9 - 11+
135         // Removing the function wrapper causes a "Permission Denied"
136         // error in IE.
137         unloadHandler = function() {
138                 setDocument();
139         },
141         inDisabledFieldset = addCombinator(
142                 function( elem ) {
143                         return elem.disabled === true && nodeName( elem, "fieldset" );
144                 },
145                 { dir: "parentNode", next: "legend" }
146         );
148 function selectorError( msg ) {
149         throw new Error( "Syntax error, unrecognized expression: " + msg );
152 function find( selector, context, results, seed ) {
153         var m, i, elem, nid, match, groups, newSelector,
154                 newContext = context && context.ownerDocument,
156                 // nodeType defaults to 9, since context defaults to document
157                 nodeType = context ? context.nodeType : 9;
159         results = results || [];
161         // Return early from calls with invalid selector or context
162         if ( typeof selector !== "string" || !selector ||
163                 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
165                 return results;
166         }
168         // Try to shortcut find operations (as opposed to filters) in HTML documents
169         if ( !seed ) {
170                 setDocument( context );
171                 context = context || document;
173                 if ( documentIsHTML ) {
175                         // If the selector is sufficiently simple, try using a "get*By*" DOM method
176                         // (excepting DocumentFragment context, where the methods don't exist)
177                         if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
179                                 // ID selector
180                                 if ( ( m = match[ 1 ] ) ) {
182                                         // Document context
183                                         if ( nodeType === 9 ) {
184                                                 if ( ( elem = context.getElementById( m ) ) ) {
185                                                         push.call( results, elem );
186                                                 }
187                                                 return results;
189                                         // Element context
190                                         } else {
191                                                 if ( newContext && ( elem = newContext.getElementById( m ) ) &&
192                                                         jQuery.contains( context, elem ) ) {
194                                                         push.call( results, elem );
195                                                         return results;
196                                                 }
197                                         }
199                                 // Type selector
200                                 } else if ( match[ 2 ] ) {
201                                         push.apply( results, context.getElementsByTagName( selector ) );
202                                         return results;
204                                 // Class selector
205                                 } else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) {
206                                         push.apply( results, context.getElementsByClassName( m ) );
207                                         return results;
208                                 }
209                         }
211                         // Take advantage of querySelectorAll
212                         if ( !nonnativeSelectorCache[ selector + " " ] &&
213                                 ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) {
215                                 newSelector = selector;
216                                 newContext = context;
218                                 // qSA considers elements outside a scoping root when evaluating child or
219                                 // descendant combinators, which is not what we want.
220                                 // In such cases, we work around the behavior by prefixing every selector in the
221                                 // list with an ID selector referencing the scope context.
222                                 // The technique has to be used as well when a leading combinator is used
223                                 // as such selectors are not recognized by querySelectorAll.
224                                 // Thanks to Andrew Dupont for this technique.
225                                 if ( nodeType === 1 &&
226                                         ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
228                                         // Expand context for sibling selectors
229                                         newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
230                                                 context;
232                                         // Outside of IE, if we're not changing the context we can
233                                         // use :scope instead of an ID.
234                                         if ( newContext !== context || isIE ) {
236                                                 // Capture the context ID, setting it first if necessary
237                                                 if ( ( nid = context.getAttribute( "id" ) ) ) {
238                                                         nid = jQuery.escapeSelector( nid );
239                                                 } else {
240                                                         context.setAttribute( "id", ( nid = expando ) );
241                                                 }
242                                         }
244                                         // Prefix every selector in the list
245                                         groups = tokenize( selector );
246                                         i = groups.length;
247                                         while ( i-- ) {
248                                                 groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
249                                                         toSelector( groups[ i ] );
250                                         }
251                                         newSelector = groups.join( "," );
252                                 }
254                                 try {
255                                         push.apply( results,
256                                                 newContext.querySelectorAll( newSelector )
257                                         );
258                                         return results;
259                                 } catch ( qsaError ) {
260                                         nonnativeSelectorCache( selector, true );
261                                 } finally {
262                                         if ( nid === expando ) {
263                                                 context.removeAttribute( "id" );
264                                         }
265                                 }
266                         }
267                 }
268         }
270         // All others
271         return select( selector.replace( rtrim, "$1" ), context, results, seed );
275  * Create key-value caches of limited size
276  * @returns {function(string, object)} Returns the Object data after storing it on itself with
277  *      property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
278  *      deleting the oldest entry
279  */
280 function createCache() {
281         var keys = [];
283         function cache( key, value ) {
285                 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
286                 if ( keys.push( key + " " ) > Expr.cacheLength ) {
288                         // Only keep the most recent entries
289                         delete cache[ keys.shift() ];
290                 }
291                 return ( cache[ key + " " ] = value );
292         }
293         return cache;
297  * Mark a function for special use by jQuery selector module
298  * @param {Function} fn The function to mark
299  */
300 function markFunction( fn ) {
301         fn[ expando ] = true;
302         return fn;
306  * Returns a function to use in pseudos for input types
307  * @param {String} type
308  */
309 function createInputPseudo( type ) {
310         return function( elem ) {
311                 return nodeName( elem, "input" ) && elem.type === type;
312         };
316  * Returns a function to use in pseudos for buttons
317  * @param {String} type
318  */
319 function createButtonPseudo( type ) {
320         return function( elem ) {
321                 return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) &&
322                         elem.type === type;
323         };
327  * Returns a function to use in pseudos for :enabled/:disabled
328  * @param {Boolean} disabled true for :disabled; false for :enabled
329  */
330 function createDisabledPseudo( disabled ) {
332         // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
333         return function( elem ) {
335                 // Only certain elements can match :enabled or :disabled
336                 // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
337                 // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
338                 if ( "form" in elem ) {
340                         // Check for inherited disabledness on relevant non-disabled elements:
341                         // * listed form-associated elements in a disabled fieldset
342                         //   https://html.spec.whatwg.org/multipage/forms.html#category-listed
343                         //   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
344                         // * option elements in a disabled optgroup
345                         //   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
346                         // All such elements have a "form" property.
347                         if ( elem.parentNode && elem.disabled === false ) {
349                                 // Option elements defer to a parent optgroup if present
350                                 if ( "label" in elem ) {
351                                         if ( "label" in elem.parentNode ) {
352                                                 return elem.parentNode.disabled === disabled;
353                                         } else {
354                                                 return elem.disabled === disabled;
355                                         }
356                                 }
358                                 // Support: IE 6 - 11+
359                                 // Use the isDisabled shortcut property to check for disabled fieldset ancestors
360                                 return elem.isDisabled === disabled ||
362                                         // Where there is no isDisabled, check manually
363                                         elem.isDisabled !== !disabled &&
364                                                 inDisabledFieldset( elem ) === disabled;
365                         }
367                         return elem.disabled === disabled;
369                 // Try to winnow out elements that can't be disabled before trusting the disabled property.
370                 // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
371                 // even exist on them, let alone have a boolean value.
372                 } else if ( "label" in elem ) {
373                         return elem.disabled === disabled;
374                 }
376                 // Remaining elements are neither :enabled nor :disabled
377                 return false;
378         };
382  * Returns a function to use in pseudos for positionals
383  * @param {Function} fn
384  */
385 function createPositionalPseudo( fn ) {
386         return markFunction( function( argument ) {
387                 argument = +argument;
388                 return markFunction( function( seed, matches ) {
389                         var j,
390                                 matchIndexes = fn( [], seed.length, argument ),
391                                 i = matchIndexes.length;
393                         // Match elements found at the specified indexes
394                         while ( i-- ) {
395                                 if ( seed[ ( j = matchIndexes[ i ] ) ] ) {
396                                         seed[ j ] = !( matches[ j ] = seed[ j ] );
397                                 }
398                         }
399                 } );
400         } );
404  * Checks a node for validity as a jQuery selector context
405  * @param {Element|Object=} context
406  * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
407  */
408 function testContext( context ) {
409         return context && typeof context.getElementsByTagName !== "undefined" && context;
413  * Sets document-related variables once based on the current document
414  * @param {Element|Object} [node] An element or document object to use to set the document
415  */
416 function setDocument( node ) {
417         var subWindow,
418                 doc = node ? node.ownerDocument || node : preferredDoc;
420         // Return early if doc is invalid or already selected
421         // Support: IE 11+
422         // IE sometimes throws a "Permission denied" error when strict-comparing
423         // two documents; shallow comparisons work.
424         // eslint-disable-next-line eqeqeq
425         if ( doc == document || doc.nodeType !== 9 ) {
426                 return;
427         }
429         // Update global variables
430         document = doc;
431         documentElement = document.documentElement;
432         documentIsHTML = !jQuery.isXMLDoc( document );
434         // Support: IE 9 - 11+
435         // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
436         // Support: IE 11+
437         // IE sometimes throws a "Permission denied" error when strict-comparing
438         // two documents; shallow comparisons work.
439         // eslint-disable-next-line eqeqeq
440         if ( isIE && preferredDoc != document &&
441                 ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
442                 subWindow.addEventListener( "unload", unloadHandler );
443         }
446 find.matches = function( expr, elements ) {
447         return find( expr, null, null, elements );
450 find.matchesSelector = function( elem, expr ) {
451         setDocument( elem );
453         if ( documentIsHTML &&
454                 !nonnativeSelectorCache[ expr + " " ] &&
455                 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
457                 try {
458                         return matches.call( elem, expr );
459                 } catch ( e ) {
460                         nonnativeSelectorCache( expr, true );
461                 }
462         }
464         return find( expr, document, null, [ elem ] ).length > 0;
467 Expr = jQuery.expr = {
469         // Can be adjusted by the user
470         cacheLength: 50,
472         createPseudo: markFunction,
474         match: matchExpr,
476         find: {
477                 ID: function( id, context ) {
478                         if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
479                                 var elem = context.getElementById( id );
480                                 return elem ? [ elem ] : [];
481                         }
482                 },
484                 TAG: function( tag, context ) {
485                         if ( typeof context.getElementsByTagName !== "undefined" ) {
486                                 return context.getElementsByTagName( tag );
488                                 // DocumentFragment nodes don't have gEBTN
489                         } else {
490                                 return context.querySelectorAll( tag );
491                         }
492                 },
494                 CLASS: function( className, context ) {
495                         if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
496                                 return context.getElementsByClassName( className );
497                         }
498                 }
499         },
501         relative: {
502                 ">": { dir: "parentNode", first: true },
503                 " ": { dir: "parentNode" },
504                 "+": { dir: "previousSibling", first: true },
505                 "~": { dir: "previousSibling" }
506         },
508         preFilter: {
509                 ATTR: function( match ) {
510                         match[ 1 ] = match[ 1 ].replace( runescape, funescape );
512                         // Move the given value to match[3] whether quoted or unquoted
513                         match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" )
514                                 .replace( runescape, funescape );
516                         if ( match[ 2 ] === "~=" ) {
517                                 match[ 3 ] = " " + match[ 3 ] + " ";
518                         }
520                         return match.slice( 0, 4 );
521                 },
523                 CHILD: function( match ) {
525                         /* matches from matchExpr["CHILD"]
526                                 1 type (only|nth|...)
527                                 2 what (child|of-type)
528                                 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
529                                 4 xn-component of xn+y argument ([+-]?\d*n|)
530                                 5 sign of xn-component
531                                 6 x of xn-component
532                                 7 sign of y-component
533                                 8 y of y-component
534                         */
535                         match[ 1 ] = match[ 1 ].toLowerCase();
537                         if ( match[ 1 ].slice( 0, 3 ) === "nth" ) {
539                                 // nth-* requires argument
540                                 if ( !match[ 3 ] ) {
541                                         selectorError( match[ 0 ] );
542                                 }
544                                 // numeric x and y parameters for Expr.filter.CHILD
545                                 // remember that false/true cast respectively to 0/1
546                                 match[ 4 ] = +( match[ 4 ] ?
547                                         match[ 5 ] + ( match[ 6 ] || 1 ) :
548                                         2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" )
549                                 );
550                                 match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" );
552                         // other types prohibit arguments
553                         } else if ( match[ 3 ] ) {
554                                 selectorError( match[ 0 ] );
555                         }
557                         return match;
558                 },
560                 PSEUDO: function( match ) {
561                         var excess,
562                                 unquoted = !match[ 6 ] && match[ 2 ];
564                         if ( matchExpr.CHILD.test( match[ 0 ] ) ) {
565                                 return null;
566                         }
568                         // Accept quoted arguments as-is
569                         if ( match[ 3 ] ) {
570                                 match[ 2 ] = match[ 4 ] || match[ 5 ] || "";
572                         // Strip excess characters from unquoted arguments
573                         } else if ( unquoted && rpseudo.test( unquoted ) &&
575                                 // Get excess from tokenize (recursively)
576                                 ( excess = tokenize( unquoted, true ) ) &&
578                                 // advance to the next closing parenthesis
579                                 ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) {
581                                 // excess is a negative index
582                                 match[ 0 ] = match[ 0 ].slice( 0, excess );
583                                 match[ 2 ] = unquoted.slice( 0, excess );
584                         }
586                         // Return only captures needed by the pseudo filter method (type and argument)
587                         return match.slice( 0, 3 );
588                 }
589         },
591         filter: {
592                 ID: function( id ) {
593                         var attrId = id.replace( runescape, funescape );
594                         return function( elem ) {
595                                 return elem.getAttribute( "id" ) === attrId;
596                         };
597                 },
599                 TAG: function( nodeNameSelector ) {
600                         var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
601                         return nodeNameSelector === "*" ?
603                                 function() {
604                                         return true;
605                                 } :
607                                 function( elem ) {
608                                         return nodeName( elem, expectedNodeName );
609                                 };
610                 },
612                 CLASS: function( className ) {
613                         var pattern = classCache[ className + " " ];
615                         return pattern ||
616                                 ( pattern = new RegExp( "(^|" + whitespace + ")" + className +
617                                         "(" + whitespace + "|$)" ) ) &&
618                                 classCache( className, function( elem ) {
619                                         return pattern.test(
620                                                 typeof elem.className === "string" && elem.className ||
621                                                         typeof elem.getAttribute !== "undefined" &&
622                                                                 elem.getAttribute( "class" ) ||
623                                                         ""
624                                         );
625                                 } );
626                 },
628                 ATTR: function( name, operator, check ) {
629                         return function( elem ) {
630                                 var result = jQuery.attr( elem, name );
632                                 if ( result == null ) {
633                                         return operator === "!=";
634                                 }
635                                 if ( !operator ) {
636                                         return true;
637                                 }
639                                 result += "";
641                                 if ( operator === "=" ) {
642                                         return result === check;
643                                 }
644                                 if ( operator === "!=" ) {
645                                         return result !== check;
646                                 }
647                                 if ( operator === "^=" ) {
648                                         return check && result.indexOf( check ) === 0;
649                                 }
650                                 if ( operator === "*=" ) {
651                                         return check && result.indexOf( check ) > -1;
652                                 }
653                                 if ( operator === "$=" ) {
654                                         return check && result.slice( -check.length ) === check;
655                                 }
656                                 if ( operator === "~=" ) {
657                                         return ( " " + result.replace( rwhitespace, " " ) + " " )
658                                                 .indexOf( check ) > -1;
659                                 }
660                                 if ( operator === "|=" ) {
661                                         return result === check || result.slice( 0, check.length + 1 ) === check + "-";
662                                 }
664                                 return false;
665                         };
666                 },
668                 CHILD: function( type, what, _argument, first, last ) {
669                         var simple = type.slice( 0, 3 ) !== "nth",
670                                 forward = type.slice( -4 ) !== "last",
671                                 ofType = what === "of-type";
673                         return first === 1 && last === 0 ?
675                                 // Shortcut for :nth-*(n)
676                                 function( elem ) {
677                                         return !!elem.parentNode;
678                                 } :
680                                 function( elem, _context, xml ) {
681                                         var cache, outerCache, node, nodeIndex, start,
682                                                 dir = simple !== forward ? "nextSibling" : "previousSibling",
683                                                 parent = elem.parentNode,
684                                                 name = ofType && elem.nodeName.toLowerCase(),
685                                                 useCache = !xml && !ofType,
686                                                 diff = false;
688                                         if ( parent ) {
690                                                 // :(first|last|only)-(child|of-type)
691                                                 if ( simple ) {
692                                                         while ( dir ) {
693                                                                 node = elem;
694                                                                 while ( ( node = node[ dir ] ) ) {
695                                                                         if ( ofType ?
696                                                                                 nodeName( node, name ) :
697                                                                                 node.nodeType === 1 ) {
699                                                                                 return false;
700                                                                         }
701                                                                 }
703                                                                 // Reverse direction for :only-* (if we haven't yet done so)
704                                                                 start = dir = type === "only" && !start && "nextSibling";
705                                                         }
706                                                         return true;
707                                                 }
709                                                 start = [ forward ? parent.firstChild : parent.lastChild ];
711                                                 // non-xml :nth-child(...) stores cache data on `parent`
712                                                 if ( forward && useCache ) {
714                                                         // Seek `elem` from a previously-cached index
715                                                         outerCache = parent[ expando ] || ( parent[ expando ] = {} );
716                                                         cache = outerCache[ type ] || [];
717                                                         nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
718                                                         diff = nodeIndex && cache[ 2 ];
719                                                         node = nodeIndex && parent.childNodes[ nodeIndex ];
721                                                         while ( ( node = ++nodeIndex && node && node[ dir ] ||
723                                                                 // Fallback to seeking `elem` from the start
724                                                                 ( diff = nodeIndex = 0 ) || start.pop() ) ) {
726                                                                 // When found, cache indexes on `parent` and break
727                                                                 if ( node.nodeType === 1 && ++diff && node === elem ) {
728                                                                         outerCache[ type ] = [ dirruns, nodeIndex, diff ];
729                                                                         break;
730                                                                 }
731                                                         }
733                                                 } else {
735                                                         // Use previously-cached element index if available
736                                                         if ( useCache ) {
737                                                                 outerCache = elem[ expando ] || ( elem[ expando ] = {} );
738                                                                 cache = outerCache[ type ] || [];
739                                                                 nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
740                                                                 diff = nodeIndex;
741                                                         }
743                                                         // xml :nth-child(...)
744                                                         // or :nth-last-child(...) or :nth(-last)?-of-type(...)
745                                                         if ( diff === false ) {
747                                                                 // Use the same loop as above to seek `elem` from the start
748                                                                 while ( ( node = ++nodeIndex && node && node[ dir ] ||
749                                                                         ( diff = nodeIndex = 0 ) || start.pop() ) ) {
751                                                                         if ( ( ofType ?
752                                                                                 nodeName( node, name ) :
753                                                                                 node.nodeType === 1 ) &&
754                                                                                 ++diff ) {
756                                                                                 // Cache the index of each encountered element
757                                                                                 if ( useCache ) {
758                                                                                         outerCache = node[ expando ] ||
759                                                                                                 ( node[ expando ] = {} );
760                                                                                         outerCache[ type ] = [ dirruns, diff ];
761                                                                                 }
763                                                                                 if ( node === elem ) {
764                                                                                         break;
765                                                                                 }
766                                                                         }
767                                                                 }
768                                                         }
769                                                 }
771                                                 // Incorporate the offset, then check against cycle size
772                                                 diff -= last;
773                                                 return diff === first || ( diff % first === 0 && diff / first >= 0 );
774                                         }
775                                 };
776                 },
778                 PSEUDO: function( pseudo, argument ) {
780                         // pseudo-class names are case-insensitive
781                         // https://www.w3.org/TR/selectors/#pseudo-classes
782                         // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
783                         // Remember that setFilters inherits from pseudos
784                         var args,
785                                 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
786                                         selectorError( "unsupported pseudo: " + pseudo );
788                         // The user may use createPseudo to indicate that
789                         // arguments are needed to create the filter function
790                         // just as jQuery does
791                         if ( fn[ expando ] ) {
792                                 return fn( argument );
793                         }
795                         // But maintain support for old signatures
796                         if ( fn.length > 1 ) {
797                                 args = [ pseudo, pseudo, "", argument ];
798                                 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
799                                         markFunction( function( seed, matches ) {
800                                                 var idx,
801                                                         matched = fn( seed, argument ),
802                                                         i = matched.length;
803                                                 while ( i-- ) {
804                                                         idx = indexOf.call( seed, matched[ i ] );
805                                                         seed[ idx ] = !( matches[ idx ] = matched[ i ] );
806                                                 }
807                                         } ) :
808                                         function( elem ) {
809                                                 return fn( elem, 0, args );
810                                         };
811                         }
813                         return fn;
814                 }
815         },
817         pseudos: {
819                 // Potentially complex pseudos
820                 not: markFunction( function( selector ) {
822                         // Trim the selector passed to compile
823                         // to avoid treating leading and trailing
824                         // spaces as combinators
825                         var input = [],
826                                 results = [],
827                                 matcher = compile( selector.replace( rtrim, "$1" ) );
829                         return matcher[ expando ] ?
830                                 markFunction( function( seed, matches, _context, xml ) {
831                                         var elem,
832                                                 unmatched = matcher( seed, null, xml, [] ),
833                                                 i = seed.length;
835                                         // Match elements unmatched by `matcher`
836                                         while ( i-- ) {
837                                                 if ( ( elem = unmatched[ i ] ) ) {
838                                                         seed[ i ] = !( matches[ i ] = elem );
839                                                 }
840                                         }
841                                 } ) :
842                                 function( elem, _context, xml ) {
843                                         input[ 0 ] = elem;
844                                         matcher( input, null, xml, results );
846                                         // Don't keep the element (issue #299)
847                                         input[ 0 ] = null;
848                                         return !results.pop();
849                                 };
850                 } ),
852                 has: markFunction( function( selector ) {
853                         return function( elem ) {
854                                 return find( selector, elem ).length > 0;
855                         };
856                 } ),
858                 contains: markFunction( function( text ) {
859                         text = text.replace( runescape, funescape );
860                         return function( elem ) {
861                                 return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1;
862                         };
863                 } ),
865                 // "Whether an element is represented by a :lang() selector
866                 // is based solely on the element's language value
867                 // being equal to the identifier C,
868                 // or beginning with the identifier C immediately followed by "-".
869                 // The matching of C against the element's language value is performed case-insensitively.
870                 // The identifier C does not have to be a valid language name."
871                 // https://www.w3.org/TR/selectors/#lang-pseudo
872                 lang: markFunction( function( lang ) {
874                         // lang value must be a valid identifier
875                         if ( !ridentifier.test( lang || "" ) ) {
876                                 selectorError( "unsupported lang: " + lang );
877                         }
878                         lang = lang.replace( runescape, funescape ).toLowerCase();
879                         return function( elem ) {
880                                 var elemLang;
881                                 do {
882                                         if ( ( elemLang = documentIsHTML ?
883                                                 elem.lang :
884                                                 elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
886                                                 elemLang = elemLang.toLowerCase();
887                                                 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
888                                         }
889                                 } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
890                                 return false;
891                         };
892                 } ),
894                 // Miscellaneous
895                 target: function( elem ) {
896                         var hash = window.location && window.location.hash;
897                         return hash && hash.slice( 1 ) === elem.id;
898                 },
900                 root: function( elem ) {
901                         return elem === documentElement;
902                 },
904                 focus: function( elem ) {
905                         return elem === document.activeElement &&
906                                 document.hasFocus() &&
907                                 !!( elem.type || elem.href || ~elem.tabIndex );
908                 },
910                 // Boolean properties
911                 enabled: createDisabledPseudo( false ),
912                 disabled: createDisabledPseudo( true ),
914                 checked: function( elem ) {
916                         // In CSS3, :checked should return both checked and selected elements
917                         // https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
918                         return ( nodeName( elem, "input" ) && !!elem.checked ) ||
919                                 ( nodeName( elem, "option" ) && !!elem.selected );
920                 },
922                 selected: function( elem ) {
924                         // Support: IE <=11+
925                         // Accessing the selectedIndex property
926                         // forces the browser to treat the default option as
927                         // selected when in an optgroup.
928                         if ( isIE && elem.parentNode ) {
929                                 // eslint-disable-next-line no-unused-expressions
930                                 elem.parentNode.selectedIndex;
931                         }
933                         return elem.selected === true;
934                 },
936                 // Contents
937                 empty: function( elem ) {
939                         // https://www.w3.org/TR/selectors/#empty-pseudo
940                         // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
941                         //   but not by others (comment: 8; processing instruction: 7; etc.)
942                         // nodeType < 6 works because attributes (2) do not appear as children
943                         for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
944                                 if ( elem.nodeType < 6 ) {
945                                         return false;
946                                 }
947                         }
948                         return true;
949                 },
951                 parent: function( elem ) {
952                         return !Expr.pseudos.empty( elem );
953                 },
955                 // Element/input types
956                 header: function( elem ) {
957                         return rheader.test( elem.nodeName );
958                 },
960                 input: function( elem ) {
961                         return rinputs.test( elem.nodeName );
962                 },
964                 button: function( elem ) {
965                         return nodeName( elem, "input" ) && elem.type === "button" ||
966                                 nodeName( elem, "button" );
967                 },
969                 text: function( elem ) {
970                         return nodeName( elem, "input" ) && elem.type === "text";
971                 },
973                 // Position-in-collection
974                 first: createPositionalPseudo( function() {
975                         return [ 0 ];
976                 } ),
978                 last: createPositionalPseudo( function( _matchIndexes, length ) {
979                         return [ length - 1 ];
980                 } ),
982                 eq: createPositionalPseudo( function( _matchIndexes, length, argument ) {
983                         return [ argument < 0 ? argument + length : argument ];
984                 } ),
986                 even: createPositionalPseudo( function( matchIndexes, length ) {
987                         var i = 0;
988                         for ( ; i < length; i += 2 ) {
989                                 matchIndexes.push( i );
990                         }
991                         return matchIndexes;
992                 } ),
994                 odd: createPositionalPseudo( function( matchIndexes, length ) {
995                         var i = 1;
996                         for ( ; i < length; i += 2 ) {
997                                 matchIndexes.push( i );
998                         }
999                         return matchIndexes;
1000                 } ),
1002                 lt: createPositionalPseudo( function( matchIndexes, length, argument ) {
1003                         var i;
1005                         if ( argument < 0 ) {
1006                                 i = argument + length;
1007                         } else if ( argument > length ) {
1008                                 i = length;
1009                         } else {
1010                                 i = argument;
1011                         }
1013                         for ( ; --i >= 0; ) {
1014                                 matchIndexes.push( i );
1015                         }
1016                         return matchIndexes;
1017                 } ),
1019                 gt: createPositionalPseudo( function( matchIndexes, length, argument ) {
1020                         var i = argument < 0 ? argument + length : argument;
1021                         for ( ; ++i < length; ) {
1022                                 matchIndexes.push( i );
1023                         }
1024                         return matchIndexes;
1025                 } )
1026         }
1029 Expr.pseudos.nth = Expr.pseudos.eq;
1031 // Add button/input type pseudos
1032 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
1033         Expr.pseudos[ i ] = createInputPseudo( i );
1035 for ( i in { submit: true, reset: true } ) {
1036         Expr.pseudos[ i ] = createButtonPseudo( i );
1039 // Easy API for creating new setFilters
1040 function setFilters() {}
1041 setFilters.prototype = Expr.filters = Expr.pseudos;
1042 Expr.setFilters = new setFilters();
1044 function tokenize( selector, parseOnly ) {
1045         var matched, match, tokens, type,
1046                 soFar, groups, preFilters,
1047                 cached = tokenCache[ selector + " " ];
1049         if ( cached ) {
1050                 return parseOnly ? 0 : cached.slice( 0 );
1051         }
1053         soFar = selector;
1054         groups = [];
1055         preFilters = Expr.preFilter;
1057         while ( soFar ) {
1059                 // Comma and first run
1060                 if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
1061                         if ( match ) {
1063                                 // Don't consume trailing commas as valid
1064                                 soFar = soFar.slice( match[ 0 ].length ) || soFar;
1065                         }
1066                         groups.push( ( tokens = [] ) );
1067                 }
1069                 matched = false;
1071                 // Combinators
1072                 if ( ( match = rcombinators.exec( soFar ) ) ) {
1073                         matched = match.shift();
1074                         tokens.push( {
1075                                 value: matched,
1077                                 // Cast descendant combinators to space
1078                                 type: match[ 0 ].replace( rtrim, " " )
1079                         } );
1080                         soFar = soFar.slice( matched.length );
1081                 }
1083                 // Filters
1084                 for ( type in Expr.filter ) {
1085                         if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
1086                                 ( match = preFilters[ type ]( match ) ) ) ) {
1087                                 matched = match.shift();
1088                                 tokens.push( {
1089                                         value: matched,
1090                                         type: type,
1091                                         matches: match
1092                                 } );
1093                                 soFar = soFar.slice( matched.length );
1094                         }
1095                 }
1097                 if ( !matched ) {
1098                         break;
1099                 }
1100         }
1102         // Return the length of the invalid excess
1103         // if we're just parsing
1104         // Otherwise, throw an error or return tokens
1105         if ( parseOnly ) {
1106                 return soFar.length;
1107         }
1109         return soFar ?
1110                 selectorError( selector ) :
1112                 // Cache the tokens
1113                 tokenCache( selector, groups ).slice( 0 );
1116 function toSelector( tokens ) {
1117         var i = 0,
1118                 len = tokens.length,
1119                 selector = "";
1120         for ( ; i < len; i++ ) {
1121                 selector += tokens[ i ].value;
1122         }
1123         return selector;
1126 function addCombinator( matcher, combinator, base ) {
1127         var dir = combinator.dir,
1128                 skip = combinator.next,
1129                 key = skip || dir,
1130                 checkNonElements = base && key === "parentNode",
1131                 doneName = done++;
1133         return combinator.first ?
1135                 // Check against closest ancestor/preceding element
1136                 function( elem, context, xml ) {
1137                         while ( ( elem = elem[ dir ] ) ) {
1138                                 if ( elem.nodeType === 1 || checkNonElements ) {
1139                                         return matcher( elem, context, xml );
1140                                 }
1141                         }
1142                         return false;
1143                 } :
1145                 // Check against all ancestor/preceding elements
1146                 function( elem, context, xml ) {
1147                         var oldCache, outerCache,
1148                                 newCache = [ dirruns, doneName ];
1150                         // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
1151                         if ( xml ) {
1152                                 while ( ( elem = elem[ dir ] ) ) {
1153                                         if ( elem.nodeType === 1 || checkNonElements ) {
1154                                                 if ( matcher( elem, context, xml ) ) {
1155                                                         return true;
1156                                                 }
1157                                         }
1158                                 }
1159                         } else {
1160                                 while ( ( elem = elem[ dir ] ) ) {
1161                                         if ( elem.nodeType === 1 || checkNonElements ) {
1162                                                 outerCache = elem[ expando ] || ( elem[ expando ] = {} );
1164                                                 if ( skip && nodeName( elem, skip ) ) {
1165                                                         elem = elem[ dir ] || elem;
1166                                                 } else if ( ( oldCache = outerCache[ key ] ) &&
1167                                                         oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
1169                                                         // Assign to newCache so results back-propagate to previous elements
1170                                                         return ( newCache[ 2 ] = oldCache[ 2 ] );
1171                                                 } else {
1173                                                         // Reuse newcache so results back-propagate to previous elements
1174                                                         outerCache[ key ] = newCache;
1176                                                         // A match means we're done; a fail means we have to keep checking
1177                                                         if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
1178                                                                 return true;
1179                                                         }
1180                                                 }
1181                                         }
1182                                 }
1183                         }
1184                         return false;
1185                 };
1188 function elementMatcher( matchers ) {
1189         return matchers.length > 1 ?
1190                 function( elem, context, xml ) {
1191                         var i = matchers.length;
1192                         while ( i-- ) {
1193                                 if ( !matchers[ i ]( elem, context, xml ) ) {
1194                                         return false;
1195                                 }
1196                         }
1197                         return true;
1198                 } :
1199                 matchers[ 0 ];
1202 function multipleContexts( selector, contexts, results ) {
1203         var i = 0,
1204                 len = contexts.length;
1205         for ( ; i < len; i++ ) {
1206                 find( selector, contexts[ i ], results );
1207         }
1208         return results;
1211 function condense( unmatched, map, filter, context, xml ) {
1212         var elem,
1213                 newUnmatched = [],
1214                 i = 0,
1215                 len = unmatched.length,
1216                 mapped = map != null;
1218         for ( ; i < len; i++ ) {
1219                 if ( ( elem = unmatched[ i ] ) ) {
1220                         if ( !filter || filter( elem, context, xml ) ) {
1221                                 newUnmatched.push( elem );
1222                                 if ( mapped ) {
1223                                         map.push( i );
1224                                 }
1225                         }
1226                 }
1227         }
1229         return newUnmatched;
1232 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
1233         if ( postFilter && !postFilter[ expando ] ) {
1234                 postFilter = setMatcher( postFilter );
1235         }
1236         if ( postFinder && !postFinder[ expando ] ) {
1237                 postFinder = setMatcher( postFinder, postSelector );
1238         }
1239         return markFunction( function( seed, results, context, xml ) {
1240                 var temp, i, elem, matcherOut,
1241                         preMap = [],
1242                         postMap = [],
1243                         preexisting = results.length,
1245                         // Get initial elements from seed or context
1246                         elems = seed ||
1247                                 multipleContexts( selector || "*",
1248                                         context.nodeType ? [ context ] : context, [] ),
1250                         // Prefilter to get matcher input, preserving a map for seed-results synchronization
1251                         matcherIn = preFilter && ( seed || !selector ) ?
1252                                 condense( elems, preMap, preFilter, context, xml ) :
1253                                 elems;
1255                 if ( matcher ) {
1257                         // If we have a postFinder, or filtered seed, or non-seed postFilter
1258                         // or preexisting results,
1259                         matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
1261                                 // ...intermediate processing is necessary
1262                                 [] :
1264                                 // ...otherwise use results directly
1265                                 results;
1267                         // Find primary matches
1268                         matcher( matcherIn, matcherOut, context, xml );
1269                 } else {
1270                         matcherOut = matcherIn;
1271                 }
1273                 // Apply postFilter
1274                 if ( postFilter ) {
1275                         temp = condense( matcherOut, postMap );
1276                         postFilter( temp, [], context, xml );
1278                         // Un-match failing elements by moving them back to matcherIn
1279                         i = temp.length;
1280                         while ( i-- ) {
1281                                 if ( ( elem = temp[ i ] ) ) {
1282                                         matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
1283                                 }
1284                         }
1285                 }
1287                 if ( seed ) {
1288                         if ( postFinder || preFilter ) {
1289                                 if ( postFinder ) {
1291                                         // Get the final matcherOut by condensing this intermediate into postFinder contexts
1292                                         temp = [];
1293                                         i = matcherOut.length;
1294                                         while ( i-- ) {
1295                                                 if ( ( elem = matcherOut[ i ] ) ) {
1297                                                         // Restore matcherIn since elem is not yet a final match
1298                                                         temp.push( ( matcherIn[ i ] = elem ) );
1299                                                 }
1300                                         }
1301                                         postFinder( null, ( matcherOut = [] ), temp, xml );
1302                                 }
1304                                 // Move matched elements from seed to results to keep them synchronized
1305                                 i = matcherOut.length;
1306                                 while ( i-- ) {
1307                                         if ( ( elem = matcherOut[ i ] ) &&
1308                                                 ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) {
1310                                                 seed[ temp ] = !( results[ temp ] = elem );
1311                                         }
1312                                 }
1313                         }
1315                 // Add elements to results, through postFinder if defined
1316                 } else {
1317                         matcherOut = condense(
1318                                 matcherOut === results ?
1319                                         matcherOut.splice( preexisting, matcherOut.length ) :
1320                                         matcherOut
1321                         );
1322                         if ( postFinder ) {
1323                                 postFinder( null, results, matcherOut, xml );
1324                         } else {
1325                                 push.apply( results, matcherOut );
1326                         }
1327                 }
1328         } );
1331 function matcherFromTokens( tokens ) {
1332         var checkContext, matcher, j,
1333                 len = tokens.length,
1334                 leadingRelative = Expr.relative[ tokens[ 0 ].type ],
1335                 implicitRelative = leadingRelative || Expr.relative[ " " ],
1336                 i = leadingRelative ? 1 : 0,
1338                 // The foundational matcher ensures that elements are reachable from top-level context(s)
1339                 matchContext = addCombinator( function( elem ) {
1340                         return elem === checkContext;
1341                 }, implicitRelative, true ),
1342                 matchAnyContext = addCombinator( function( elem ) {
1343                         return indexOf.call( checkContext, elem ) > -1;
1344                 }, implicitRelative, true ),
1345                 matchers = [ function( elem, context, xml ) {
1346                         var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
1347                                 ( checkContext = context ).nodeType ?
1348                                         matchContext( elem, context, xml ) :
1349                                         matchAnyContext( elem, context, xml ) );
1351                         // Avoid hanging onto element (issue #299)
1352                         checkContext = null;
1353                         return ret;
1354                 } ];
1356         for ( ; i < len; i++ ) {
1357                 if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
1358                         matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
1359                 } else {
1360                         matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
1362                         // Return special upon seeing a positional matcher
1363                         if ( matcher[ expando ] ) {
1365                                 // Find the next relative operator (if any) for proper handling
1366                                 j = ++i;
1367                                 for ( ; j < len; j++ ) {
1368                                         if ( Expr.relative[ tokens[ j ].type ] ) {
1369                                                 break;
1370                                         }
1371                                 }
1372                                 return setMatcher(
1373                                         i > 1 && elementMatcher( matchers ),
1374                                         i > 1 && toSelector(
1376                                                 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
1377                                                 tokens.slice( 0, i - 1 )
1378                                                         .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
1379                                         ).replace( rtrim, "$1" ),
1380                                         matcher,
1381                                         i < j && matcherFromTokens( tokens.slice( i, j ) ),
1382                                         j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
1383                                         j < len && toSelector( tokens )
1384                                 );
1385                         }
1386                         matchers.push( matcher );
1387                 }
1388         }
1390         return elementMatcher( matchers );
1393 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
1394         var bySet = setMatchers.length > 0,
1395                 byElement = elementMatchers.length > 0,
1396                 superMatcher = function( seed, context, xml, results, outermost ) {
1397                         var elem, j, matcher,
1398                                 matchedCount = 0,
1399                                 i = "0",
1400                                 unmatched = seed && [],
1401                                 setMatched = [],
1402                                 contextBackup = outermostContext,
1404                                 // We must always have either seed elements or outermost context
1405                                 elems = seed || byElement && Expr.find.TAG( "*", outermost ),
1407                                 // Use integer dirruns iff this is the outermost matcher
1408                                 dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 );
1410                         if ( outermost ) {
1412                                 // Support: IE 11+
1413                                 // IE sometimes throws a "Permission denied" error when strict-comparing
1414                                 // two documents; shallow comparisons work.
1415                                 // eslint-disable-next-line eqeqeq
1416                                 outermostContext = context == document || context || outermost;
1417                         }
1419                         // Add elements passing elementMatchers directly to results
1420                         for ( ; ( elem = elems[ i ] ) != null; i++ ) {
1421                                 if ( byElement && elem ) {
1422                                         j = 0;
1424                                         // Support: IE 11+
1425                                         // IE sometimes throws a "Permission denied" error when strict-comparing
1426                                         // two documents; shallow comparisons work.
1427                                         // eslint-disable-next-line eqeqeq
1428                                         if ( !context && elem.ownerDocument != document ) {
1429                                                 setDocument( elem );
1430                                                 xml = !documentIsHTML;
1431                                         }
1432                                         while ( ( matcher = elementMatchers[ j++ ] ) ) {
1433                                                 if ( matcher( elem, context || document, xml ) ) {
1434                                                         push.call( results, elem );
1435                                                         break;
1436                                                 }
1437                                         }
1438                                         if ( outermost ) {
1439                                                 dirruns = dirrunsUnique;
1440                                         }
1441                                 }
1443                                 // Track unmatched elements for set filters
1444                                 if ( bySet ) {
1446                                         // They will have gone through all possible matchers
1447                                         if ( ( elem = !matcher && elem ) ) {
1448                                                 matchedCount--;
1449                                         }
1451                                         // Lengthen the array for every element, matched or not
1452                                         if ( seed ) {
1453                                                 unmatched.push( elem );
1454                                         }
1455                                 }
1456                         }
1458                         // `i` is now the count of elements visited above, and adding it to `matchedCount`
1459                         // makes the latter nonnegative.
1460                         matchedCount += i;
1462                         // Apply set filters to unmatched elements
1463                         // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
1464                         // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
1465                         // no element matchers and no seed.
1466                         // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
1467                         // case, which will result in a "00" `matchedCount` that differs from `i` but is also
1468                         // numerically zero.
1469                         if ( bySet && i !== matchedCount ) {
1470                                 j = 0;
1471                                 while ( ( matcher = setMatchers[ j++ ] ) ) {
1472                                         matcher( unmatched, setMatched, context, xml );
1473                                 }
1475                                 if ( seed ) {
1477                                         // Reintegrate element matches to eliminate the need for sorting
1478                                         if ( matchedCount > 0 ) {
1479                                                 while ( i-- ) {
1480                                                         if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
1481                                                                 setMatched[ i ] = pop.call( results );
1482                                                         }
1483                                                 }
1484                                         }
1486                                         // Discard index placeholder values to get only actual matches
1487                                         setMatched = condense( setMatched );
1488                                 }
1490                                 // Add matches to results
1491                                 push.apply( results, setMatched );
1493                                 // Seedless set matches succeeding multiple successful matchers stipulate sorting
1494                                 if ( outermost && !seed && setMatched.length > 0 &&
1495                                         ( matchedCount + setMatchers.length ) > 1 ) {
1497                                         jQuery.uniqueSort( results );
1498                                 }
1499                         }
1501                         // Override manipulation of globals by nested matchers
1502                         if ( outermost ) {
1503                                 dirruns = dirrunsUnique;
1504                                 outermostContext = contextBackup;
1505                         }
1507                         return unmatched;
1508                 };
1510         return bySet ?
1511                 markFunction( superMatcher ) :
1512                 superMatcher;
1515 function compile( selector, match /* Internal Use Only */ ) {
1516         var i,
1517                 setMatchers = [],
1518                 elementMatchers = [],
1519                 cached = compilerCache[ selector + " " ];
1521         if ( !cached ) {
1523                 // Generate a function of recursive functions that can be used to check each element
1524                 if ( !match ) {
1525                         match = tokenize( selector );
1526                 }
1527                 i = match.length;
1528                 while ( i-- ) {
1529                         cached = matcherFromTokens( match[ i ] );
1530                         if ( cached[ expando ] ) {
1531                                 setMatchers.push( cached );
1532                         } else {
1533                                 elementMatchers.push( cached );
1534                         }
1535                 }
1537                 // Cache the compiled function
1538                 cached = compilerCache( selector,
1539                         matcherFromGroupMatchers( elementMatchers, setMatchers ) );
1541                 // Save selector and tokenization
1542                 cached.selector = selector;
1543         }
1544         return cached;
1548  * A low-level selection function that works with jQuery's compiled
1549  *  selector functions
1550  * @param {String|Function} selector A selector or a pre-compiled
1551  *  selector function built with jQuery selector compile
1552  * @param {Element} context
1553  * @param {Array} [results]
1554  * @param {Array} [seed] A set of elements to match against
1555  */
1556 function select( selector, context, results, seed ) {
1557         var i, tokens, token, type, find,
1558                 compiled = typeof selector === "function" && selector,
1559                 match = !seed && tokenize( ( selector = compiled.selector || selector ) );
1561         results = results || [];
1563         // Try to minimize operations if there is only one selector in the list and no seed
1564         // (the latter of which guarantees us context)
1565         if ( match.length === 1 ) {
1567                 // Reduce context if the leading compound selector is an ID
1568                 tokens = match[ 0 ] = match[ 0 ].slice( 0 );
1569                 if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
1570                                 context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
1572                         context = ( Expr.find.ID(
1573                                 token.matches[ 0 ].replace( runescape, funescape ),
1574                                 context
1575                         ) || [] )[ 0 ];
1576                         if ( !context ) {
1577                                 return results;
1579                         // Precompiled matchers will still verify ancestry, so step up a level
1580                         } else if ( compiled ) {
1581                                 context = context.parentNode;
1582                         }
1584                         selector = selector.slice( tokens.shift().value.length );
1585                 }
1587                 // Fetch a seed set for right-to-left matching
1588                 i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length;
1589                 while ( i-- ) {
1590                         token = tokens[ i ];
1592                         // Abort if we hit a combinator
1593                         if ( Expr.relative[ ( type = token.type ) ] ) {
1594                                 break;
1595                         }
1596                         if ( ( find = Expr.find[ type ] ) ) {
1598                                 // Search, expanding context for leading sibling combinators
1599                                 if ( ( seed = find(
1600                                         token.matches[ 0 ].replace( runescape, funescape ),
1601                                         rsibling.test( tokens[ 0 ].type ) &&
1602                                                 testContext( context.parentNode ) || context
1603                                 ) ) ) {
1605                                         // If seed is empty or no tokens remain, we can return early
1606                                         tokens.splice( i, 1 );
1607                                         selector = seed.length && toSelector( tokens );
1608                                         if ( !selector ) {
1609                                                 push.apply( results, seed );
1610                                                 return results;
1611                                         }
1613                                         break;
1614                                 }
1615                         }
1616                 }
1617         }
1619         // Compile and execute a filtering function if one is not provided
1620         // Provide `match` to avoid retokenization if we modified the selector above
1621         ( compiled || compile( selector, match ) )(
1622                 seed,
1623                 context,
1624                 !documentIsHTML,
1625                 results,
1626                 !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
1627         );
1628         return results;
1631 // Initialize against the default document
1632 setDocument();
1634 jQuery.find = find;
1636 } )();