@@ -555,6 +555,35 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
555
555
}
556
556
}
557
557
558
+ function setObjectEquiv ( a , b , mode , set , memo ) {
559
+ if ( mode === kPartial ) {
560
+ return partialObjectSetEquiv ( a , b , mode , set , memo ) ;
561
+ }
562
+ // Fast path for objects only
563
+ if ( mode === kStrict && set . size === a . size ) {
564
+ for ( const val of a ) {
565
+ if ( ! setHasEqualElement ( set , val , mode , memo ) ) {
566
+ return false ;
567
+ }
568
+ }
569
+ return true ;
570
+ }
571
+
572
+ for ( const val of a ) {
573
+ // Primitive values have already been handled above.
574
+ if ( typeof val === 'object' ) {
575
+ if ( ! b . has ( val ) && ! setHasEqualElement ( set , val , mode , memo ) ) {
576
+ return false ;
577
+ }
578
+ } else if ( mode === kLoose &&
579
+ ! b . has ( val ) &&
580
+ ! setHasEqualElement ( set , val , mode , memo ) ) {
581
+ return false ;
582
+ }
583
+ }
584
+ return set . size === 0 ;
585
+ }
586
+
558
587
function setEquiv ( a , b , mode , memo ) {
559
588
// This is a lazily initiated Set of entries which have to be compared
560
589
// pairwise.
@@ -580,22 +609,7 @@ function setEquiv(a, b, mode, memo) {
580
609
}
581
610
582
611
if ( set !== null ) {
583
- if ( mode === kPartial ) {
584
- return partialObjectSetEquiv ( a , b , mode , set , memo ) ;
585
- }
586
- for ( const val of a ) {
587
- // Primitive values have already been handled above.
588
- if ( typeof val === 'object' && val !== null ) {
589
- if ( ! b . has ( val ) && ! setHasEqualElement ( set , val , mode , memo ) ) {
590
- return false ;
591
- }
592
- } else if ( mode === kLoose &&
593
- ! b . has ( val ) &&
594
- ! setHasEqualElement ( set , val , mode , memo ) ) {
595
- return false ;
596
- }
597
- }
598
- return set . size === 0 ;
612
+ return setObjectEquiv ( a , b , mode , set , memo ) ;
599
613
}
600
614
601
615
return true ;
@@ -636,6 +650,35 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
636
650
}
637
651
}
638
652
653
+ function mapObjectEquivalence ( a , b , mode , set , memo ) {
654
+ if ( mode === kPartial ) {
655
+ return partialObjectMapEquiv ( a , b , mode , set , memo ) ;
656
+ }
657
+ // Fast path for objects only
658
+ if ( mode === kStrict && set . size === a . size ) {
659
+ for ( const { 0 : key1 , 1 : item1 } of a ) {
660
+ if ( ! mapHasEqualEntry ( set , b , key1 , item1 , mode , memo ) ) {
661
+ return false ;
662
+ }
663
+ }
664
+ return true ;
665
+ }
666
+ for ( const { 0 : key1 , 1 : item1 } of a ) {
667
+ if ( typeof key1 === 'object' && key1 !== null ) {
668
+ if ( ! mapHasEqualEntry ( set , b , key1 , item1 , mode , memo ) )
669
+ return false ;
670
+ } else if ( set . size === 0 ) {
671
+ return true ;
672
+ } else if ( mode === kLoose &&
673
+ ( ! b . has ( key1 ) ||
674
+ ! innerDeepEqual ( item1 , b . get ( key1 ) , mode , memo ) ) &&
675
+ ! mapHasEqualEntry ( set , b , key1 , item1 , mode , memo ) ) {
676
+ return false ;
677
+ }
678
+ }
679
+ return set . size === 0 ;
680
+ }
681
+
639
682
function mapEquiv ( a , b , mode , memo ) {
640
683
let set = null ;
641
684
@@ -671,21 +714,7 @@ function mapEquiv(a, b, mode, memo) {
671
714
}
672
715
673
716
if ( set !== null ) {
674
- if ( mode === kPartial ) {
675
- return partialObjectMapEquiv ( a , b , mode , set , memo ) ;
676
- }
677
- for ( const { 0 : key1 , 1 : item1 } of a ) {
678
- if ( typeof key1 === 'object' && key1 !== null ) {
679
- if ( ! mapHasEqualEntry ( set , b , key1 , item1 , mode , memo ) )
680
- return false ;
681
- } else if ( mode === kLoose &&
682
- ( ! b . has ( key1 ) ||
683
- ! innerDeepEqual ( item1 , b . get ( key1 ) , mode , memo ) ) &&
684
- ! mapHasEqualEntry ( set , b , key1 , item1 , mode , memo ) ) {
685
- return false ;
686
- }
687
- }
688
- return set . size === 0 ;
717
+ return mapObjectEquivalence ( a , b , mode , set , memo ) ;
689
718
}
690
719
691
720
return true ;
@@ -733,6 +762,24 @@ function partialArrayEquiv(a, b, mode, memos) {
733
762
return true ;
734
763
}
735
764
765
+ function sparseArrayEquiv ( a , b , mode , memos , i ) {
766
+ // TODO(BridgeAR): Use internal method to only get index properties. The
767
+ // same applies to the partial implementation.
768
+ const keysA = ObjectKeys ( a ) ;
769
+ const keysB = ObjectKeys ( b ) ;
770
+ if ( keysA . length !== keysB . length ) {
771
+ return false ;
772
+ }
773
+ for ( ; i < keysA . length ; i ++ ) {
774
+ const key = keysA [ i ] ;
775
+ if ( ! ObjectPrototypeHasOwnProperty ( b , key ) ||
776
+ ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
777
+ return false ;
778
+ }
779
+ }
780
+ return true ;
781
+ }
782
+
736
783
function objEquiv ( a , b , mode , keys2 , memos , iterationType ) {
737
784
// The pair must have equivalent values for every corresponding key.
738
785
if ( keys2 . length > 0 ) {
@@ -751,23 +798,13 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
751
798
if ( ! innerDeepEqual ( a [ i ] , b [ i ] , mode , memos ) ) {
752
799
return false ;
753
800
}
754
- const isOwnProperty = ObjectPrototypeHasOwnProperty ( a , i ) ;
755
- if ( isOwnProperty !== ObjectPrototypeHasOwnProperty ( b , i ) ) {
801
+ const isSparseA = a [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( a , i ) ;
802
+ const isSparseB = b [ i ] === undefined && ! ObjectPrototypeHasOwnProperty ( b , i ) ;
803
+ if ( isSparseA !== isSparseB ) {
756
804
return false ;
757
805
}
758
- if ( ! isOwnProperty ) {
759
- // Array is sparse.
760
- // TODO(BridgeAR): Use internal method to only get index properties. The
761
- // same applies to the partial implementation.
762
- const keysA = ObjectKeys ( a ) ;
763
- for ( ; i < keysA . length ; i ++ ) {
764
- const key = keysA [ i ] ;
765
- if ( ! ObjectPrototypeHasOwnProperty ( b , key ) ||
766
- ! innerDeepEqual ( a [ key ] , b [ key ] , mode , memos ) ) {
767
- return false ;
768
- }
769
- }
770
- return keysA . length === ObjectKeys ( b ) . length ;
806
+ if ( isSparseA ) {
807
+ return sparseArrayEquiv ( a , b , mode , memos , i ) ;
771
808
}
772
809
}
773
810
} else if ( iterationType === kIsSet ) {
0 commit comments