Ensure _.has returns the correct result for nested sparse arrays. [closes #2614]

This commit is contained in:
John-David Dalton
2016-08-30 17:12:59 -07:00
parent 0263a879c4
commit 0d757fdc40
2 changed files with 37 additions and 16 deletions

View File

@@ -5930,9 +5930,9 @@
function hasPath(object, path, hasFunc) { function hasPath(object, path, hasFunc) {
path = isKey(path, object) ? [path] : castPath(path); path = isKey(path, object) ? [path] : castPath(path);
var result, var index = -1,
index = -1, length = path.length,
length = path.length; result = false;
while (++index < length) { while (++index < length) {
var key = toKey(path[index]); var key = toKey(path[index]);
@@ -5941,10 +5941,10 @@
} }
object = object[key]; object = object[key];
} }
if (result) { if (result || ++index != length) {
return result; return result;
} }
var length = object ? object.length : 0; length = object ? object.length : 0;
return !!length && isLength(length) && isIndex(key, length) && return !!length && isLength(length) && isIndex(key, length) &&
(isArray(object) || isArguments(object)); (isArray(object) || isArguments(object));
} }

View File

@@ -7731,7 +7731,13 @@
lodashStable.each(['has', 'hasIn'], function(methodName) { lodashStable.each(['has', 'hasIn'], function(methodName) {
var args = (function() { return arguments; }(1, 2, 3)), var args = (function() { return arguments; }(1, 2, 3)),
func = _[methodName], func = _[methodName],
isHas = methodName == 'has'; isHas = methodName == 'has',
sparseArgs = (function() { return arguments; }(1)),
sparseArray = Array(1),
sparseString = Object('a');
delete sparseArgs[0];
delete sparseString[0];
QUnit.test('`_.' + methodName + '` should check for own properties', function(assert) { QUnit.test('`_.' + methodName + '` should check for own properties', function(assert) {
assert.expect(2); assert.expect(2);
@@ -7866,14 +7872,10 @@
}); });
}); });
QUnit.test('`_.' + methodName + '` should return `true` for index values within bounds for arrays, `arguments` objects, and strings', function(assert) { QUnit.test('`_.' + methodName + '` should return `true` for indexes of sparse values', function(assert) {
assert.expect(2); assert.expect(1);
var string = Object('abc'); var values = [sparseArgs, sparseArray, sparseString],
delete args[0];
delete string[0];
var values = [Array(3), args, string],
expected = lodashStable.map(values, stubTrue); expected = lodashStable.map(values, stubTrue);
var actual = lodashStable.map(values, function(value) { var actual = lodashStable.map(values, function(value) {
@@ -7881,17 +7883,21 @@
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
});
expected = lodashStable.map(values, lodashStable.constant([true, true])); QUnit.test('`_.' + methodName + '` should return `true` for indexes of sparse values with deep paths', function(assert) {
assert.expect(1);
actual = lodashStable.map(values, function(value) { var values = [sparseArgs, sparseArray, sparseString],
expected = lodashStable.map(values, lodashStable.constant([true, true]));
var actual = lodashStable.map(values, function(value) {
return lodashStable.map(['a[0]', ['a', '0']], function(path) { return lodashStable.map(['a[0]', ['a', '0']], function(path) {
return func({ 'a': value }, path); return func({ 'a': value }, path);
}); });
}); });
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
args[0] = 1;
}); });
QUnit.test('`_.' + methodName + '` should return `false` when `object` is nullish', function(assert) { QUnit.test('`_.' + methodName + '` should return `false` when `object` is nullish', function(assert) {
@@ -7939,6 +7945,21 @@
assert.deepEqual(actual, expected); assert.deepEqual(actual, expected);
}); });
}); });
QUnit.test('`_.' + methodName + '` should return `false` over sparse values of deep paths', function(assert) {
assert.expect(1);
var values = [sparseArgs, sparseArray, sparseString],
expected = lodashStable.map(values, lodashStable.constant([false, false]));
var actual = lodashStable.map(values, function(value) {
return lodashStable.map(['a[0].b', ['a', '0', 'b']], function(path) {
return func({ 'a': value }, path);
});
});
assert.deepEqual(actual, expected);
});
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/