Tests: Add custom attribute getter tests to the selector module
[jquery.git] / src / selector / tokenize.js
blobfb25cb2074481055341488f36eb5077c81651d1c
1 import { jQuery } from "../core.js";
2 import { rcomma } from "./var/rcomma.js";
3 import { rleadingCombinator } from "./var/rleadingCombinator.js";
4 import { rtrimCSS } from "../var/rtrimCSS.js";
5 import { createCache } from "./createCache.js";
6 import { selectorError } from "./selectorError.js";
7 import { filterMatchExpr } from "./filterMatchExpr.js";
9 var tokenCache = createCache();
11 export function tokenize( selector, parseOnly ) {
12         var matched, match, tokens, type,
13                 soFar, groups, preFilters,
14                 cached = tokenCache[ selector + " " ];
16         if ( cached ) {
17                 return parseOnly ? 0 : cached.slice( 0 );
18         }
20         soFar = selector;
21         groups = [];
22         preFilters = jQuery.expr.preFilter;
24         while ( soFar ) {
26                 // Comma and first run
27                 if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
28                         if ( match ) {
30                                 // Don't consume trailing commas as valid
31                                 soFar = soFar.slice( match[ 0 ].length ) || soFar;
32                         }
33                         groups.push( ( tokens = [] ) );
34                 }
36                 matched = false;
38                 // Combinators
39                 if ( ( match = rleadingCombinator.exec( soFar ) ) ) {
40                         matched = match.shift();
41                         tokens.push( {
42                                 value: matched,
44                                 // Cast descendant combinators to space
45                                 type: match[ 0 ].replace( rtrimCSS, " " )
46                         } );
47                         soFar = soFar.slice( matched.length );
48                 }
50                 // Filters
51                 for ( type in filterMatchExpr ) {
52                         if ( ( match = jQuery.expr.match[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
53                                 ( match = preFilters[ type ]( match ) ) ) ) {
54                                 matched = match.shift();
55                                 tokens.push( {
56                                         value: matched,
57                                         type: type,
58                                         matches: match
59                                 } );
60                                 soFar = soFar.slice( matched.length );
61                         }
62                 }
64                 if ( !matched ) {
65                         break;
66                 }
67         }
69         // Return the length of the invalid excess
70         // if we're just parsing
71         // Otherwise, throw an error or return tokens
72         if ( parseOnly ) {
73                 return soFar.length;
74         }
76         return soFar ?
77                 selectorError( selector ) :
79                 // Cache the tokens
80                 tokenCache( selector, groups ).slice( 0 );