@@ -555,6 +555,35 @@ function partialObjectSetEquiv(a, b, mode, set, memo) {
555555 }
556556}
557557
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+
558587function setEquiv ( a , b , mode , memo ) {
559588 // This is a lazily initiated Set of entries which have to be compared
560589 // pairwise.
@@ -580,22 +609,7 @@ function setEquiv(a, b, mode, memo) {
580609 }
581610
582611 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 ) ;
599613 }
600614
601615 return true ;
@@ -636,6 +650,35 @@ function partialObjectMapEquiv(a, b, mode, set, memo) {
636650 }
637651}
638652
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+
639682function mapEquiv ( a , b , mode , memo ) {
640683 let set = null ;
641684
@@ -671,21 +714,7 @@ function mapEquiv(a, b, mode, memo) {
671714 }
672715
673716 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 ) ;
689718 }
690719
691720 return true ;
@@ -733,6 +762,24 @@ function partialArrayEquiv(a, b, mode, memos) {
733762 return true ;
734763}
735764
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+
736783function objEquiv ( a , b , mode , keys2 , memos , iterationType ) {
737784 // The pair must have equivalent values for every corresponding key.
738785 if ( keys2 . length > 0 ) {
@@ -751,23 +798,13 @@ function objEquiv(a, b, mode, keys2, memos, iterationType) {
751798 if ( ! innerDeepEqual ( a [ i ] , b [ i ] , mode , memos ) ) {
752799 return false ;
753800 }
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 ) {
756804 return false ;
757805 }
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 ) ;
771808 }
772809 }
773810 } else if ( iterationType === kIsSet ) {
0 commit comments