Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b3b1d00

Browse files
committed
Core: Refactor loops to avoid going behind array bounds
Reaching behind array bounds - which is what effectively happens if you check for `null`/`undefined` value instead of doing a `length` check - can trigger deopts in various JS engines. Switch to regular `length`-based loops. In the past, this was impractical as IE <9 used to clobber the `length` property if an element with the `name="length"` attribute was present, but this is no longer a concern.
1 parent 35789e7 commit b3b1d00

10 files changed

Lines changed: 42 additions & 39 deletions

File tree

src/ajax.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ function addToPrefiltersOrTransports( structure ) {
5959
dataTypeExpression = "*";
6060
}
6161

62-
var dataType,
63-
i = 0,
62+
var dataType, i,
6463
dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
6564

6665
if ( typeof func === "function" ) {
6766

6867
// For each dataType in the dataTypeExpression
69-
while ( ( dataType = dataTypes[ i++ ] ) ) {
68+
for ( i = 0; i < dataTypes.length; i++ ) {
69+
dataType = dataTypes[ i ];
7070

7171
// Prepend if requested
7272
if ( dataType[ 0 ] === "+" ) {

src/attributes/attr.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ jQuery.extend( {
7272
attrHooks: {},
7373

7474
removeAttr: function( elem, value ) {
75-
var name,
76-
i = 0,
75+
var i, name,
7776

7877
// Attribute names can contain non-HTML whitespace characters
7978
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
8079
attrNames = value && value.match( rnothtmlwhite );
8180

8281
if ( attrNames && elem.nodeType === 1 ) {
83-
while ( ( name = attrNames[ i++ ] ) ) {
82+
for ( i = 0; i < attrNames.length; i++ ) {
83+
name = attrNames[ i ];
8484
elem.removeAttribute( name );
8585
}
8686
}

src/attributes/classes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ jQuery.fn.extend( {
140140
},
141141

142142
hasClass: function( selector ) {
143-
var className, elem,
144-
i = 0;
143+
var className, elem, i;
145144

146145
className = " " + selector + " ";
147-
while ( ( elem = this[ i++ ] ) ) {
146+
for ( i = 0; i < this.length; i++ ) {
147+
elem = this[ i ];
148148
if ( elem.nodeType === 1 &&
149149
( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
150150
return true;

src/core.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,15 @@ jQuery.extend( {
258258

259259
// Retrieve the text value of an array of DOM nodes
260260
text: function( elem ) {
261-
var node,
261+
var i, node,
262262
ret = "",
263-
i = 0,
264263
nodeType = elem.nodeType;
265264

266265
if ( !nodeType ) {
267266

268267
// If no nodeType, this is expected to be an array
269-
while ( ( node = elem[ i++ ] ) ) {
268+
for ( i = 0; i < elem.length; i++ ) {
269+
node = elem[ i ];
270270

271271
// Do not traverse comment nodes
272272
ret += jQuery.text( node );

src/event.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,16 @@ jQuery.event = {
304304
handlerQueue = jQuery.event.handlers.call( this, event, handlers );
305305

306306
// Run delegates first; they may want to stop propagation beneath us
307-
i = 0;
308-
while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
307+
for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
308+
matched = handlerQueue[ i ];
309309
event.currentTarget = matched.elem;
310310

311-
j = 0;
312-
while ( ( handleObj = matched.handlers[ j++ ] ) &&
313-
!event.isImmediatePropagationStopped() ) {
311+
for (
312+
j = 0;
313+
j < matched.handlers.length && !event.isImmediatePropagationStopped();
314+
j++
315+
) {
316+
handleObj = matched.handlers[ j ];
314317

315318
// If the event is namespaced, then each handler is only invoked if it is
316319
// specially universal or its namespaces are a superset of the event's.

src/event/trigger.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ jQuery.extend( jQuery.event, {
9191
}
9292

9393
// Fire handlers on the event path
94-
i = 0;
95-
while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
94+
for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
95+
cur = eventPath[ i ];
9696
lastElement = cur;
97-
event.type = i > 1 ?
97+
event.type = i > 0 ?
9898
bubbleType :
9999
special.bindType || type;
100100

src/manipulation/buildFragment.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import { isArrayLike } from "../core/isArrayLike.js";
1212
var rhtml = /<|&#?\w+;/;
1313

1414
export function buildFragment( elems, context, scripts, selection, ignored ) {
15-
var elem, tmp, tag, wrap, attached, j,
15+
var elem, tmp, tag, wrap, attached, i, j,
1616
fragment = context.createDocumentFragment(),
1717
nodes = [],
18-
i = 0,
1918
l = elems.length;
2019

21-
for ( ; i < l; i++ ) {
20+
for ( i = 0; i < l; i++ ) {
2221
elem = elems[ i ];
2322

2423
if ( elem || elem === 0 ) {
@@ -61,8 +60,8 @@ export function buildFragment( elems, context, scripts, selection, ignored ) {
6160
// Remove wrapper from fragment
6261
fragment.textContent = "";
6362

64-
i = 0;
65-
while ( ( elem = nodes[ i++ ] ) ) {
63+
for ( i = 0; i < nodes.length; i++ ) {
64+
elem = nodes[ i ];
6665

6766
// Skip elements already in the context collection (trac-4087)
6867
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
@@ -84,8 +83,8 @@ export function buildFragment( elems, context, scripts, selection, ignored ) {
8483

8584
// Capture executables
8685
if ( scripts ) {
87-
j = 0;
88-
while ( ( elem = tmp[ j++ ] ) ) {
86+
for ( j = 0; j < tmp.length; j++ ) {
87+
elem = tmp[ j ];
8988
if ( rscriptType.test( elem.type || "" ) ) {
9089
scripts.push( elem );
9190
}

src/selector-native.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@ var matchExpr = jQuery.extend( {
4545

4646
jQuery.extend( {
4747
find: function( selector, context, results, seed ) {
48-
var elem, nid, groups, newSelector,
48+
var elem, nid, groups, newSelector, i,
4949
newContext = context && context.ownerDocument,
5050

5151
// nodeType defaults to 9, since context defaults to document
52-
nodeType = context ? context.nodeType : 9,
53-
i = 0;
52+
nodeType = context ? context.nodeType : 9;
5453

5554
results = results || [];
5655
context = context || document;
@@ -66,7 +65,8 @@ jQuery.extend( {
6665
}
6766

6867
if ( seed ) {
69-
while ( ( elem = seed[ i++ ] ) ) {
68+
for ( i = 0; i < seed.length; i++ ) {
69+
elem = seed[ i ];
7070
if ( jQuery.find.matchesSelector( elem, selector ) ) {
7171
results.push( elem );
7272
}

src/selector.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,6 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
11711171
// Add elements passing elementMatchers directly to results
11721172
for ( ; ( elem = elems[ i ] ) != null; i++ ) {
11731173
if ( byElement && elem ) {
1174-
j = 0;
11751174

11761175
// Support: IE 11+
11771176
// IE sometimes throws a "Permission denied" error when strict-comparing
@@ -1181,8 +1180,10 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
11811180
setDocument( elem );
11821181
xml = !documentIsHTML;
11831182
}
1184-
while ( ( matcher = elementMatchers[ j++ ] ) ) {
1185-
if ( matcher( elem, context || document, xml ) ) {
1183+
matcher = undefined;
1184+
for ( j = 0; j < elementMatchers.length; j++ ) {
1185+
if ( elementMatchers[ j ]( elem, context || document, xml ) ) {
1186+
matcher = elementMatchers[ j ];
11861187
push.call( results, elem );
11871188
break;
11881189
}
@@ -1219,8 +1220,8 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
12191220
// case, which will result in a "00" `matchedCount` that differs from `i` but is also
12201221
// numerically zero.
12211222
if ( bySet && i !== matchedCount ) {
1222-
j = 0;
1223-
while ( ( matcher = setMatchers[ j++ ] ) ) {
1223+
for ( j = 0; j < setMatchers.length; j++ ) {
1224+
matcher = setMatchers[ j ];
12241225
matcher( unmatched, setMatched, context, xml );
12251226
}
12261227

src/selector/uniqueSort.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ function sortOrder( a, b ) {
7070
* @param {ArrayLike} results
7171
*/
7272
jQuery.uniqueSort = function( results ) {
73-
var j = 1,
74-
i = 1;
73+
var i,
74+
j = 1;
7575

7676
hasDuplicate = false;
7777

@@ -82,7 +82,7 @@ jQuery.uniqueSort = function( results ) {
8282
// Pack the first instance of each unique element into the start of
8383
// results (starting at index 1 because index 0 is always kept), then
8484
// splice away the tail of duplicates.
85-
for ( ; i < results.length; i++ ) {
85+
for ( i = 1; i < results.length; i++ ) {
8686
if ( results[ i ] !== results[ i - 1 ] ) {
8787
results[ j++ ] = results[ i ];
8888
}

0 commit comments

Comments
 (0)