@@ -10,17 +10,17 @@ const {
10
10
Error,
11
11
NumberIsNaN,
12
12
NumberPrototypeValueOf,
13
- ObjectGetOwnPropertySymbols,
13
+ ObjectGetOwnPropertySymbols : getOwnSymbols ,
14
14
ObjectGetPrototypeOf,
15
15
ObjectIs,
16
16
ObjectKeys,
17
- ObjectPrototypeHasOwnProperty,
18
- ObjectPrototypePropertyIsEnumerable,
17
+ ObjectPrototypeHasOwnProperty : hasOwn ,
18
+ ObjectPrototypePropertyIsEnumerable : hasEnumerable ,
19
19
ObjectPrototypeToString,
20
20
SafeSet,
21
21
StringPrototypeValueOf,
22
22
SymbolPrototypeValueOf,
23
- TypedArrayPrototypeGetByteLength,
23
+ TypedArrayPrototypeGetByteLength : getByteLength ,
24
24
TypedArrayPrototypeGetSymbolToStringTag,
25
25
Uint8Array,
26
26
} = primordials ;
@@ -76,8 +76,8 @@ function areSimilarRegExps(a, b) {
76
76
}
77
77
78
78
function isPartialUint8Array ( a , b ) {
79
- const lenA = TypedArrayPrototypeGetByteLength ( a ) ;
80
- const lenB = TypedArrayPrototypeGetByteLength ( b ) ;
79
+ const lenA = getByteLength ( a ) ;
80
+ const lenB = getByteLength ( b ) ;
81
81
if ( lenA < lenB ) {
82
82
return false ;
83
83
}
@@ -105,10 +105,10 @@ function isPartialArrayBufferView(a, b) {
105
105
}
106
106
107
107
function areSimilarFloatArrays ( a , b ) {
108
- if ( a . byteLength !== b . byteLength ) {
108
+ const len = getByteLength ( a ) ;
109
+ if ( len !== getByteLength ( b ) ) {
109
110
return false ;
110
111
}
111
- const len = TypedArrayPrototypeGetByteLength ( a ) ;
112
112
for ( let offset = 0 ; offset < len ; offset ++ ) {
113
113
if ( a [ offset ] !== b [ offset ] ) {
114
114
return false ;
@@ -156,6 +156,12 @@ function isEqualBoxedPrimitive(val1, val2) {
156
156
assert . fail ( `Unknown boxed type ${ val1 } ` ) ;
157
157
}
158
158
159
+ function isEnumerableOrIdentical ( val1 , val2 , prop , mode , memos , method ) {
160
+ return hasEnumerable ( val2 , prop ) || // This is handled by Object.keys()
161
+ ( mode === kPartial && ( val2 [ prop ] === undefined || ( prop === 'message' && val2 [ prop ] === '' ) ) ) ||
162
+ innerDeepEqual ( val1 [ prop ] , val2 [ prop ] , mode , memos ) ;
163
+ }
164
+
159
165
// Notes: Type tags are historical [[Class]] properties that can be set by
160
166
// FunctionTemplate::SetClassName() in C++ or Symbol.toStringTag in JS
161
167
// and retrieved using Object.prototype.toString.call(obj) in JS
@@ -261,8 +267,7 @@ function innerDeepEqual(val1, val2, mode, memos) {
261
267
( val1 . size !== val2 . size && ( mode !== kPartial || val1 . size < val2 . size ) ) ) {
262
268
return false ;
263
269
}
264
- const result = keyCheck ( val1 , val2 , mode , memos , kIsSet ) ;
265
- return result ;
270
+ return keyCheck ( val1 , val2 , mode , memos , kIsSet ) ;
266
271
} else if ( isMap ( val1 ) ) {
267
272
if ( ! isMap ( val2 ) ||
268
273
( val1 . size !== val2 . size && ( mode !== kPartial || val1 . size < val2 . size ) ) ) {
@@ -283,26 +288,15 @@ function innerDeepEqual(val1, val2, mode, memos) {
283
288
} else if ( isError ( val1 ) ) {
284
289
// Do not compare the stack as it might differ even though the error itself
285
290
// is otherwise identical.
286
- if ( ! isError ( val2 ) ) {
291
+ if ( ! isError ( val2 ) ||
292
+ ! isEnumerableOrIdentical ( val1 , val2 , 'message' , mode , memos ) ||
293
+ ! isEnumerableOrIdentical ( val1 , val2 , 'name' , mode , memos ) ||
294
+ ! isEnumerableOrIdentical ( val1 , val2 , 'cause' , mode , memos ) ||
295
+ ! isEnumerableOrIdentical ( val1 , val2 , 'errors' , mode , memos ) ) {
287
296
return false ;
288
297
}
289
-
290
- const message1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'message' ) ;
291
- const name1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'name' ) ;
292
- // TODO(BridgeAR): Adjust cause and errors properties for partial mode.
293
- const cause1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'cause' ) ;
294
- const errors1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'errors' ) ;
295
-
296
- if ( ( message1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'message' ) ||
297
- ( ! message1Enumerable && val1 . message !== val2 . message ) ) ||
298
- ( name1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'name' ) ||
299
- ( ! name1Enumerable && val1 . name !== val2 . name ) ) ||
300
- ( cause1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'cause' ) ||
301
- ( ! cause1Enumerable && (
302
- ObjectPrototypeHasOwnProperty ( val1 , 'cause' ) !== ObjectPrototypeHasOwnProperty ( val2 , 'cause' ) ||
303
- ! innerDeepEqual ( val1 . cause , val2 . cause , mode , memos ) ) ) ) ||
304
- ( errors1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'errors' ) ||
305
- ( ! errors1Enumerable && ! innerDeepEqual ( val1 . errors , val2 . errors , mode , memos ) ) ) ) {
298
+ const hasOwnVal2Cause = hasOwn ( val2 , 'cause' ) ;
299
+ if ( ( hasOwnVal2Cause !== hasOwn ( val1 , 'cause' ) && ( mode !== kPartial || hasOwnVal2Cause ) ) ) {
306
300
return false ;
307
301
}
308
302
} else if ( isBoxedPrimitive ( val1 ) ) {
@@ -344,10 +338,7 @@ function innerDeepEqual(val1, val2, mode, memos) {
344
338
}
345
339
346
340
function getEnumerables ( val , keys ) {
347
- return ArrayPrototypeFilter (
348
- keys ,
349
- ( k ) => ObjectPrototypePropertyIsEnumerable ( val , k ) ,
350
- ) ;
341
+ return ArrayPrototypeFilter ( keys , ( key ) => hasEnumerable ( val , key ) ) ;
351
342
}
352
343
353
344
function keyCheck ( val1 , val2 , mode , memos , iterationType , keys2 ) {
@@ -367,7 +358,7 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
367
358
// Cheap key test
368
359
if ( keys2 . length > 0 ) {
369
360
for ( const key of keys2 ) {
370
- if ( ! ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
361
+ if ( ! hasEnumerable ( val1 , key ) ) {
371
362
return false ;
372
363
}
373
364
}
@@ -376,11 +367,11 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
376
367
if ( ! isArrayLikeObject ) {
377
368
// The pair must have the same number of owned properties.
378
369
if ( mode === kPartial ) {
379
- const symbolKeys = ObjectGetOwnPropertySymbols ( val2 ) ;
370
+ const symbolKeys = getOwnSymbols ( val2 ) ;
380
371
if ( symbolKeys . length !== 0 ) {
381
372
for ( const key of symbolKeys ) {
382
- if ( ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
383
- if ( ! ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
373
+ if ( hasEnumerable ( val2 , key ) ) {
374
+ if ( ! hasEnumerable ( val1 , key ) ) {
384
375
return false ;
385
376
}
386
377
ArrayPrototypePush ( keys2 , key ) ;
@@ -392,27 +383,27 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
392
383
}
393
384
394
385
if ( mode === kStrict ) {
395
- const symbolKeysA = ObjectGetOwnPropertySymbols ( val1 ) ;
386
+ const symbolKeysA = getOwnSymbols ( val1 ) ;
396
387
if ( symbolKeysA . length !== 0 ) {
397
388
let count = 0 ;
398
389
for ( const key of symbolKeysA ) {
399
- if ( ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
400
- if ( ! ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
390
+ if ( hasEnumerable ( val1 , key ) ) {
391
+ if ( ! hasEnumerable ( val2 , key ) ) {
401
392
return false ;
402
393
}
403
394
ArrayPrototypePush ( keys2 , key ) ;
404
395
count ++ ;
405
- } else if ( ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
396
+ } else if ( hasEnumerable ( val2 , key ) ) {
406
397
return false ;
407
398
}
408
399
}
409
- const symbolKeysB = ObjectGetOwnPropertySymbols ( val2 ) ;
400
+ const symbolKeysB = getOwnSymbols ( val2 ) ;
410
401
if ( symbolKeysA . length !== symbolKeysB . length &&
411
402
getEnumerables ( val2 , symbolKeysB ) . length !== count ) {
412
403
return false ;
413
404
}
414
405
} else {
415
- const symbolKeysB = ObjectGetOwnPropertySymbols ( val2 ) ;
406
+ const symbolKeysB = getOwnSymbols ( val2 ) ;
416
407
if ( symbolKeysB . length !== 0 &&
417
408
getEnumerables ( val2 , symbolKeysB ) . length !== 0 ) {
418
409
return false ;
@@ -437,7 +428,6 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
437
428
c : undefined ,
438
429
d : undefined ,
439
430
deep : false ,
440
- deleteFailures : false ,
441
431
} ;
442
432
return objEquiv ( val1 , val2 , mode , keys2 , memos , iterationType ) ;
443
433
}
@@ -472,27 +462,21 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
472
462
473
463
const areEq = objEquiv ( val1 , val2 , mode , keys2 , memos , iterationType ) ;
474
464
475
- if ( areEq || memos . deleteFailures ) {
476
- set . delete ( val1 ) ;
477
- set . delete ( val2 ) ;
478
- }
465
+ set . delete ( val1 ) ;
466
+ set . delete ( val2 ) ;
479
467
480
468
return areEq ;
481
469
}
482
470
483
471
function setHasEqualElement ( set , val1 , mode , memo ) {
484
- const { deleteFailures } = memo ;
485
- memo . deleteFailures = true ;
486
472
for ( const val2 of set ) {
487
473
if ( innerDeepEqual ( val1 , val2 , mode , memo ) ) {
488
474
// Remove the matching element to make sure we do not check that again.
489
475
set . delete ( val2 ) ;
490
- memo . deleteFailures = deleteFailures ;
491
476
return true ;
492
477
}
493
478
}
494
479
495
- memo . deleteFailures = deleteFailures ;
496
480
return false ;
497
481
}
498
482
@@ -553,6 +537,8 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
553
537
return false ;
554
538
}
555
539
}
540
+ /* c8 ignore next */
541
+ assert . fail ( 'Unreachable code' ) ;
556
542
}
557
543
558
544
function setObjectEquiv ( a , b , mode , set , memo ) {
@@ -619,18 +605,14 @@ function mapHasEqualEntry(set, map, key1, item1, mode, memo) {
619
605
// To be able to handle cases like:
620
606
// Map([[{}, 'a'], [{}, 'b']]) vs Map([[{}, 'b'], [{}, 'a']])
621
607
// ... we need to consider *all* matching keys, not just the first we find.
622
- const { deleteFailures } = memo ;
623
- memo . deleteFailures = true ;
624
608
for ( const key2 of set ) {
625
609
if ( innerDeepEqual ( key1 , key2 , mode , memo ) &&
626
610
innerDeepEqual ( item1 , map . get ( key2 ) , mode , memo ) ) {
627
611
set . delete ( key2 ) ;
628
- memo . deleteFailures = deleteFailures ;
629
612
return true ;
630
613
}
631
614
}
632
615
633
- memo . deleteFailures = deleteFailures ;
634
616
return false ;
635
617
}
636
618
@@ -648,6 +630,8 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
648
630
return false ;
649
631
}
650
632
}
633
+ /* c8 ignore next */
634
+ assert . fail ( 'Unreachable code' ) ;
651
635
}
652
636
653
637
function mapObjectEquivalence ( a , b , mode , set , memo ) {
@@ -743,11 +727,11 @@ function partialSparseArrayEquiv(a, b, mode, memos, startA, startB) {
743
727
function partialArrayEquiv ( a , b , mode , memos ) {
744
728
let aPos = 0 ;
745
729
for ( let i = 0 ; i < b . length ; i ++ ) {
746
- let isSparse = b [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( b , i ) ;
730
+ let isSparse = b [ i ] === undefined && ! hasOwn ( b , i ) ;
747
731
if ( isSparse ) {
748
732
return partialSparseArrayEquiv ( a , b , mode , memos , aPos , i ) ;
749
733
}
750
- while ( ! ( isSparse = a [ aPos ] === undefined && ! ObjectPrototypeHasOwnProperty ( a , aPos ) ) &&
734
+ while ( ! ( isSparse = a [ aPos ] === undefined && ! hasOwn ( a , aPos ) ) &&
751
735
! innerDeepEqual ( a [ aPos ] , b [ i ] , mode , memos ) ) {
752
736
aPos ++ ;
753
737
if ( aPos > a . length - b . length + i ) {
@@ -772,8 +756,7 @@ function sparseArrayEquiv(a, b, mode, memos, i) {
772
756
}
773
757
for ( ; i < keysA . length ; i ++ ) {
774
758
const key = keysA [ i ] ;
775
- if ( ! ObjectPrototypeHasOwnProperty ( b , key ) ||
776
- ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
759
+ if ( ! hasOwn ( b , key ) || ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
777
760
return false ;
778
761
}
779
762
}
@@ -798,8 +781,8 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
798
781
if ( ! innerDeepEqual ( a [ i ] , b [ i ] , mode , memos ) ) {
799
782
return false ;
800
783
}
801
- const isSparseA = a [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( a , i ) ;
802
- const isSparseB = b [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( b , i ) ;
784
+ const isSparseA = a [ i ] === undefined && ! hasOwn ( a , i ) ;
785
+ const isSparseB = b [ i ] === undefined && ! hasOwn ( b , i ) ;
803
786
if ( isSparseA !== isSparseB ) {
804
787
return false ;
805
788
}
0 commit comments