mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
assert,util: improve comparison performance
This makes sure that the toStringTag symbol is used, if available instead of calculating the toString() value each time, if not needed (the type checks make a brand check, so there is no need to check the toStringTag, if non is defined on the object). PR-URL: https://github.com/nodejs/node/pull/61176 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
This commit is contained in:
committed by
GitHub
parent
879b95efea
commit
5c8ce910bd
@@ -41,6 +41,7 @@ const {
|
||||
StringPrototypeValueOf,
|
||||
Symbol,
|
||||
SymbolPrototypeValueOf,
|
||||
SymbolToStringTag,
|
||||
TypedArrayPrototypeGetByteLength: getByteLength,
|
||||
TypedArrayPrototypeGetSymbolToStringTag,
|
||||
Uint16Array,
|
||||
@@ -264,6 +265,17 @@ function innerDeepEqual(val1, val2, mode, memos) {
|
||||
return objectComparisonStart(val1, val2, mode, memos);
|
||||
}
|
||||
|
||||
function hasUnequalTag(val1, val2) {
|
||||
return val1[SymbolToStringTag] !== val2[SymbolToStringTag];
|
||||
}
|
||||
|
||||
function slowHasUnequalTag(val1Tag, val1, val2) {
|
||||
if (val1[SymbolToStringTag] !== undefined && val2[SymbolToStringTag] !== undefined) {
|
||||
return val1[SymbolToStringTag] !== val2[SymbolToStringTag];
|
||||
}
|
||||
return val1Tag !== ObjectPrototypeToString(val2);
|
||||
}
|
||||
|
||||
function objectComparisonStart(val1, val2, mode, memos) {
|
||||
if (mode === kStrict) {
|
||||
if (wellKnownConstructors.has(val1.constructor) ||
|
||||
@@ -276,16 +288,10 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
}
|
||||
}
|
||||
|
||||
const val1Tag = ObjectPrototypeToString(val1);
|
||||
const val2Tag = ObjectPrototypeToString(val2);
|
||||
|
||||
if (val1Tag !== val2Tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ArrayIsArray(val1)) {
|
||||
if (!ArrayIsArray(val2) ||
|
||||
(val1.length !== val2.length && (mode !== kPartial || val1.length < val2.length))) {
|
||||
(val1.length !== val2.length && (mode !== kPartial || val1.length < val2.length)) ||
|
||||
hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -296,22 +302,29 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kIsArray, keys2);
|
||||
} else if (val1Tag === '[object Object]') {
|
||||
}
|
||||
|
||||
let val1Tag;
|
||||
if (val1[SymbolToStringTag] === undefined &&
|
||||
(val1Tag = ObjectPrototypeToString(val1)) === '[object Object]') {
|
||||
if (slowHasUnequalTag(val1Tag, val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kNoIterator);
|
||||
} else if (isDate(val1)) {
|
||||
if (!isDate(val2)) {
|
||||
} else if (isSet(val1)) {
|
||||
if (!isSet(val2) ||
|
||||
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size)) ||
|
||||
hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
const time1 = DatePrototypeGetTime(val1);
|
||||
const time2 = DatePrototypeGetTime(val2);
|
||||
// eslint-disable-next-line no-self-compare
|
||||
if (time1 !== time2 && (time1 === time1 || time2 === time2)) {
|
||||
return false;
|
||||
}
|
||||
} else if (isRegExp(val1)) {
|
||||
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2)) {
|
||||
return keyCheck(val1, val2, mode, memos, kIsSet);
|
||||
} else if (isMap(val1)) {
|
||||
if (!isMap(val2) ||
|
||||
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size)) ||
|
||||
hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kIsMap);
|
||||
} else if (isArrayBufferView(val1)) {
|
||||
if (TypedArrayPrototypeGetSymbolToStringTag(val1) !==
|
||||
TypedArrayPrototypeGetSymbolToStringTag(val2)) {
|
||||
@@ -339,20 +352,22 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kNoIterator, keys2);
|
||||
} else if (isSet(val1)) {
|
||||
if (!isSet(val2) ||
|
||||
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size))) {
|
||||
} else if (isDate(val1)) {
|
||||
if (!isDate(val2) || hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kIsSet);
|
||||
} else if (isMap(val1)) {
|
||||
if (!isMap(val2) ||
|
||||
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size))) {
|
||||
const time1 = DatePrototypeGetTime(val1);
|
||||
const time2 = DatePrototypeGetTime(val2);
|
||||
// eslint-disable-next-line no-self-compare
|
||||
if (time1 !== time2 && (time1 === time1 || time2 === time2)) {
|
||||
return false;
|
||||
}
|
||||
} else if (isRegExp(val1)) {
|
||||
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2) || hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
return keyCheck(val1, val2, mode, memos, kIsMap);
|
||||
} else if (isAnyArrayBuffer(val1)) {
|
||||
if (!isAnyArrayBuffer(val2)) {
|
||||
if (!isAnyArrayBuffer(val2) || hasUnequalTag(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
if (mode !== kPartial || val1.byteLength === val2.byteLength) {
|
||||
@@ -362,6 +377,15 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
} else if (!isPartialUint8Array(new Uint8Array(val1), new Uint8Array(val2))) {
|
||||
return false;
|
||||
}
|
||||
} else if (slowHasUnequalTag(val1Tag ?? ObjectPrototypeToString(val1), val1, val2) ||
|
||||
ArrayIsArray(val2) ||
|
||||
isArrayBufferView(val2) ||
|
||||
isSet(val2) ||
|
||||
isMap(val2) ||
|
||||
isDate(val2) ||
|
||||
isRegExp(val2) ||
|
||||
isAnyArrayBuffer(val2)) {
|
||||
return false;
|
||||
} else if (isError(val1)) {
|
||||
// Do not compare the stack as it might differ even though the error itself
|
||||
// is otherwise identical.
|
||||
@@ -380,17 +404,6 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
if (!isEqualBoxedPrimitive(val1, val2)) {
|
||||
return false;
|
||||
}
|
||||
} else if (ArrayIsArray(val2) ||
|
||||
isArrayBufferView(val2) ||
|
||||
isSet(val2) ||
|
||||
isMap(val2) ||
|
||||
isDate(val2) ||
|
||||
isRegExp(val2) ||
|
||||
isAnyArrayBuffer(val2) ||
|
||||
isBoxedPrimitive(val2) ||
|
||||
isNativeError(val2) ||
|
||||
val2 instanceof Error) {
|
||||
return false;
|
||||
} else if (isURL(val1)) {
|
||||
if (!isURL(val2) || val1.href !== val2.href) {
|
||||
return false;
|
||||
@@ -412,7 +425,12 @@ function objectComparisonStart(val1, val2, mode, memos) {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
} else if (isWeakMap(val1) || isWeakSet(val1) || isPromise(val1)) {
|
||||
} else if (isBoxedPrimitive(val2) ||
|
||||
isNativeError(val2) ||
|
||||
val2 instanceof Error ||
|
||||
isWeakMap(val1) ||
|
||||
isWeakSet(val1) ||
|
||||
isPromise(val1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -879,10 +897,8 @@ function partialSparseArrayEquiv(a, b, mode, memos, startA, startB) {
|
||||
let aPos = startA;
|
||||
const keysA = ObjectKeys(a);
|
||||
const keysB = ObjectKeys(b);
|
||||
const keysBLength = keysB.length;
|
||||
const keysALength = keysA.length;
|
||||
const lenA = keysALength - startA;
|
||||
const lenB = keysBLength - startB;
|
||||
const lenA = keysA.length - startA;
|
||||
const lenB = keysB.length - startB;
|
||||
if (lenA < lenB) {
|
||||
return false;
|
||||
}
|
||||
@@ -890,7 +906,7 @@ function partialSparseArrayEquiv(a, b, mode, memos, startA, startB) {
|
||||
const keyB = keysB[startB + i];
|
||||
while (!innerDeepEqual(a[keysA[aPos]], b[keyB], mode, memos)) {
|
||||
aPos++;
|
||||
if (aPos > keysALength - lenB + i) {
|
||||
if (aPos > keysA.length - lenB + i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -922,8 +938,6 @@ function partialArrayEquiv(a, b, mode, memos) {
|
||||
}
|
||||
|
||||
function sparseArrayEquiv(a, b, mode, memos, i) {
|
||||
// TODO(BridgeAR): Use internal method to only get index properties. The
|
||||
// same applies to the partial implementation.
|
||||
const keysA = ObjectKeys(a);
|
||||
const keysB = ObjectKeys(b);
|
||||
if (keysA.length !== keysB.length) {
|
||||
|
||||
Reference in New Issue
Block a user