diff --git a/src/Angular.js b/src/Angular.js index a6b82c7e9188..a5f335e21844 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -215,7 +215,8 @@ function isArrayLike(obj) { // NodeList objects (with `item` method) and // other objects with suitable length characteristics are array-like return isNumber(length) && - (length >= 0 && (length - 1) in obj || typeof obj.item == 'function'); + (length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item == 'function'); + } /** diff --git a/test/AngularSpec.js b/test/AngularSpec.js index d397edb8d682..e64abb9e5229 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -1218,17 +1218,38 @@ describe('angular', function() { }); it('should return true if passed a nodelist', function() { - var nodes = document.body.childNodes; - expect(isArrayLike(nodes)).toBe(true); + var nodes1 = document.body.childNodes; + expect(isArrayLike(nodes1)).toBe(true); + + var nodes2 = document.getElementsByTagName('nonExistingTagName'); + expect(isArrayLike(nodes2)).toBe(true); }); it('should return false for objects with `length` but no matching indexable items', function() { - var obj = { + var obj1 = { a: 'a', b:'b', length: 10 }; - expect(isArrayLike(obj)).toBe(false); + expect(isArrayLike(obj1)).toBe(false); + + var obj2 = { + length: 0 + }; + expect(isArrayLike(obj2)).toBe(false); + }); + + it('should return true for empty instances of an Array subclass', function() { + function ArrayLike() {} + ArrayLike.prototype = Array.prototype; + + var arrLike = new ArrayLike(); + expect(arrLike.length).toBe(0); + expect(isArrayLike(arrLike)).toBe(true); + + arrLike.push(1, 2, 3); + expect(arrLike.length).toBe(3); + expect(isArrayLike(arrLike)).toBe(true); }); });