mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-15 05:07:49 +00:00
Ensure wrapped arrays are compared correctly in _.isEqual. [closes #676]
This commit is contained in:
40
lodash.js
40
lodash.js
@@ -1846,7 +1846,7 @@
|
||||
othType = typeof other;
|
||||
|
||||
// exit early for unlike primitive values
|
||||
if (value === value && (value == null || other == null ||
|
||||
if (!(valType == 'number' && othType == 'number') && (value == null || other == null ||
|
||||
(valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object'))) {
|
||||
return false;
|
||||
}
|
||||
@@ -1861,13 +1861,13 @@
|
||||
if (othIsArg) {
|
||||
othClass = objectClass;
|
||||
}
|
||||
if (valClass != othClass) {
|
||||
return false;
|
||||
}
|
||||
var isArr = arrayLikeClasses[valClass],
|
||||
isErr = valClass == errorClass;
|
||||
var valIsArr = arrayLikeClasses[valClass],
|
||||
valIsErr = valClass == errorClass,
|
||||
valIsObj = valClass == objectClass && !isHostObject(value),
|
||||
othIsObj = othClass == objectClass && !isHostObject(other);
|
||||
|
||||
if (isArr) {
|
||||
var isSameClass = valClass == othClass;
|
||||
if (isSameClass && valIsArr) {
|
||||
var valLength = value.length,
|
||||
othLength = other.length;
|
||||
|
||||
@@ -1875,14 +1875,18 @@
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (isErr || (valClass == objectClass && (support.nodeClass || !(isHostObject(value) || isHostObject(other))))) {
|
||||
else {
|
||||
// unwrap any `lodash` wrapped values
|
||||
var valWrapped = hasOwnProperty.call(value, '__wrapped__'),
|
||||
othWrapped = hasOwnProperty.call(other, '__wrapped__');
|
||||
var valWrapped = valIsObj && hasOwnProperty.call(value, '__wrapped__'),
|
||||
othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
||||
|
||||
if (valWrapped || othWrapped) {
|
||||
return baseIsEqual(valWrapped ? value.__wrapped__ : value, othWrapped ? other.__wrapped__ : other, customizer, isWhere, stackA, stackB);
|
||||
}
|
||||
if (!isSameClass) {
|
||||
return false;
|
||||
}
|
||||
if (valIsErr || valIsObj) {
|
||||
if (!support.argsClass) {
|
||||
valIsArg = isArguments(value);
|
||||
othIsArg = isArguments(other);
|
||||
@@ -1891,12 +1895,13 @@
|
||||
var valCtor = valIsArg ? Object : value.constructor,
|
||||
othCtor = othIsArg ? Object : other.constructor;
|
||||
|
||||
if (isErr) {
|
||||
if (valIsErr) {
|
||||
// error objects of different types are not equal
|
||||
if (valCtor.prototype.name != othCtor.prototype.name) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
var valHasCtor = !valIsArg && hasOwnProperty.call(value, 'constructor'),
|
||||
othHasCtor = !othIsArg && hasOwnProperty.call(other, 'constructor');
|
||||
|
||||
@@ -1913,8 +1918,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
var valProps = isErr ? ['message', 'name'] : keys(value),
|
||||
othProps = isErr ? valProps : keys(other);
|
||||
var valProps = valIsErr ? ['message', 'name'] : keys(value),
|
||||
othProps = valIsErr ? valProps : keys(other);
|
||||
|
||||
if (valIsArg) {
|
||||
valProps.push('length');
|
||||
@@ -1951,6 +1956,7 @@
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// assume cyclic structures are equal
|
||||
// the algorithm for detecting cyclic structures is adapted from ES 5.1
|
||||
// section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
|
||||
@@ -1969,7 +1975,7 @@
|
||||
|
||||
// recursively compare objects and arrays (susceptible to call stack limits)
|
||||
result = true;
|
||||
if (isArr) {
|
||||
if (valIsArr) {
|
||||
// deep compare the contents, ignoring non-numeric properties
|
||||
while (result && ++index < valLength) {
|
||||
var valValue = value[index];
|
||||
@@ -1993,7 +1999,7 @@
|
||||
else {
|
||||
while (result && ++index < valLength) {
|
||||
var key = valProps[index];
|
||||
result = isErr || hasOwnProperty.call(other, key);
|
||||
result = valIsErr || hasOwnProperty.call(other, key);
|
||||
|
||||
if (result) {
|
||||
valValue = value[key];
|
||||
@@ -2943,7 +2949,7 @@
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is a host object, else `false`.
|
||||
*/
|
||||
var isHostObject = support.hostObject ? constant(false) : function(value) {
|
||||
var isHostObject = !support.hostObject ? constant(false) : function(value) {
|
||||
// IE < 9 presents many host objects as `Object` objects that can coerce to
|
||||
// strings despite having improperly defined `toString` methods
|
||||
return typeof value.toString != 'function' && typeof (value + '') == 'string';
|
||||
|
||||
27
test/test.js
27
test/test.js
@@ -5805,19 +5805,31 @@
|
||||
}
|
||||
});
|
||||
|
||||
test('should perform comparisons between wrapped values', 4, function() {
|
||||
test('should perform comparisons between wrapped values', 32, function() {
|
||||
var values = [
|
||||
[[1, 2], [1, 2], [1, 2, 3]],
|
||||
[true, true, false],
|
||||
[new Date, new Date, new Date(new Date - 100)],
|
||||
[{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 1 }],
|
||||
[1, 1, 2],
|
||||
[NaN, NaN, Infinity],
|
||||
[/x/, /x/, /x/i],
|
||||
['a', 'a', 'A']
|
||||
];
|
||||
|
||||
_.each(values, function(vals) {
|
||||
if (!isNpm) {
|
||||
var object1 = _({ 'a': 1, 'b': 2 }),
|
||||
object2 = _({ 'a': 1, 'b': 2 }),
|
||||
actual = object1.isEqual(object2);
|
||||
var wrapper1 = _(vals[0]),
|
||||
wrapper2 = _(vals[1]),
|
||||
actual = wrapper1.isEqual(wrapper2);
|
||||
|
||||
strictEqual(actual, true);
|
||||
strictEqual(_.isEqual(_(actual), _(true)), true);
|
||||
|
||||
object1 = _({ 'a': 1, 'b': 2 });
|
||||
object2 = _({ 'a': 1, 'b': 1 });
|
||||
wrapper1 = _(vals[0]);
|
||||
wrapper2 = _(vals[2]);
|
||||
|
||||
actual = object1.isEqual(object2);
|
||||
actual = wrapper1.isEqual(wrapper2);
|
||||
strictEqual(actual, false);
|
||||
strictEqual(_.isEqual(_(actual), _(false)), true);
|
||||
}
|
||||
@@ -5825,6 +5837,7 @@
|
||||
skipTest(4);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('should perform comparisons between wrapped and non-wrapped values', 4, function() {
|
||||
if (!isNpm) {
|
||||
|
||||
Reference in New Issue
Block a user