mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-10 10:57:49 +00:00
Remove support for cloning arrays and make _.isEqual more robust when comparing errors.
This commit is contained in:
38
lodash.js
38
lodash.js
@@ -162,16 +162,16 @@
|
|||||||
|
|
||||||
/** Used to identify object classifications that `_.clone` supports */
|
/** Used to identify object classifications that `_.clone` supports */
|
||||||
var cloneableClasses = {};
|
var cloneableClasses = {};
|
||||||
cloneableClasses[argsClass] =
|
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
|
||||||
cloneableClasses[arrayClass] = cloneableClasses[arrayBufferClass] =
|
cloneableClasses[arrayBufferClass] = cloneableClasses[boolClass] =
|
||||||
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
|
cloneableClasses[dateClass] = cloneableClasses[float32Class] =
|
||||||
cloneableClasses[errorClass] = cloneableClasses[float32Class] =
|
|
||||||
cloneableClasses[float64Class] = cloneableClasses[int8Class] =
|
cloneableClasses[float64Class] = cloneableClasses[int8Class] =
|
||||||
cloneableClasses[int16Class] = cloneableClasses[int32Class] =
|
cloneableClasses[int16Class] = cloneableClasses[int32Class] =
|
||||||
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
|
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
|
||||||
cloneableClasses[regexpClass] = cloneableClasses[stringClass] =
|
cloneableClasses[regexpClass] = cloneableClasses[stringClass] =
|
||||||
cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] =
|
cloneableClasses[uint8Class] = cloneableClasses[uint8ClampedClass] =
|
||||||
cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true;
|
cloneableClasses[uint16Class] = cloneableClasses[uint32Class] = true;
|
||||||
|
cloneableClasses[errorClass] =
|
||||||
cloneableClasses[funcClass] = cloneableClasses[mapClass] =
|
cloneableClasses[funcClass] = cloneableClasses[mapClass] =
|
||||||
cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false;
|
cloneableClasses[setClass] = cloneableClasses[weakMapClass] = false;
|
||||||
|
|
||||||
@@ -1237,9 +1237,6 @@
|
|||||||
case dateClass:
|
case dateClass:
|
||||||
return new Ctor(+value);
|
return new Ctor(+value);
|
||||||
|
|
||||||
case errorClass:
|
|
||||||
return new Ctor(value.message);
|
|
||||||
|
|
||||||
case float32Class: case float64Class:
|
case float32Class: case float64Class:
|
||||||
case int8Class: case int16Class: case int32Class:
|
case int8Class: case int16Class: case int32Class:
|
||||||
case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class:
|
case uint8Class: case uint8ClampedClass: case uint16Class: case uint32Class:
|
||||||
@@ -1791,10 +1788,6 @@
|
|||||||
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
|
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
|
||||||
return +value == +other;
|
return +value == +other;
|
||||||
|
|
||||||
case errorClass:
|
|
||||||
// check properties instead of coercing to strings to support IE < 8
|
|
||||||
return value.name === other.name && value.message === other.message;
|
|
||||||
|
|
||||||
case numberClass:
|
case numberClass:
|
||||||
// treat `NaN` vs. `NaN` as equal
|
// treat `NaN` vs. `NaN` as equal
|
||||||
return (value != +value)
|
return (value != +value)
|
||||||
@@ -1804,18 +1797,20 @@
|
|||||||
|
|
||||||
case regexpClass:
|
case regexpClass:
|
||||||
case stringClass:
|
case stringClass:
|
||||||
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
|
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4) and
|
||||||
// treat string primitives and object instances as equal
|
// treat strings primitives and string objects as equal
|
||||||
return value == String(other);
|
return value == String(other);
|
||||||
}
|
}
|
||||||
|
var isArr = arrayLikeClasses[valClass],
|
||||||
|
isErr = valClass == errorClass;
|
||||||
|
|
||||||
if (!support.argsClass) {
|
if (!support.argsClass) {
|
||||||
valIsArg = isArguments(value);
|
valIsArg = isArguments(value);
|
||||||
othIsArg = isArguments(other);
|
othIsArg = isArguments(other);
|
||||||
}
|
}
|
||||||
var isArr = arrayLikeClasses[valClass];
|
|
||||||
if (!isArr) {
|
if (!isArr) {
|
||||||
// exit for functions and DOM nodes
|
// exit for things like functions and DOM nodes
|
||||||
if (valClass != objectClass || (!support.nodeClass && (isNode(value) || isNode(other)))) {
|
if (!(isErr || valClass == objectClass) || (!support.nodeClass && (isNode(value) || isNode(other)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// unwrap any `lodash` wrapped values
|
// unwrap any `lodash` wrapped values
|
||||||
@@ -1836,6 +1831,10 @@
|
|||||||
var valCtor = valIsArg ? Object : value.constructor,
|
var valCtor = valIsArg ? Object : value.constructor,
|
||||||
othCtor = othIsArg ? Object : other.constructor;
|
othCtor = othIsArg ? Object : other.constructor;
|
||||||
|
|
||||||
|
// error objects of different types are not equal
|
||||||
|
if (isErr && valCtor.prototype.name != othCtor.prototype.name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// non `Object` object instances with different constructors are not equal
|
// non `Object` object instances with different constructors are not equal
|
||||||
if (valCtor != othCtor &&
|
if (valCtor != othCtor &&
|
||||||
!(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) &&
|
!(isFunction(valCtor) && valCtor instanceof valCtor && isFunction(othCtor) && othCtor instanceof othCtor) &&
|
||||||
@@ -1895,8 +1894,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var valProps = keys(value),
|
var valProps = isErr ? ['message', 'name'] : keys(value),
|
||||||
othProps = keys(other);
|
othProps = isErr ? ['message', 'name'] : keys(other);
|
||||||
|
|
||||||
if (valIsArg) {
|
if (valIsArg) {
|
||||||
valProps.push('length');
|
valProps.push('length');
|
||||||
@@ -1910,7 +1909,8 @@
|
|||||||
if (result || isWhere) {
|
if (result || isWhere) {
|
||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
var key = valProps[index];
|
var key = valProps[index];
|
||||||
result = hasOwnProperty.call(other, key);
|
result = isErr || hasOwnProperty.call(other, key);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
valValue = value[key];
|
valValue = value[key];
|
||||||
othValue = other[key];
|
othValue = other[key];
|
||||||
|
|||||||
50
test/test.js
50
test/test.js
@@ -1241,30 +1241,30 @@
|
|||||||
Klass.prototype = { 'b': 1 };
|
Klass.prototype = { 'b': 1 };
|
||||||
|
|
||||||
var nonCloneable = {
|
var nonCloneable = {
|
||||||
'a DOM element': body,
|
'DOM elements': body,
|
||||||
'a function': Klass
|
'functions': Klass
|
||||||
};
|
};
|
||||||
|
|
||||||
var objects = {
|
var objects = {
|
||||||
'an `arguments` object': arguments,
|
'`arguments` objects': arguments,
|
||||||
'an array': ['a', ''],
|
'arrays': ['a', ''],
|
||||||
'an array-like-object': { '0': 'a', '1': '', 'length': 3 },
|
'array-like-objects': { '0': 'a', '1': '', 'length': 3 },
|
||||||
'boolean': false,
|
'booleans': false,
|
||||||
'boolean object': Object(false),
|
'boolean objects': Object(false),
|
||||||
'a Klass instance': new Klass,
|
'Klass instances': new Klass,
|
||||||
'an object': { 'a': 0, 'b': 1, 'c': 3 },
|
'objects': { 'a': 0, 'b': 1, 'c': 3 },
|
||||||
'an object with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } },
|
'objects with object values': { 'a': /a/, 'b': ['B'], 'c': { 'C': 1 } },
|
||||||
'an object from another document': _._object || {},
|
'objects from another document': _._object || {},
|
||||||
'null': null,
|
'null values': null,
|
||||||
'a number': 3,
|
'numbers': 3,
|
||||||
'a number object': Object(3),
|
'number objects': Object(3),
|
||||||
'a regexp': /a/gim,
|
'regexes': /a/gim,
|
||||||
'a string': 'a',
|
'strings': 'a',
|
||||||
'a string object': Object('a'),
|
'string objects': Object('a'),
|
||||||
'undefined': undefined
|
'undefined values': undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
objects['an array'].length = 3;
|
objects['arrays'].length = 3;
|
||||||
|
|
||||||
test('`_.clone` should shallow clone by default', 2, function() {
|
test('`_.clone` should shallow clone by default', 2, function() {
|
||||||
var expected = [{ 'a': 0 }, { 'b': 1 }],
|
var expected = [{ 'a': 0 }, { 'b': 1 }],
|
||||||
@@ -1313,13 +1313,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
_.each(errorTypes, function(type) {
|
_.each(errorTypes, function(type) {
|
||||||
test('`_.' + methodName + '` should clone ' + type + ' objects', 2, function() {
|
test('`_.' + methodName + '` should not clone ' + type + ' objects', 1, function() {
|
||||||
var Ctor = root[type],
|
var error = new root[type];
|
||||||
error = new Ctor('text'),
|
strictEqual(func(error), error);
|
||||||
actual = func(error);
|
|
||||||
|
|
||||||
ok(_.isEqual(actual, error));
|
|
||||||
notStrictEqual(actual, error);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1426,7 +1422,7 @@
|
|||||||
|
|
||||||
test('`_.' + methodName + '` should return a unwrapped value when chaining', 2, function() {
|
test('`_.' + methodName + '` should return a unwrapped value when chaining', 2, function() {
|
||||||
if (!isNpm) {
|
if (!isNpm) {
|
||||||
var object = objects['an object'],
|
var object = objects['objects'],
|
||||||
actual = _(object)[methodName]();
|
actual = _(object)[methodName]();
|
||||||
|
|
||||||
deepEqual(actual, object);
|
deepEqual(actual, object);
|
||||||
|
|||||||
Reference in New Issue
Block a user