@@ -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 ;
@@ -78,8 +78,8 @@ function areSimilarRegExps(a, b) {
78
78
}
79
79
80
80
function isPartialUint8Array ( a , b ) {
81
- const lenA = TypedArrayPrototypeGetByteLength ( a ) ;
82
- const lenB = TypedArrayPrototypeGetByteLength ( b ) ;
81
+ const lenA = getByteLength ( a ) ;
82
+ const lenB = getByteLength ( b ) ;
83
83
if ( lenA < lenB ) {
84
84
return false ;
85
85
}
@@ -107,10 +107,10 @@ function isPartialArrayBufferView(a, b) {
107
107
}
108
108
109
109
function areSimilarFloatArrays ( a , b ) {
110
- if ( a . byteLength !== b . byteLength ) {
110
+ const len = getByteLength ( a ) ;
111
+ if ( len !== getByteLength ( b ) ) {
111
112
return false ;
112
113
}
113
- const len = TypedArrayPrototypeGetByteLength ( a ) ;
114
114
for ( let offset = 0 ; offset < len ; offset ++ ) {
115
115
if ( a [ offset ] !== b [ offset ] ) {
116
116
return false ;
@@ -158,6 +158,12 @@ function isEqualBoxedPrimitive(val1, val2) {
158
158
assert . fail ( `Unknown boxed type ${ val1 } ` ) ;
159
159
}
160
160
161
+ function isEnumerableOrIdentical ( val1 , val2 , prop , mode , memos , method ) {
162
+ return hasEnumerable ( val2 , prop ) || // This is handled by Object.keys()
163
+ ( mode === kPartial && ( val2 [ prop ] === undefined || ( prop === 'message' && val2 [ prop ] === '' ) ) ) ||
164
+ innerDeepEqual ( val1 [ prop ] , val2 [ prop ] , mode , memos ) ;
165
+ }
166
+
161
167
// Notes: Type tags are historical [[Class]] properties that can be set by
162
168
// FunctionTemplate::SetClassName() in C++ or Symbol.toStringTag in JS
163
169
// and retrieved using Object.prototype.toString.call(obj) in JS
@@ -263,8 +269,7 @@ function innerDeepEqual(val1, val2, mode, memos) {
263
269
( val1 . size !== val2 . size && ( mode !== kPartial || val1 . size < val2 . size ) ) ) {
264
270
return false ;
265
271
}
266
- const result = keyCheck ( val1 , val2 , mode , memos , kIsSet ) ;
267
- return result ;
272
+ return keyCheck ( val1 , val2 , mode , memos , kIsSet ) ;
268
273
} else if ( isMap ( val1 ) ) {
269
274
if ( ! isMap ( val2 ) ||
270
275
( val1 . size !== val2 . size && ( mode !== kPartial || val1 . size < val2 . size ) ) ) {
@@ -285,26 +290,15 @@ function innerDeepEqual(val1, val2, mode, memos) {
285
290
} else if ( isError ( val1 ) ) {
286
291
// Do not compare the stack as it might differ even though the error itself
287
292
// is otherwise identical.
288
- if ( ! isError ( val2 ) ) {
293
+ if ( ! isError ( val2 ) ||
294
+ ! isEnumerableOrIdentical ( val1 , val2 , 'message' , mode , memos ) ||
295
+ ! isEnumerableOrIdentical ( val1 , val2 , 'name' , mode , memos ) ||
296
+ ! isEnumerableOrIdentical ( val1 , val2 , 'cause' , mode , memos ) ||
297
+ ! isEnumerableOrIdentical ( val1 , val2 , 'errors' , mode , memos ) ) {
289
298
return false ;
290
299
}
291
-
292
- const message1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'message' ) ;
293
- const name1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'name' ) ;
294
- // TODO(BridgeAR): Adjust cause and errors properties for partial mode.
295
- const cause1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'cause' ) ;
296
- const errors1Enumerable = ObjectPrototypePropertyIsEnumerable ( val1 , 'errors' ) ;
297
-
298
- if ( ( message1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'message' ) ||
299
- ( ! message1Enumerable && val1 . message !== val2 . message ) ) ||
300
- ( name1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'name' ) ||
301
- ( ! name1Enumerable && val1 . name !== val2 . name ) ) ||
302
- ( cause1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'cause' ) ||
303
- ( ! cause1Enumerable && (
304
- ObjectPrototypeHasOwnProperty ( val1 , 'cause' ) !== ObjectPrototypeHasOwnProperty ( val2 , 'cause' ) ||
305
- ! innerDeepEqual ( val1 . cause , val2 . cause , mode , memos ) ) ) ) ||
306
- ( errors1Enumerable !== ObjectPrototypePropertyIsEnumerable ( val2 , 'errors' ) ||
307
- ( ! errors1Enumerable && ! innerDeepEqual ( val1 . errors , val2 . errors , mode , memos ) ) ) ) {
300
+ const hasOwnVal2Cause = hasOwn ( val2 , 'cause' ) ;
301
+ if ( ( hasOwnVal2Cause !== hasOwn ( val1 , 'cause' ) && ( mode !== kPartial || hasOwnVal2Cause ) ) ) {
308
302
return false ;
309
303
}
310
304
} else if ( isBoxedPrimitive ( val1 ) ) {
@@ -348,10 +342,7 @@ function innerDeepEqual(val1, val2, mode, memos) {
348
342
}
349
343
350
344
function getEnumerables ( val , keys ) {
351
- return ArrayPrototypeFilter (
352
- keys ,
353
- ( k ) => ObjectPrototypePropertyIsEnumerable ( val , k ) ,
354
- ) ;
345
+ return ArrayPrototypeFilter ( keys , ( key ) => hasEnumerable ( val , key ) ) ;
355
346
}
356
347
357
348
function keyCheck ( val1 , val2 , mode , memos , iterationType , keys2 ) {
@@ -371,7 +362,7 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
371
362
// Cheap key test
372
363
if ( keys2 . length > 0 ) {
373
364
for ( const key of keys2 ) {
374
- if ( ! ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
365
+ if ( ! hasEnumerable ( val1 , key ) ) {
375
366
return false ;
376
367
}
377
368
}
@@ -380,11 +371,11 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
380
371
if ( ! isArrayLikeObject ) {
381
372
// The pair must have the same number of owned properties.
382
373
if ( mode === kPartial ) {
383
- const symbolKeys = ObjectGetOwnPropertySymbols ( val2 ) ;
374
+ const symbolKeys = getOwnSymbols ( val2 ) ;
384
375
if ( symbolKeys . length !== 0 ) {
385
376
for ( const key of symbolKeys ) {
386
- if ( ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
387
- if ( ! ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
377
+ if ( hasEnumerable ( val2 , key ) ) {
378
+ if ( ! hasEnumerable ( val1 , key ) ) {
388
379
return false ;
389
380
}
390
381
ArrayPrototypePush ( keys2 , key ) ;
@@ -396,27 +387,27 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
396
387
}
397
388
398
389
if ( mode === kStrict ) {
399
- const symbolKeysA = ObjectGetOwnPropertySymbols ( val1 ) ;
390
+ const symbolKeysA = getOwnSymbols ( val1 ) ;
400
391
if ( symbolKeysA . length !== 0 ) {
401
392
let count = 0 ;
402
393
for ( const key of symbolKeysA ) {
403
- if ( ObjectPrototypePropertyIsEnumerable ( val1 , key ) ) {
404
- if ( ! ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
394
+ if ( hasEnumerable ( val1 , key ) ) {
395
+ if ( ! hasEnumerable ( val2 , key ) ) {
405
396
return false ;
406
397
}
407
398
ArrayPrototypePush ( keys2 , key ) ;
408
399
count ++ ;
409
- } else if ( ObjectPrototypePropertyIsEnumerable ( val2 , key ) ) {
400
+ } else if ( hasEnumerable ( val2 , key ) ) {
410
401
return false ;
411
402
}
412
403
}
413
- const symbolKeysB = ObjectGetOwnPropertySymbols ( val2 ) ;
404
+ const symbolKeysB = getOwnSymbols ( val2 ) ;
414
405
if ( symbolKeysA . length !== symbolKeysB . length &&
415
406
getEnumerables ( val2 , symbolKeysB ) . length !== count ) {
416
407
return false ;
417
408
}
418
409
} else {
419
- const symbolKeysB = ObjectGetOwnPropertySymbols ( val2 ) ;
410
+ const symbolKeysB = getOwnSymbols ( val2 ) ;
420
411
if ( symbolKeysB . length !== 0 &&
421
412
getEnumerables ( val2 , symbolKeysB ) . length !== 0 ) {
422
413
return false ;
@@ -441,7 +432,6 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
441
432
c : undefined ,
442
433
d : undefined ,
443
434
deep : false ,
444
- deleteFailures : false ,
445
435
} ;
446
436
return objEquiv ( val1 , val2 , mode , keys2 , memos , iterationType ) ;
447
437
}
@@ -476,27 +466,21 @@ function keyCheck(val1, val2, mode, memos, iterationType, keys2) {
476
466
477
467
const areEq = objEquiv ( val1 , val2 , mode , keys2 , memos , iterationType ) ;
478
468
479
- if ( areEq || memos . deleteFailures ) {
480
- set . delete ( val1 ) ;
481
- set . delete ( val2 ) ;
482
- }
469
+ set . delete ( val1 ) ;
470
+ set . delete ( val2 ) ;
483
471
484
472
return areEq ;
485
473
}
486
474
487
475
function setHasEqualElement ( set , val1 , mode , memo ) {
488
- const { deleteFailures } = memo ;
489
- memo . deleteFailures = true ;
490
476
for ( const val2 of set ) {
491
477
if ( innerDeepEqual ( val1 , val2 , mode , memo ) ) {
492
478
// Remove the matching element to make sure we do not check that again.
493
479
set . delete ( val2 ) ;
494
- memo . deleteFailures = deleteFailures ;
495
480
return true ;
496
481
}
497
482
}
498
483
499
- memo . deleteFailures = deleteFailures ;
500
484
return false ;
501
485
}
502
486
@@ -557,6 +541,8 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
557
541
return false ;
558
542
}
559
543
}
544
+ /* c8 ignore next */
545
+ assert . fail ( 'Unreachable code' ) ;
560
546
}
561
547
562
548
function setObjectEquiv ( a , b , mode , set , memo ) {
@@ -623,18 +609,14 @@ function mapHasEqualEntry(set, map, key1, item1, mode, memo) {
623
609
// To be able to handle cases like:
624
610
// Map([[{}, 'a'], [{}, 'b']]) vs Map([[{}, 'b'], [{}, 'a']])
625
611
// ... we need to consider *all* matching keys, not just the first we find.
626
- const { deleteFailures } = memo ;
627
- memo . deleteFailures = true ;
628
612
for ( const key2 of set ) {
629
613
if ( innerDeepEqual ( key1 , key2 , mode , memo ) &&
630
614
innerDeepEqual ( item1 , map . get ( key2 ) , mode , memo ) ) {
631
615
set . delete ( key2 ) ;
632
- memo . deleteFailures = deleteFailures ;
633
616
return true ;
634
617
}
635
618
}
636
619
637
- memo . deleteFailures = deleteFailures ;
638
620
return false ;
639
621
}
640
622
@@ -652,6 +634,8 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
652
634
return false ;
653
635
}
654
636
}
637
+ /* c8 ignore next */
638
+ assert . fail ( 'Unreachable code' ) ;
655
639
}
656
640
657
641
function mapObjectEquivalence ( a , b , mode , set , memo ) {
@@ -747,11 +731,11 @@ function partialSparseArrayEquiv(a, b, mode, memos, startA, startB) {
747
731
function partialArrayEquiv ( a , b , mode , memos ) {
748
732
let aPos = 0 ;
749
733
for ( let i = 0 ; i < b . length ; i ++ ) {
750
- let isSparse = b [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( b , i ) ;
734
+ let isSparse = b [ i ] === undefined && ! hasOwn ( b , i ) ;
751
735
if ( isSparse ) {
752
736
return partialSparseArrayEquiv ( a , b , mode , memos , aPos , i ) ;
753
737
}
754
- while ( ! ( isSparse = a [ aPos ] === undefined && ! ObjectPrototypeHasOwnProperty ( a , aPos ) ) &&
738
+ while ( ! ( isSparse = a [ aPos ] === undefined && ! hasOwn ( a , aPos ) ) &&
755
739
! innerDeepEqual ( a [ aPos ] , b [ i ] , mode , memos ) ) {
756
740
aPos ++ ;
757
741
if ( aPos > a . length - b . length + i ) {
@@ -776,8 +760,7 @@ function sparseArrayEquiv(a, b, mode, memos, i) {
776
760
}
777
761
for ( ; i < keysA . length ; i ++ ) {
778
762
const key = keysA [ i ] ;
779
- if ( ! ObjectPrototypeHasOwnProperty ( b , key ) ||
780
- ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
763
+ if ( ! hasOwn ( b , key ) || ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
781
764
return false ;
782
765
}
783
766
}
@@ -802,8 +785,8 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
802
785
if ( ! innerDeepEqual ( a [ i ] , b [ i ] , mode , memos ) ) {
803
786
return false ;
804
787
}
805
- const isSparseA = a [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( a , i ) ;
806
- const isSparseB = b [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( b , i ) ;
788
+ const isSparseA = a [ i ] === undefined && ! hasOwn ( a , i ) ;
789
+ const isSparseB = b [ i ] === undefined && ! hasOwn ( b , i ) ;
807
790
if ( isSparseA !== isSparseB ) {
808
791
return false ;
809
792
}
0 commit comments