Treat arguments objects like plain objects.

This commit is contained in:
John-David Dalton
2015-01-16 10:01:24 -08:00
committed by jdalton
parent edffe2a6fc
commit bdbafb7a2a
2 changed files with 30 additions and 56 deletions

View File

@@ -1826,10 +1826,7 @@
var tag = objToString.call(value), var tag = objToString.call(value),
isFunc = tag == funcTag; isFunc = tag == funcTag;
if (!lodash.support.argsTag && isArguments(value)) { if (tag == argsTag || tag == objectTag || (isFunc && !object)) {
tag = argsTag;
}
if (tag == objectTag || (isFunc && !object)) {
if (isHostObject(value)) { if (isHostObject(value)) {
return object ? value : {}; return object ? value : {};
} }
@@ -2289,24 +2286,18 @@
if (!objIsArr) { if (!objIsArr) {
objTag = objToString.call(object); objTag = objToString.call(object);
if (isLength(object.length)) { if (objTag == argsTag) {
if (isArguments(object)) { objTag = objectTag;
object = arrayToObject(object); } else if (objTag != objectTag) {
objTag = objectTag; objIsArr = isTypedArray(object);
} else if (objTag != objectTag) {
objIsArr = isTypedArray(object);
}
} }
} }
if (!othIsArr) { if (!othIsArr) {
othTag = objToString.call(other); othTag = objToString.call(other);
if (isLength(other.length)) { if (othTag == argsTag) {
if (isArguments(other)) { othTag = objectTag;
other = arrayToObject(other); } else if (othTag != objectTag) {
othTag = objectTag; othIsArr = isTypedArray(other);
} else if (othTag != objectTag) {
othIsArr = isTypedArray(other);
}
} }
} }
var objIsObj = objTag == objectTag && !isHostObject(object), var objIsObj = objTag == objectTag && !isHostObject(object),
@@ -2528,7 +2519,7 @@
} }
else if (isPlainObject(srcValue) || isArguments(srcValue)) { else if (isPlainObject(srcValue) || isArguments(srcValue)) {
result = isArguments(value) result = isArguments(value)
? arrayToObject(value) ? toPlainObject(value)
: (isPlainObject(value) ? value : {}); : (isPlainObject(value) ? value : {});
} }
} }
@@ -3666,11 +3657,6 @@
function initCloneByTag(object, tag, isDeep) { function initCloneByTag(object, tag, isDeep) {
var Ctor = object.constructor; var Ctor = object.constructor;
switch (tag) { switch (tag) {
case argsTag:
var result = new Ctor;
result.length = object.length;
return arrayCopy(object, result);
case arrayBufferTag: case arrayBufferTag:
return bufferClone(object); return bufferClone(object);
@@ -3693,7 +3679,7 @@
return new Ctor(object); return new Ctor(object);
case regexpTag: case regexpTag:
result = new Ctor(object.source, reFlags.exec(object)); var result = new Ctor(object.source, reFlags.exec(object));
result.lastIndex = object.lastIndex; result.lastIndex = object.lastIndex;
} }
return result; return result;
@@ -4031,17 +4017,6 @@
return result; return result;
} }
/**
* Converts `array` to a plain array-like object.
*
* @private
* @param {Array} array The array to convert.
* @returns {Object} Returns the converted object.
*/
function arrayToObject(array) {
return arrayCopy(array, { 'length': array.length });
}
/** /**
* Converts `value` to an array-like object if it is not one. * Converts `value` to an array-like object if it is not one.
* *
@@ -8366,9 +8341,7 @@
* // => { 'a': 1, 'b': 2, 'c': 3 } * // => { 'a': 1, 'b': 2, 'c': 3 }
*/ */
function toPlainObject(value) { function toPlainObject(value) {
return (isArray(value) || isArguments(value) || isTypedArray(value)) return baseCopy(value, keysIn(value));
? arrayToObject(value)
: baseCopy(value, keysIn(value));
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/

View File

@@ -1786,9 +1786,10 @@
}); });
test('`_.' + methodName + '` should clone array buffers', 2, function() { test('`_.' + methodName + '` should clone array buffers', 2, function() {
var buffer = ArrayBuffer && new ArrayBuffer(10); if (ArrayBuffer) {
if (buffer) { var buffer = new ArrayBuffer(10),
var actual = func(buffer); actual = func(buffer);
strictEqual(actual.byteLength, buffer.byteLength); strictEqual(actual.byteLength, buffer.byteLength);
notStrictEqual(actual, buffer); notStrictEqual(actual, buffer);
} }
@@ -6585,7 +6586,7 @@
test('should treat `arguments` objects like `Object` objects', 4, function() { test('should treat `arguments` objects like `Object` objects', 4, function() {
var args = (function() { return arguments; }(1, 2, 3)), var args = (function() { return arguments; }(1, 2, 3)),
object = { '0': 1, '1': 2, '2': 3, 'length': 3 }; object = { '0': 1, '1': 2, '2': 3 };
function Foo() {} function Foo() {}
Foo.prototype = object; Foo.prototype = object;
@@ -8927,7 +8928,7 @@
test('should merge `arguments` objects', 3, function() { test('should merge `arguments` objects', 3, function() {
var object1 = { 'value': args }, var object1 = { 'value': args },
object2 = { 'value': { '3': 4 } }, object2 = { 'value': { '3': 4 } },
expected = { '0': 1, '1': 2, '2': 3, '3': 4, 'length': 3 }, expected = { '0': 1, '1': 2, '2': 3, '3': 4 },
actual = _.merge(object1, object2); actual = _.merge(object1, object2);
ok(!_.isArguments(actual.value)); ok(!_.isArguments(actual.value));
@@ -8947,9 +8948,9 @@
var arrays = [array2, array1, array4, array3, array2, array4, array4, array3, array2], var arrays = [array2, array1, array4, array3, array2, array4, array4, array3, array2],
buffer = ArrayBuffer && new ArrayBuffer(8); buffer = ArrayBuffer && new ArrayBuffer(8);
if (root.Float64Array) { // juggle for `Float64Array` shim
// juggle for `Float64Array` shim if (root.Float64Array && (new Float64Array(buffer)).length == 8) {
arrays[1] = _.size(new Float64Array(buffer)) > 1 ? array4 : array1; arrays[1] = array4;
} }
var expected = _.map(typedArrays, function(type, index) { var expected = _.map(typedArrays, function(type, index) {
var array = arrays[index].slice(); var array = arrays[index].slice();
@@ -13213,30 +13214,30 @@
test('should convert `arguments` objects to plain objects', 1, function() { test('should convert `arguments` objects to plain objects', 1, function() {
var actual = _.toPlainObject(args), var actual = _.toPlainObject(args),
expected = { '0': 1, '1': 2, '2': 3, 'length': 3 }; expected = { '0': 1, '1': 2, '2': 3 };
deepEqual(actual, expected); deepEqual(actual, expected);
}); });
test('should convert arrays to plain objects', 1, function() { test('should convert arrays to plain objects', 1, function() {
var actual = _.toPlainObject(['a', 'b', 'c']), var actual = _.toPlainObject(['a', 'b', 'c']),
expected = { '0': 'a', '1': 'b', '2': 'c', 'length': 3 }; expected = { '0': 'a', '1': 'b', '2': 'c' };
deepEqual(actual, expected); deepEqual(actual, expected);
}); });
test('should convert typed arrays to plain objects', 1, function() { test('should convert typed arrays to plain objects', 1, function() {
var object1 = { '0': 0, 'length': 1 }, var object1 = { '0': 0 },
object2 = { '0': 0, '1': 0, 'length': 2 }, object2 = { '0': 0, '1': 0 },
object3 = { '0': 0, '1': 0, '2': 0, '3': 0, 'length': 4 }, object3 = { '0': 0, '1': 0, '2': 0, '3': 0 },
object4 = { '0': 0, '1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, 'length': 8 }; object4 = { '0': 0, '1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0 };
var objects = [object2, object1, object4, object3, object2, object4, object4, object3, object2], var objects = [object2, object1, object4, object3, object2, object4, object4, object3, object2],
buffer = ArrayBuffer && new ArrayBuffer(8); buffer = ArrayBuffer && new ArrayBuffer(8);
if (root.Float64Array) { // juggle for `Float64Array` shim
// juggle for `Float64Array` shim if (root.Float64Array && (new Float64Array(buffer)).length == 8) {
objects[1] = _.size(new Float64Array(buffer)) > 1 ? object4 : object1; objects[1] = object4;
} }
var expected = _.map(typedArrays, function(type, index) { var expected = _.map(typedArrays, function(type, index) {
return root[type] ? objects[index] : false; return root[type] ? objects[index] : false;