Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 148373c

Browse filesBrowse files
BridgeARaduh95
authored andcommitted
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: #61176 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
1 parent 5f8ecf3 commit 148373c
Copy full SHA for 148373c

1 file changed

+61-47Lines changed: 61 additions & 47 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎lib/internal/util/comparisons.js‎

Copy file name to clipboardExpand all lines: lib/internal/util/comparisons.js
+61-47Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const {
4141
StringPrototypeValueOf,
4242
Symbol,
4343
SymbolPrototypeValueOf,
44+
SymbolToStringTag,
4445
TypedArrayPrototypeGetByteLength: getByteLength,
4546
TypedArrayPrototypeGetSymbolToStringTag,
4647
Uint16Array,
@@ -114,6 +115,7 @@ const {
114115
isFloat64Array,
115116
isKeyObject,
116117
isCryptoKey,
118+
isPromise,
117119
isWeakMap,
118120
isWeakSet,
119121
} = types;
@@ -263,6 +265,17 @@ function innerDeepEqual(val1, val2, mode, memos) {
263265
return objectComparisonStart(val1, val2, mode, memos);
264266
}
265267

268+
function hasUnequalTag(val1, val2) {
269+
return val1[SymbolToStringTag] !== val2[SymbolToStringTag];
270+
}
271+
272+
function slowHasUnequalTag(val1Tag, val1, val2) {
273+
if (val1[SymbolToStringTag] !== undefined && val2[SymbolToStringTag] !== undefined) {
274+
return val1[SymbolToStringTag] !== val2[SymbolToStringTag];
275+
}
276+
return val1Tag !== ObjectPrototypeToString(val2);
277+
}
278+
266279
function objectComparisonStart(val1, val2, mode, memos) {
267280
if (mode === kStrict) {
268281
if (wellKnownConstructors.has(val1.constructor) ||
@@ -275,16 +288,10 @@ function objectComparisonStart(val1, val2, mode, memos) {
275288
}
276289
}
277290

278-
const val1Tag = ObjectPrototypeToString(val1);
279-
const val2Tag = ObjectPrototypeToString(val2);
280-
281-
if (val1Tag !== val2Tag) {
282-
return false;
283-
}
284-
285291
if (ArrayIsArray(val1)) {
286292
if (!ArrayIsArray(val2) ||
287-
(val1.length !== val2.length && (mode !== kPartial || val1.length < val2.length))) {
293+
(val1.length !== val2.length && (mode !== kPartial || val1.length < val2.length)) ||
294+
hasUnequalTag(val1, val2)) {
288295
return false;
289296
}
290297

@@ -295,23 +302,29 @@ function objectComparisonStart(val1, val2, mode, memos) {
295302
return false;
296303
}
297304
return keyCheck(val1, val2, mode, memos, kIsArray, keys2);
298-
} else if (val1Tag === '[object Object]') {
299-
return keyCheck(val1, val2, mode, memos, kNoIterator);
300-
} else if (isDate(val1)) {
301-
if (!isDate(val2) ||
302-
DatePrototypeGetTime(val1) !== DatePrototypeGetTime(val2)) {
305+
}
306+
307+
let val1Tag;
308+
if (val1[SymbolToStringTag] === undefined &&
309+
(val1Tag = ObjectPrototypeToString(val1)) === '[object Object]') {
310+
if (slowHasUnequalTag(val1Tag, val1, val2)) {
303311
return false;
304312
}
305-
const time1 = DatePrototypeGetTime(val1);
306-
const time2 = DatePrototypeGetTime(val2);
307-
// eslint-disable-next-line no-self-compare
308-
if (time1 !== time2 && (time1 === time1 || time2 === time2)) {
313+
return keyCheck(val1, val2, mode, memos, kNoIterator);
314+
} else if (isSet(val1)) {
315+
if (!isSet(val2) ||
316+
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size)) ||
317+
hasUnequalTag(val1, val2)) {
309318
return false;
310319
}
311-
} else if (isRegExp(val1)) {
312-
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2)) {
320+
return keyCheck(val1, val2, mode, memos, kIsSet);
321+
} else if (isMap(val1)) {
322+
if (!isMap(val2) ||
323+
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size)) ||
324+
hasUnequalTag(val1, val2)) {
313325
return false;
314326
}
327+
return keyCheck(val1, val2, mode, memos, kIsMap);
315328
} else if (isArrayBufferView(val1)) {
316329
if (TypedArrayPrototypeGetSymbolToStringTag(val1) !==
317330
TypedArrayPrototypeGetSymbolToStringTag(val2)) {
@@ -339,20 +352,22 @@ function objectComparisonStart(val1, val2, mode, memos) {
339352
return false;
340353
}
341354
return keyCheck(val1, val2, mode, memos, kNoIterator, keys2);
342-
} else if (isSet(val1)) {
343-
if (!isSet(val2) ||
344-
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size))) {
355+
} else if (isDate(val1)) {
356+
if (!isDate(val2) || hasUnequalTag(val1, val2)) {
345357
return false;
346358
}
347-
return keyCheck(val1, val2, mode, memos, kIsSet);
348-
} else if (isMap(val1)) {
349-
if (!isMap(val2) ||
350-
(val1.size !== val2.size && (mode !== kPartial || val1.size < val2.size))) {
359+
const time1 = DatePrototypeGetTime(val1);
360+
const time2 = DatePrototypeGetTime(val2);
361+
// eslint-disable-next-line no-self-compare
362+
if (time1 !== time2 && (time1 === time1 || time2 === time2)) {
363+
return false;
364+
}
365+
} else if (isRegExp(val1)) {
366+
if (!isRegExp(val2) || !areSimilarRegExps(val1, val2) || hasUnequalTag(val1, val2)) {
351367
return false;
352368
}
353-
return keyCheck(val1, val2, mode, memos, kIsMap);
354369
} else if (isAnyArrayBuffer(val1)) {
355-
if (!isAnyArrayBuffer(val2)) {
370+
if (!isAnyArrayBuffer(val2) || hasUnequalTag(val1, val2)) {
356371
return false;
357372
}
358373
if (mode !== kPartial || val1.byteLength === val2.byteLength) {
@@ -362,6 +377,15 @@ function objectComparisonStart(val1, val2, mode, memos) {
362377
} else if (!isPartialUint8Array(new Uint8Array(val1), new Uint8Array(val2))) {
363378
return false;
364379
}
380+
} else if (slowHasUnequalTag(val1Tag ?? ObjectPrototypeToString(val1), val1, val2) ||
381+
ArrayIsArray(val2) ||
382+
isArrayBufferView(val2) ||
383+
isSet(val2) ||
384+
isMap(val2) ||
385+
isDate(val2) ||
386+
isRegExp(val2) ||
387+
isAnyArrayBuffer(val2)) {
388+
return false;
365389
} else if (isError(val1)) {
366390
// Do not compare the stack as it might differ even though the error itself
367391
// is otherwise identical.
@@ -380,17 +404,6 @@ function objectComparisonStart(val1, val2, mode, memos) {
380404
if (!isEqualBoxedPrimitive(val1, val2)) {
381405
return false;
382406
}
383-
} else if (ArrayIsArray(val2) ||
384-
isArrayBufferView(val2) ||
385-
isSet(val2) ||
386-
isMap(val2) ||
387-
isDate(val2) ||
388-
isRegExp(val2) ||
389-
isAnyArrayBuffer(val2) ||
390-
isBoxedPrimitive(val2) ||
391-
isNativeError(val2) ||
392-
val2 instanceof Error) {
393-
return false;
394407
} else if (isURL(val1)) {
395408
if (!isURL(val2) || val1.href !== val2.href) {
396409
return false;
@@ -412,7 +425,12 @@ function objectComparisonStart(val1, val2, mode, memos) {
412425
) {
413426
return false;
414427
}
415-
} else if (isWeakMap(val1) || isWeakSet(val1)) {
428+
} else if (isBoxedPrimitive(val2) ||
429+
isNativeError(val2) ||
430+
val2 instanceof Error ||
431+
isWeakMap(val1) ||
432+
isWeakSet(val1) ||
433+
isPromise(val1)) {
416434
return false;
417435
}
418436

@@ -884,18 +902,16 @@ function partialSparseArrayEquiv(a, b, mode, memos, startA, startB) {
884902
let aPos = startA;
885903
const keysA = ObjectKeys(a);
886904
const keysB = ObjectKeys(b);
887-
const keysBLength = keysB.length;
888-
const keysALength = keysA.length;
889-
const lenA = keysALength - startA;
890-
const lenB = keysBLength - startB;
905+
const lenA = keysA.length - startA;
906+
const lenB = keysB.length - startB;
891907
if (lenA < lenB) {
892908
return false;
893909
}
894910
for (let i = 0; i < lenB; i++) {
895911
const keyB = keysB[startB + i];
896912
while (!innerDeepEqual(a[keysA[aPos]], b[keyB], mode, memos)) {
897913
aPos++;
898-
if (aPos > keysALength - lenB + i) {
914+
if (aPos > keysA.length - lenB + i) {
899915
return false;
900916
}
901917
}
@@ -927,8 +943,6 @@ function partialArrayEquiv(a, b, mode, memos) {
927943
}
928944

929945
function sparseArrayEquiv(a, b, mode, memos, i) {
930-
// TODO(BridgeAR): Use internal method to only get index properties. The
931-
// same applies to the partial implementation.
932946
const keysA = ObjectKeys(a);
933947
const keysB = ObjectKeys(b);
934948
if (keysA.length !== keysB.length) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.