Landed some improvements for improving the performance of ID-rooted queries (e.g...
authorJohn Resig <jeresig@gmail.com>
Wed, 25 Feb 2009 04:08:04 +0000 (04:08 +0000)
committerJohn Resig <jeresig@gmail.com>
Wed, 25 Feb 2009 04:08:04 +0000 (04:08 +0000)
src/selector.js

index a0b4077..2e6d8e1 100644 (file)
@@ -12,16 +12,17 @@ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^
 
 var Sizzle = function(selector, context, results, seed) {
        results = results || [];
-       context = context || document;
+       var origContext = context = context || document;
 
-       if ( context.nodeType !== 1 && context.nodeType !== 9 )
+       if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
                return [];
+       }
        
        if ( !selector || typeof selector !== "string" ) {
                return results;
        }
 
-       var parts = [], m, set, checkSet, check, mode, extra, prune = true;
+       var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context);
        
        // Reset the position of the chunker regexp (start from head)
        chunker.lastIndex = 0;
@@ -53,31 +54,43 @@ var Sizzle = function(selector, context, results, seed) {
                        }
                }
        } else {
-               var ret = seed ?
-                       { expr: parts.pop(), set: makeArray(seed) } :
-                       Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
-               set = Sizzle.filter( ret.expr, ret.set );
-
-               if ( parts.length > 0 ) {
-                       checkSet = makeArray(set);
-               } else {
-                       prune = false;
+               // Take a shortcut and set the context if the root selector is an ID
+               // (but not if it'll be faster if the inner selector is an ID)
+               if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+                               Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+                       var ret = Sizzle.find( parts.shift(), context, contextXML );
+                       context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
                }
 
-               while ( parts.length ) {
-                       var cur = parts.pop(), pop = cur;
+               if ( context ) {
+                       var ret = seed ?
+                               { expr: parts.pop(), set: makeArray(seed) } :
+                               Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, contextXML );
+                       set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
 
-                       if ( !Expr.relative[ cur ] ) {
-                               cur = "";
+                       if ( parts.length > 0 ) {
+                               checkSet = makeArray(set);
                        } else {
-                               pop = parts.pop();
+                               prune = false;
                        }
 
-                       if ( pop == null ) {
-                               pop = context;
-                       }
+                       while ( parts.length ) {
+                               var cur = parts.pop(), pop = cur;
+
+                               if ( !Expr.relative[ cur ] ) {
+                                       cur = "";
+                               } else {
+                                       pop = parts.pop();
+                               }
+
+                               if ( pop == null ) {
+                                       pop = context;
+                               }
 
-                       Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+                               Expr.relative[ cur ]( checkSet, pop, contextXML );
+                       }
+               } else {
+                       checkSet = parts = [];
                }
        }
 
@@ -92,7 +105,7 @@ var Sizzle = function(selector, context, results, seed) {
        if ( toString.call(checkSet) === "[object Array]" ) {
                if ( !prune ) {
                        results.push.apply( results, checkSet );
-               } else if ( context.nodeType === 1 ) {
+               } else if ( context && context.nodeType === 1 ) {
                        for ( var i = 0; checkSet[i] != null; i++ ) {
                                if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
                                        results.push( set[i] );
@@ -110,7 +123,7 @@ var Sizzle = function(selector, context, results, seed) {
        }
 
        if ( extra ) {
-               Sizzle( extra, context, results, seed );
+               Sizzle( extra, origContext, results, seed );
 
                if ( sortOrder ) {
                        hasDuplicate = false;