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