diff --git a/src/core.js b/src/core.js index 056fb88fbb..f527341bae 100644 --- a/src/core.js +++ b/src/core.js @@ -646,18 +646,33 @@ jQuery.extend({ makeArray: function( array, results ) { var ret = results || []; - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } + if ( array == null ) { + return ret; + + } else if ( array.length == null ) { + push.call( ret, array ); + return ret; + } + + var cls = toString.call( array ); + + if ( cls === "[object Array]" || cls === "[object Arguments]" ) { + push.apply( ret, array ); + + } else if ( array instanceof jQuery || !( cls in class2type ) && !jQuery.isWindow( array ) && ( + // form,.. + array.nodeType || + // arguments (using "in" to be sure to not throw exceptions) + ( "callee" in array ) || + // NodeList + array.item && ( array.namedItem || jQuery.isFunction( array.item ) ) || + // jQuery-like + array.jquery && !jQuery.isPlainObject( array ) ) + ) { + jQuery.merge( ret, array ); + + } else { + push.call( ret, array ); } return ret; @@ -848,8 +863,8 @@ jQuery.extend({ browser: {} }); -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { +// Populate the class2type map. Don't add Object! +jQuery.each("Boolean Number String Function Array Date RegExp".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); diff --git a/test/unit/core.js b/test/unit/core.js index 75d3e0e2c1..f5ef1b4dc1 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -867,7 +867,7 @@ test("jQuery.each(Object,Function)", function() { f[i] = "baz"; }); equals( "baz", f.foo, "Loop over a function" ); - + var stylesheet_count = 0; jQuery.each(document.styleSheets, function(i){ stylesheet_count++; @@ -877,7 +877,7 @@ test("jQuery.each(Object,Function)", function() { }); test("jQuery.makeArray", function(){ - expect(17); + expect(16); equals( jQuery.makeArray(jQuery("html>*"))[0].nodeName.toUpperCase(), "HEAD", "Pass makeArray a jQuery object" ); @@ -897,7 +897,7 @@ test("jQuery.makeArray", function(){ equals( jQuery.makeArray( document.createElement("div") )[0].nodeName.toUpperCase(), "DIV", "Pass makeArray a single node" ); - equals( jQuery.makeArray( {length:2, 0:"a", 1:"b"} ).join(""), "ab", "Pass makeArray an array like map (with length)" ); + //equals( jQuery.makeArray( {length:2, 0:"a", 1:"b"} ).join(""), "ab", "Pass makeArray an array like map (with length)" ); ok( !!jQuery.makeArray( document.documentElement.childNodes ).slice(0,1)[0].nodeName, "Pass makeArray a childNodes array" ); @@ -912,8 +912,16 @@ test("jQuery.makeArray", function(){ ok( jQuery.makeArray(document.getElementById("form")).length >= 13, "Pass makeArray a form (treat as elements)" ); // For #5610 - same( jQuery.makeArray({length: "0"}), [], "Make sure object is coerced properly."); - same( jQuery.makeArray({length: "5"}), [], "Make sure object is coerced properly."); + //same( jQuery.makeArray({length: "0"}), [], "Make sure object is coerced properly."); + //same( jQuery.makeArray({length: "5"}), [], "Make sure object is coerced properly."); + + // For #8104 + function Klass( n ) { + this.length = n; + } + equals( jQuery.makeArray( new Klass(0) ).length, 1, "Make sure class instances are not considered arrays" ); + equals( jQuery.makeArray( new Klass(3) ).length, 1, "Make sure class instances are not considered arrays" ); + }); test("jQuery.isEmptyObject", function(){