Skip to content

Commit

Permalink
Fixes #13021. Normalization of core utility array like detection base…
Browse files Browse the repository at this point in the history
…d on standard protocol by Richard Gibson <richard.gibson@gmail.com>. Closes gh-1064
  • Loading branch information
rwaldron committed Dec 10, 2012
1 parent 7d5b86e commit 07a7b3e
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 100 deletions.
73 changes: 45 additions & 28 deletions src/core.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -583,37 +583,45 @@ jQuery.extend({


// args is for internal usage only // args is for internal usage only
each: function( obj, callback, args ) { each: function( obj, callback, args ) {
var name, var value,
i = 0, i = 0,
length = obj.length, length = obj.length,
isObj = length === undefined || jQuery.isFunction( obj ); isArray = isArraylike( obj );


if ( args ) { if ( args ) {
if ( isObj ) { if ( isArray ) {
for ( name in obj ) { for ( ; i < length; i++ ) {
if ( callback.apply( obj[ name ], args ) === false ) { value = callback.apply( obj[ i ], args );

if ( value === false ) {
break; break;
} }
} }
} else { } else {
for ( ; i < length; ) { for ( i in obj ) {
if ( callback.apply( obj[ i++ ], args ) === false ) { value = callback.apply( obj[ i ], args );

if ( value === false ) {
break; break;
} }
} }
} }


// A special, fast, case for the most common use of each // A special, fast, case for the most common use of each
} else { } else {
if ( isObj ) { if ( isArray ) {
for ( name in obj ) { for ( ; i < length; i++ ) {
if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { value = callback.call( obj[ i ], i, obj[ i ] );

if ( value === false ) {
break; break;
} }
} }
} else { } else {
for ( ; i < length; ) { for ( i in obj ) {
if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { value = callback.call( obj[ i ], i, obj[ i ] );

if ( value === false ) {
break; break;
} }
} }
Expand All @@ -640,18 +648,16 @@ jQuery.extend({


// results is for internal usage only // results is for internal usage only
makeArray: function( arr, results ) { makeArray: function( arr, results ) {
var type, var ret = results || [];
ret = results || [];


if ( arr != null ) { if ( arr != null ) {
// The window, strings (and functions) also have 'length' if ( isArraylike( Object(arr) ) ) {
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 jQuery.merge( ret,
type = jQuery.type( arr ); typeof arr === "string" ?

[ arr ] : arr
if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) { );
core_push.call( ret, arr );
} else { } else {
jQuery.merge( ret, arr ); core_push.call( ret, arr );
} }
} }


Expand Down Expand Up @@ -689,7 +695,6 @@ jQuery.extend({
for ( ; j < l; j++ ) { for ( ; j < l; j++ ) {
first[ i++ ] = second[ j ]; first[ i++ ] = second[ j ];
} }

} else { } else {
while ( second[j] !== undefined ) { while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ]; first[ i++ ] = second[ j++ ];
Expand Down Expand Up @@ -722,12 +727,11 @@ jQuery.extend({


// arg is for internal usage only // arg is for internal usage only
map: function( elems, callback, arg ) { map: function( elems, callback, arg ) {
var value, key, var value,
ret = [],
i = 0, i = 0,
length = elems.length, length = elems.length,
// jquery objects are treated as arrays isArray = isArraylike( elems ),
isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; ret = [];


// Go through the array, translating each of the items to their // Go through the array, translating each of the items to their
if ( isArray ) { if ( isArray ) {
Expand All @@ -741,8 +745,8 @@ jQuery.extend({


// Go through every key on the object, // Go through every key on the object,
} else { } else {
for ( key in elems ) { for ( i in elems ) {
value = callback( elems[ key ], key, arg ); value = callback( elems[ i ], i, arg );


if ( value != null ) { if ( value != null ) {
ret[ ret.length ] = value; ret[ ret.length ] = value;
Expand Down Expand Up @@ -907,5 +911,18 @@ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".spli
class2type[ "[object " + name + "]" ] = name.toLowerCase(); class2type[ "[object " + name + "]" ] = name.toLowerCase();
}); });


function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );

if ( jQuery.isWindow( obj ) ) {
return false;
}

return type === "array" || type !== "function" &&
( length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj );
}

// All jQuery objects should point back to these // All jQuery objects should point back to these
rootjQuery = jQuery(document); rootjQuery = jQuery(document);
Loading

2 comments on commit 07a7b3e

@Krinkle
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears this (consistently/reproducibly) broke 1 unit test in Firefox 16 and Firefox 17. http://swarm.jquery.org/job/1832

  • core Pass makeArray a form (treat as elements) Rerun

@rwaldron
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'm looking at this now

Please sign in to comment.