Skip to content

Commit

Permalink
Avoid reading outside of collection bounds
Browse files Browse the repository at this point in the history
Consider the following collection:

    const array = ['a', 'b', 'c'];

Retrieving `array[0]` can be done relatively quickly. However, when the property doesn’t exist on the receiver, JavaScript engines must continue to look up the prototype chain until either the property is found or the chain ends. This is inherently slower than *not* doing any prototype chain lookups. Retrieving an out-of-bounds index, e.g. `array[3]`, triggers this scenario, resulting in decreased performance.

This patch changes the way some loops are written to avoid running into the slow case unnecessarily.
  • Loading branch information
mathiasbynens committed Aug 29, 2017
1 parent f6bd902 commit 88e5e6d
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 19 deletions.
24 changes: 15 additions & 9 deletions dist/sizzle.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Released under the MIT license
* https://js.foundation/
*
* Date: 2016-12-02
* Date: 2017-08-29
*/
(function( window ) {

Expand Down Expand Up @@ -658,7 +658,7 @@ setDocument = Sizzle.setDocument = function( node ) {
// getElementById is not reliable as a find shortcut
Expr.find["ID"] = function( id, context ) {
if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
var node, i, elems,
var node, i, elems, length,
elem = context.getElementById( id );

if ( elem ) {
Expand All @@ -671,8 +671,10 @@ setDocument = Sizzle.setDocument = function( node ) {

// Fall back on getElementsByName
elems = context.getElementsByName( id );
length = elems.length;
i = 0;
while ( (elem = elems[i++]) ) {
for ( ; i < length; i++) {
elem = elems[ i ];
node = elem.getAttributeNode("id");
if ( node && node.value === id ) {
return [ elem ];
Expand Down Expand Up @@ -702,11 +704,13 @@ setDocument = Sizzle.setDocument = function( node ) {
tmp = [],
i = 0,
// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
results = context.getElementsByTagName( tag );
results = context.getElementsByTagName( tag ),
length = results.length;

// Filter out possible comments
if ( tag === "*" ) {
while ( (elem = results[i++]) ) {
for ( ; i < length; i++) {
elem = results[ i ];
if ( elem.nodeType === 1 ) {
tmp.push( elem );
}
Expand Down Expand Up @@ -1054,17 +1058,19 @@ Sizzle.uniqueSort = function( results ) {
var elem,
duplicates = [],
j = 0,
i = 0;
i = 0,
length = results.length;

// Unless we *know* we can detect duplicates, assume their presence
hasDuplicate = !support.detectDuplicates;
sortInput = !support.sortStable && results.slice( 0 );
results.sort( sortOrder );

if ( hasDuplicate ) {
while ( (elem = results[i++]) ) {
if ( elem === results[ i ] ) {
j = duplicates.push( i );
for ( ; i < length; i++ ) {
elem = results[ i ];
if ( i + 1 < length && elem === results[ i + 1 ] ) {
j = duplicates.push( i + 1 );
}
}
while ( j-- ) {
Expand Down
Loading

0 comments on commit 88e5e6d

Please sign in to comment.