Skip to content

Commit 893e3c5

Browse files
committed
Core: Avoid reading outside of collection bounds
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.
1 parent f6bd902 commit 893e3c5

File tree

5 files changed

+41
-33
lines changed

5 files changed

+41
-33
lines changed

dist/sizzle.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Released under the MIT license
77
* https://js.foundation/
88
*
9-
* Date: 2016-12-02
9+
* Date: 2017-09-10
1010
*/
1111
(function( window ) {
1212

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

664664
if ( elem ) {
@@ -671,8 +671,9 @@ setDocument = Sizzle.setDocument = function( node ) {
671671

672672
// Fall back on getElementsByName
673673
elems = context.getElementsByName( id );
674+
length = elems.length;
674675
i = 0;
675-
while ( (elem = elems[i++]) ) {
676+
for ( ; i !== length && (elem = elems[ i ]) != null; i++ ) {
676677
node = elem.getAttributeNode("id");
677678
if ( node && node.value === id ) {
678679
return [ elem ];
@@ -702,11 +703,12 @@ setDocument = Sizzle.setDocument = function( node ) {
702703
tmp = [],
703704
i = 0,
704705
// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
705-
results = context.getElementsByTagName( tag );
706+
results = context.getElementsByTagName( tag ),
707+
length = results.length;
706708

707709
// Filter out possible comments
708710
if ( tag === "*" ) {
709-
while ( (elem = results[i++]) ) {
711+
for ( ; i !== length && (elem = results[ i ]) != null; i++ ) {
710712
if ( elem.nodeType === 1 ) {
711713
tmp.push( elem );
712714
}
@@ -1054,17 +1056,19 @@ Sizzle.uniqueSort = function( results ) {
10541056
var elem,
10551057
duplicates = [],
10561058
j = 0,
1057-
i = 0;
1059+
i = 0,
1060+
length = results.length;
10581061

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

10641067
if ( hasDuplicate ) {
1065-
while ( (elem = results[i++]) ) {
1066-
if ( elem === results[ i ] ) {
1067-
j = duplicates.push( i );
1068+
for ( ; i < length; i++ ) {
1069+
elem = results[ i ];
1070+
if ( i + 1 < length && elem === results[ i + 1 ] ) {
1071+
j = duplicates.push( i + 1 );
10681072
}
10691073
}
10701074
while ( j-- ) {

0 commit comments

Comments
 (0)