summaryrefslogtreecommitdiff
path: root/lib/internal/util/comparisons.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/internal/util/comparisons.js')
-rw-r--r--lib/internal/util/comparisons.js153
1 files changed, 47 insertions, 106 deletions
diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js
index d072608906..3470f20666 100644
--- a/lib/internal/util/comparisons.js
+++ b/lib/internal/util/comparisons.js
@@ -14,7 +14,9 @@ const {
isStringObject,
isBooleanObject,
isBigIntObject,
- isSymbolObject
+ isSymbolObject,
+ isFloat32Array,
+ isFloat64Array
} = require('internal/util/types');
const {
getOwnNonIndexProperties,
@@ -84,18 +86,6 @@ function areEqualArrayBuffers(buf1, buf2) {
compare(new Uint8Array(buf1), new Uint8Array(buf2)) === 0;
}
-function isFloatTypedArrayTag(tag) {
- return tag === '[object Float32Array]' || tag === '[object Float64Array]';
-}
-
-function isArguments(tag) {
- return tag === '[object Arguments]';
-}
-
-function isObjectOrArrayTag(tag) {
- return tag === '[object Array]' || tag === '[object Object]';
-}
-
function isEqualBoxedPrimitive(val1, val2) {
if (isNumberObject(val1)) {
return isNumberObject(val2) &&
@@ -132,13 +122,38 @@ function isEqualBoxedPrimitive(val1, val2) {
// For strict comparison, objects should have
// a) The same built-in type tags
// b) The same prototypes.
-function strictDeepEqual(val1, val2, memos) {
- if (typeof val1 !== 'object') {
- return typeof val1 === 'number' && numberIsNaN(val1) &&
- numberIsNaN(val2);
+
+function innerDeepEqual(val1, val2, strict, memos) {
+ // All identical values are equivalent, as determined by ===.
+ if (val1 === val2) {
+ if (val1 !== 0)
+ return true;
+ return strict ? objectIs(val1, val2) : true;
}
- if (typeof val2 !== 'object' || val1 === null || val2 === null) {
- return false;
+
+ // Check more closely if val1 and val2 are equal.
+ if (strict) {
+ if (typeof val1 !== 'object') {
+ return typeof val1 === 'number' && numberIsNaN(val1) &&
+ numberIsNaN(val2);
+ }
+ if (typeof val2 !== 'object' || val1 === null || val2 === null) {
+ return false;
+ }
+ if (getPrototypeOf(val1) !== getPrototypeOf(val2)) {
+ return false;
+ }
+ } else {
+ if (val1 === null || typeof val1 !== 'object') {
+ if (val2 === null || typeof val2 !== 'object') {
+ // eslint-disable-next-line eqeqeq
+ return val1 == val2;
+ }
+ return false;
+ }
+ if (val2 === null || typeof val2 !== 'object') {
+ return false;
+ }
}
const val1Tag = objectToString(val1);
const val2Tag = objectToString(val2);
@@ -146,9 +161,6 @@ function strictDeepEqual(val1, val2, memos) {
if (val1Tag !== val2Tag) {
return false;
}
- if (getPrototypeOf(val1) !== getPrototypeOf(val2)) {
- return false;
- }
if (Array.isArray(val1)) {
// Check for sparse arrays and general fast path
if (val1.length !== val2.length) {
@@ -159,10 +171,10 @@ function strictDeepEqual(val1, val2, memos) {
if (keys1.length !== keys2.length) {
return false;
}
- return keyCheck(val1, val2, kStrict, memos, kIsArray, keys1);
+ return keyCheck(val1, val2, strict, memos, kIsArray, keys1);
}
if (val1Tag === '[object Object]') {
- return keyCheck(val1, val2, kStrict, memos, kNoIterator);
+ return keyCheck(val1, val2, strict, memos, kNoIterator);
}
if (isDate(val1)) {
if (dateGetTime(val1) !== dateGetTime(val2)) {
@@ -174,13 +186,16 @@ function strictDeepEqual(val1, val2, memos) {
}
} else if (isNativeError(val1) || val1 instanceof Error) {
// Do not compare the stack as it might differ even though the error itself
- // is otherwise identical. The non-enumerable name should be identical as
- // the prototype is also identical. Otherwise this is caught later on.
- if (val1.message !== val2.message) {
+ // is otherwise identical.
+ if (val1.message !== val2.message || val1.name !== val2.name) {
return false;
}
} else if (isArrayBufferView(val1)) {
- if (!areSimilarTypedArrays(val1, val2)) {
+ if (!strict && (isFloat32Array(val1) || isFloat64Array(val1))) {
+ if (!areSimilarFloatArrays(val1, val2)) {
+ return false;
+ }
+ } else if (!areSimilarTypedArrays(val1, val2)) {
return false;
}
// Buffer.compare returns true, so val1.length === val2.length. If they both
@@ -191,17 +206,17 @@ function strictDeepEqual(val1, val2, memos) {
if (keys1.length !== keys2.length) {
return false;
}
- return keyCheck(val1, val2, kStrict, memos, kNoIterator, keys1);
+ return keyCheck(val1, val2, strict, memos, kNoIterator, keys1);
} else if (isSet(val1)) {
if (!isSet(val2) || val1.size !== val2.size) {
return false;
}
- return keyCheck(val1, val2, kStrict, memos, kIsSet);
+ return keyCheck(val1, val2, strict, memos, kIsSet);
} else if (isMap(val1)) {
if (!isMap(val2) || val1.size !== val2.size) {
return false;
}
- return keyCheck(val1, val2, kStrict, memos, kIsMap);
+ return keyCheck(val1, val2, strict, memos, kIsMap);
} else if (isAnyArrayBuffer(val1)) {
if (!areEqualArrayBuffers(val1, val2)) {
return false;
@@ -209,66 +224,7 @@ function strictDeepEqual(val1, val2, memos) {
} else if (isBoxedPrimitive(val1) && !isEqualBoxedPrimitive(val1, val2)) {
return false;
}
- return keyCheck(val1, val2, kStrict, memos, kNoIterator);
-}
-
-function looseDeepEqual(val1, val2, memos) {
- if (val1 === null || typeof val1 !== 'object') {
- if (val2 === null || typeof val2 !== 'object') {
- // eslint-disable-next-line eqeqeq
- return val1 == val2;
- }
- return false;
- }
- if (val2 === null || typeof val2 !== 'object') {
- return false;
- }
- const val1Tag = objectToString(val1);
- const val2Tag = objectToString(val2);
- if (val1Tag === val2Tag) {
- if (isObjectOrArrayTag(val1Tag)) {
- return keyCheck(val1, val2, kLoose, memos, kNoIterator);
- }
- if (isArrayBufferView(val1)) {
- if (isFloatTypedArrayTag(val1Tag)) {
- return areSimilarFloatArrays(val1, val2);
- }
- return areSimilarTypedArrays(val1, val2);
- }
- if (isDate(val1) && isDate(val2)) {
- return val1.getTime() === val2.getTime();
- }
- if (isRegExp(val1) && isRegExp(val2)) {
- return areSimilarRegExps(val1, val2);
- }
- if (val1 instanceof Error && val2 instanceof Error) {
- if (val1.message !== val2.message || val1.name !== val2.name)
- return false;
- }
- // Ensure reflexivity of deepEqual with `arguments` objects.
- // See https://github.com/nodejs/node-v0.x-archive/pull/7178
- } else if (isArguments(val1Tag) || isArguments(val2Tag)) {
- return false;
- }
- if (isSet(val1)) {
- if (!isSet(val2) || val1.size !== val2.size) {
- return false;
- }
- return keyCheck(val1, val2, kLoose, memos, kIsSet);
- } else if (isMap(val1)) {
- if (!isMap(val2) || val1.size !== val2.size) {
- return false;
- }
- return keyCheck(val1, val2, kLoose, memos, kIsMap);
- } else if (isSet(val2) || isMap(val2)) {
- return false;
- }
- if (isAnyArrayBuffer(val1) && isAnyArrayBuffer(val2)) {
- if (!areEqualArrayBuffers(val1, val2)) {
- return false;
- }
- }
- return keyCheck(val1, val2, kLoose, memos, kNoIterator);
+ return keyCheck(val1, val2, strict, memos, kNoIterator);
}
function getEnumerables(val, keys) {
@@ -370,21 +326,6 @@ function keyCheck(val1, val2, strict, memos, iterationType, aKeys) {
return areEq;
}
-function innerDeepEqual(val1, val2, strict, memos) {
- // All identical values are equivalent, as determined by ===.
- if (val1 === val2) {
- if (val1 !== 0)
- return true;
- return strict ? objectIs(val1, val2) : true;
- }
-
- // Check more closely if val1 and val2 are equal.
- if (strict === true)
- return strictDeepEqual(val1, val2, memos);
-
- return looseDeepEqual(val1, val2, memos);
-}
-
function setHasEqualElement(set, val1, strict, memo) {
// Go looking.
for (const val2 of set) {