diff --git a/lodash.js b/lodash.js index 6346dbd82..c8ce4929c 100644 --- a/lodash.js +++ b/lodash.js @@ -6081,9 +6081,9 @@ } /** - * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a - * length of `0` and objects with no own enumerable properties are considered - * "empty". + * Checks if a collection is empty. A value is considered empty unless it is + * an array, array-like object, or string with a length greater than `0` or + * an object with own properties. * * @static * @memberOf _ @@ -6115,9 +6115,11 @@ var className = toString.call(value), length = value.length; - if ((className == arrayClass || className == stringClass || - (support.argsClass ? className == argsClass : isArguments(value))) || - (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + if (length > -1 && length <= maxSafeInteger && ( + (className == arrayClass || className == stringClass || + (support.argsClass ? className == argsClass : isArguments(value))) || + (className == objectClass && isFunction(value.splice)) + )) { return !length; } baseForOwn(value, function() { diff --git a/test/test.js b/test/test.js index 2aa579100..a517fd718 100644 --- a/test/test.js +++ b/test/test.js @@ -3971,6 +3971,43 @@ strictEqual(_.isEmpty('a'), false); }); + test('should work with an object that has a `length` property', 1, function() { + strictEqual(_.isEmpty({ 'length': 0 }), false); + }); + + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantomPage) { + strictEqual(_.isEmpty(args), false); + } else { + skipTest(); + } + }); + + test('should work with jQuery/MooTools DOM query collections', 1, function() { + function Foo(elements) { push.apply(this, elements); } + Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; + + strictEqual(_.isEmpty(new Foo([])), true); + }); + + test('should not treat objects with negative lengths as array-like', 1, function() { + function Foo() {} + Foo.prototype.length = -1; + + strictEqual(_.isEmpty(new Foo), true); + }); + + test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { + function Foo() {} + Foo.prototype.length = maxSafeInteger + 1; + + strictEqual(_.isEmpty(new Foo), true); + }); + + test('should not treat objects with non-number lengths as array-like', 1, function() { + strictEqual(_.isEmpty({ 'length': '0' }), false); + }); + test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() { equal(_.isEmpty(shadowedObject), false); }); @@ -3984,25 +4021,6 @@ strictEqual(_.isEmpty(Foo), true); }); - test('should work with an object that has a `length` property', 1, function() { - strictEqual(_.isEmpty({ 'length': 0 }), false); - }); - - test('should work with jQuery/MooTools DOM query collections', 1, function() { - function Foo(elements) { push.apply(this, elements); } - Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; - - strictEqual(_.isEmpty(new Foo([])), true); - }); - - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantomPage) { - strictEqual(_.isEmpty(args), false); - } else { - skipTest(); - } - }); - test('should return an unwrapped value when intuitively chaining', 1, function() { if (!isNpm) { strictEqual(_({}).isEmpty(), true); @@ -6055,7 +6073,6 @@ }); }()); - /*--------------------------------------------------------------------------*/ QUnit.module('lodash.pad'); @@ -7422,6 +7439,14 @@ deepEqual(actual, expected); }); + test('should work with `arguments` objects (test in IE < 9)', 1, function() { + if (!isPhantomPage) { + equal(_.size(args), 3); + } else { + skipTest(); + } + }); + test('should work with jQuery/MooTools DOM query collections', 1, function() { function Foo(elements) { push.apply(this, elements); } Foo.prototype = { 'length': 0, 'splice': Array.prototype.splice }; @@ -7429,12 +7454,16 @@ equal(_.size(new Foo(array)), 3); }); - test('should work with `arguments` objects (test in IE < 9)', 1, function() { - if (!isPhantomPage) { - equal(_.size(args), 3); - } else { - skipTest(); - } + test('should not treat objects with negative lengths as array-like', 1, function() { + strictEqual(_.size({ 'length': -1 }), 1); + }); + + test('should not treat objects with lengths larger than `maxSafeInteger` as array-like', 1, function() { + strictEqual(_.size({ 'length': maxSafeInteger + 1 }), 1); + }); + + test('should not treat objects with non-number lengths as array-like', 1, function() { + strictEqual(_.size({ 'length': '0' }), 1); }); test('fixes the JScript [[DontEnum]] bug (test in IE < 9)', 1, function() {