mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-12 11:57:49 +00:00
Ensure _.keys and _.keysIn skip "length" keys for strict mode arguments objects in Safari 9.
This commit is contained in:
36
lodash.js
36
lodash.js
@@ -4764,20 +4764,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an array of property names based on `object`. If `object` is
|
* Creates an array of index keys for `object` values of arrays,
|
||||||
* an array, `arguments` object, or `string` its index keys are returned,
|
* `arguments` objects, and strings, otherwise `null` is returned.
|
||||||
* otherwise an empty array is returned.
|
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} object The object to query.
|
* @param {Object} object The object to query.
|
||||||
* @returns {Array} Returns the initialized array of property names.
|
* @returns {Array|null} Returns index keys, else `null`.
|
||||||
*/
|
*/
|
||||||
function initKeys(object) {
|
function indexKeys(object) {
|
||||||
var length = object ? object.length : 0;
|
var length = object ? object.length : undefined;
|
||||||
length = (length && isLength(length) &&
|
return (isLength(length) && (isArray(object) || isString(object) || isArguments(object)))
|
||||||
(isArray(object) || isString(object) || isArguments(object)) && length) || 0;
|
? baseTimes(length, String)
|
||||||
|
: null;
|
||||||
return baseTimes(length, String);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10808,13 +10806,14 @@
|
|||||||
if (!(isProto || isArrayLike(object))) {
|
if (!(isProto || isArrayLike(object))) {
|
||||||
return baseKeys(object);
|
return baseKeys(object);
|
||||||
}
|
}
|
||||||
var result = initKeys(object),
|
var indexes = indexKeys(object),
|
||||||
length = result.length,
|
skipIndexes = !!indexes,
|
||||||
skipIndexes = !!length;
|
result = indexes || [],
|
||||||
|
length = result.length;
|
||||||
|
|
||||||
for (var key in object) {
|
for (var key in object) {
|
||||||
if (baseHas(object, key) &&
|
if (baseHas(object, key) &&
|
||||||
!(skipIndexes && isIndex(key, length)) &&
|
!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
|
||||||
!(isProto && key == 'constructor')) {
|
!(isProto && key == 'constructor')) {
|
||||||
result.push(key);
|
result.push(key);
|
||||||
}
|
}
|
||||||
@@ -10849,13 +10848,14 @@
|
|||||||
isProto = isPrototype(object),
|
isProto = isPrototype(object),
|
||||||
props = baseKeysIn(object),
|
props = baseKeysIn(object),
|
||||||
propsLength = props.length,
|
propsLength = props.length,
|
||||||
result = initKeys(object),
|
indexes = indexKeys(object),
|
||||||
length = result.length,
|
skipIndexes = !!indexes,
|
||||||
skipIndexes = !!length;
|
result = indexes || [],
|
||||||
|
length = result.length;
|
||||||
|
|
||||||
while (++index < propsLength) {
|
while (++index < propsLength) {
|
||||||
var key = props[index];
|
var key = props[index];
|
||||||
if (!(skipIndexes && isIndex(key, length)) &&
|
if (!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
|
||||||
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
||||||
result.push(key);
|
result.push(key);
|
||||||
}
|
}
|
||||||
|
|||||||
37
test/test.js
37
test/test.js
@@ -10678,7 +10678,8 @@
|
|||||||
QUnit.module('keys methods');
|
QUnit.module('keys methods');
|
||||||
|
|
||||||
lodashStable.each(['keys', 'keysIn'], function(methodName) {
|
lodashStable.each(['keys', 'keysIn'], function(methodName) {
|
||||||
var args = arguments,
|
var args = (function() { return arguments; }(1, 2, 3)),
|
||||||
|
strictArgs = (function() { 'use strict'; return arguments; }(1, 2, 3)),
|
||||||
func = _[methodName],
|
func = _[methodName],
|
||||||
isKeys = methodName == 'keys';
|
isKeys = methodName == 'keys';
|
||||||
|
|
||||||
@@ -10740,25 +10741,43 @@
|
|||||||
QUnit.test('`_.' + methodName + '` should work with `arguments` objects', function(assert) {
|
QUnit.test('`_.' + methodName + '` should work with `arguments` objects', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
assert.deepEqual(func(args).sort(), ['0', '1', '2']);
|
var values = [args, strictArgs],
|
||||||
|
expected = lodashStable.map(values, lodashStable.constant(['0', '1', '2'])),
|
||||||
|
actual = lodashStable.map(values, func);
|
||||||
|
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('`_.' + methodName + '` should return keys for custom properties on `arguments` objects', function(assert) {
|
QUnit.test('`_.' + methodName + '` should return keys for custom properties on `arguments` objects', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
args.a = 1;
|
var values = [args, strictArgs],
|
||||||
assert.deepEqual(func(args).sort(), ['0', '1', '2', 'a']);
|
expected = lodashStable.map(values, lodashStable.constant(['0', '1', '2', 'a']));
|
||||||
delete args.a;
|
|
||||||
|
var actual = lodashStable.map(values, function(value) {
|
||||||
|
value.a = 1;
|
||||||
|
var result = func(value).sort();
|
||||||
|
delete value.a;
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', function(assert) {
|
QUnit.test('`_.' + methodName + '` should ' + (isKeys ? 'not' : '') + ' include inherited properties of `arguments` objects', function(assert) {
|
||||||
assert.expect(1);
|
assert.expect(1);
|
||||||
|
|
||||||
var expected = isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a'];
|
var values = [args, strictArgs],
|
||||||
|
expected = lodashStable.map(values, lodashStable.constant(isKeys ? ['0', '1', '2'] : ['0', '1', '2', 'a']));
|
||||||
|
|
||||||
objectProto.a = 1;
|
var actual = lodashStable.map(values, function(value) {
|
||||||
assert.deepEqual(func(args).sort(), expected);
|
objectProto.a = 1;
|
||||||
delete objectProto.a;
|
var result = func(value).sort();
|
||||||
|
delete objectProto.a;
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
QUnit.test('`_.' + methodName + '` should work with string objects', function(assert) {
|
QUnit.test('`_.' + methodName + '` should work with string objects', function(assert) {
|
||||||
|
|||||||
Reference in New Issue
Block a user