( tokens )
| 2606 | } |
| 2607 | |
| 2608 | function matcherFromTokens( tokens ) { |
| 2609 | var checkContext, matcher, j, |
| 2610 | len = tokens.length, |
| 2611 | leadingRelative = Expr.relative[ tokens[ 0 ].type ], |
| 2612 | implicitRelative = leadingRelative || Expr.relative[ " " ], |
| 2613 | i = leadingRelative ? 1 : 0, |
| 2614 | |
| 2615 | // The foundational matcher ensures that elements are reachable from top-level context(s) |
| 2616 | matchContext = addCombinator( function( elem ) { |
| 2617 | return elem === checkContext; |
| 2618 | }, implicitRelative, true ), |
| 2619 | matchAnyContext = addCombinator( function( elem ) { |
| 2620 | return indexOf( checkContext, elem ) > -1; |
| 2621 | }, implicitRelative, true ), |
| 2622 | matchers = [ function( elem, context, xml ) { |
| 2623 | var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( |
| 2624 | ( checkContext = context ).nodeType ? |
| 2625 | matchContext( elem, context, xml ) : |
| 2626 | matchAnyContext( elem, context, xml ) ); |
| 2627 | |
| 2628 | // Avoid hanging onto element (issue #299) |
| 2629 | checkContext = null; |
| 2630 | return ret; |
| 2631 | } ]; |
| 2632 | |
| 2633 | for ( ; i < len; i++ ) { |
| 2634 | if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { |
| 2635 | matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; |
| 2636 | } else { |
| 2637 | matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); |
| 2638 | |
| 2639 | // Return special upon seeing a positional matcher |
| 2640 | if ( matcher[ expando ] ) { |
| 2641 | |
| 2642 | // Find the next relative operator (if any) for proper handling |
| 2643 | j = ++i; |
| 2644 | for ( ; j < len; j++ ) { |
| 2645 | if ( Expr.relative[ tokens[ j ].type ] ) { |
| 2646 | break; |
| 2647 | } |
| 2648 | } |
| 2649 | return setMatcher( |
| 2650 | i > 1 && elementMatcher( matchers ), |
| 2651 | i > 1 && toSelector( |
| 2652 | |
| 2653 | // If the preceding token was a descendant combinator, insert an implicit any-element `*` |
| 2654 | tokens |
| 2655 | .slice( 0, i - 1 ) |
| 2656 | .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) |
| 2657 | ).replace( rtrim, "$1" ), |
| 2658 | matcher, |
| 2659 | i < j && matcherFromTokens( tokens.slice( i, j ) ), |
| 2660 | j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), |
| 2661 | j < len && toSelector( tokens ) |
| 2662 | ); |
| 2663 | } |
| 2664 | matchers.push( matcher ); |
| 2665 | } |
no test coverage detected