@@ -783,100 +783,106 @@ function arrayRemove(array, value) {
783
783
</file>
784
784
</example>
785
785
*/
786
- function copy ( source , destination , stackSource , stackDest ) {
787
- if ( isWindow ( source ) || isScope ( source ) ) {
788
- throw ngMinErr ( 'cpws' ,
789
- "Can't copy! Making copies of Window or Scope instances is not supported." ) ;
790
- }
791
- if ( isTypedArray ( destination ) ) {
792
- throw ngMinErr ( 'cpta' ,
793
- "Can't copy! TypedArray destination cannot be mutated." ) ;
794
- }
795
-
796
- if ( ! destination ) {
797
- destination = source ;
798
- if ( isObject ( source ) ) {
799
- var index ;
800
- if ( stackSource && ( index = stackSource . indexOf ( source ) ) !== - 1 ) {
801
- return stackDest [ index ] ;
802
- }
803
-
804
- // TypedArray, Date and RegExp have specific copy functionality and must be
805
- // pushed onto the stack before returning.
806
- // Array and other objects create the base object and recurse to copy child
807
- // objects. The array/object will be pushed onto the stack when recursed.
808
- if ( isArray ( source ) ) {
809
- return copy ( source , [ ] , stackSource , stackDest ) ;
810
- } else if ( isTypedArray ( source ) ) {
811
- destination = new source . constructor ( source ) ;
812
- } else if ( isDate ( source ) ) {
813
- destination = new Date ( source . getTime ( ) ) ;
814
- } else if ( isRegExp ( source ) ) {
815
- destination = new RegExp ( source . source , source . toString ( ) . match ( / [ ^ \/ ] * $ / ) [ 0 ] ) ;
816
- destination . lastIndex = source . lastIndex ;
817
- } else {
818
- var emptyObject = Object . create ( getPrototypeOf ( source ) ) ;
819
- return copy ( source , emptyObject , stackSource , stackDest ) ;
820
- }
821
-
822
- if ( stackDest ) {
823
- stackSource . push ( source ) ;
824
- stackDest . push ( destination ) ;
825
- }
786
+ function copy ( source , destination ) {
787
+ if ( destination ) {
788
+ if ( isTypedArray ( destination ) ) {
789
+ throw ngMinErr ( 'cpta' , "Can't copy! TypedArray destination cannot be mutated." ) ;
826
790
}
827
- } else {
828
- if ( source === destination ) throw ngMinErr ( 'cpi' ,
829
- "Can't copy! Source and destination are identical." ) ;
830
-
831
- stackSource = stackSource || [ ] ;
832
- stackDest = stackDest || [ ] ;
833
-
834
- if ( isObject ( source ) ) {
835
- stackSource . push ( source ) ;
836
- stackDest . push ( destination ) ;
791
+ if ( source === destination ) {
792
+ throw ngMinErr ( 'cpi' , "Can't copy! Source and destination are identical." ) ;
837
793
}
838
794
839
- var result , key ;
840
- if ( isArray ( source ) ) {
795
+ // Empty the destination object
796
+ if ( isArray ( destination ) ) {
841
797
destination . length = 0 ;
842
- for ( var i = 0 ; i < source . length ; i ++ ) {
843
- destination . push ( copy ( source [ i ] , null , stackSource , stackDest ) ) ;
844
- }
845
798
} else {
846
- var h = destination . $$hashKey ;
847
- if ( isArray ( destination ) ) {
848
- destination . length = 0 ;
849
- } else {
850
- forEach ( destination , function ( value , key ) {
799
+ forEach ( destination , function ( value , key ) {
800
+ if ( key !== '$$hashKey' ) {
851
801
delete destination [ key ] ;
852
- } ) ;
853
- }
854
- if ( isBlankObject ( source ) ) {
855
- // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
856
- for ( key in source ) {
857
- destination [ key ] = copy ( source [ key ] , null , stackSource , stackDest ) ;
858
- }
859
- } else if ( source && typeof source . hasOwnProperty === 'function' ) {
860
- // Slow path, which must rely on hasOwnProperty
861
- for ( key in source ) {
862
- if ( source . hasOwnProperty ( key ) ) {
863
- destination [ key ] = copy ( source [ key ] , null , stackSource , stackDest ) ;
864
- }
865
- }
866
- } else {
867
- // Slowest path --- hasOwnProperty can't be called as a method
868
- for ( key in source ) {
869
- if ( hasOwnProperty . call ( source , key ) ) {
870
- destination [ key ] = copy ( source [ key ] , null , stackSource , stackDest ) ;
871
- }
872
802
}
803
+ } ) ;
804
+ }
805
+
806
+ return _copyRecurse ( source , destination , [ source ] , [ destination ] ) ;
807
+ }
808
+
809
+ return _copy ( source , [ ] , [ ] ) ;
810
+ }
811
+
812
+ function _copyRecurse ( source , destination , stackSource , stackDest ) {
813
+ var h = destination . $$hashKey ;
814
+ var result , key ;
815
+ if ( isArray ( source ) ) {
816
+ for ( var i = 0 , ii = source . length ; i < ii ; i ++ ) {
817
+ destination . push ( _copy ( source [ i ] , stackSource , stackDest ) ) ;
818
+ }
819
+ } else if ( isBlankObject ( source ) ) {
820
+ // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
821
+ for ( key in source ) {
822
+ destination [ key ] = _copy ( source [ key ] , stackSource , stackDest ) ;
823
+ }
824
+ } else if ( source && typeof source . hasOwnProperty === 'function' ) {
825
+ // Slow path, which must rely on hasOwnProperty
826
+ for ( key in source ) {
827
+ if ( source . hasOwnProperty ( key ) ) {
828
+ destination [ key ] = _copy ( source [ key ] , stackSource , stackDest ) ;
829
+ }
830
+ }
831
+ } else {
832
+ // Slowest path --- hasOwnProperty can't be called as a method
833
+ for ( key in source ) {
834
+ if ( hasOwnProperty . call ( source , key ) ) {
835
+ destination [ key ] = _copy ( source [ key ] , stackSource , stackDest ) ;
873
836
}
874
- setHashKey ( destination , h ) ;
875
837
}
876
838
}
839
+ setHashKey ( destination , h ) ;
877
840
return destination ;
878
841
}
879
842
843
+ function _copy ( source , stackSource , stackDest ) {
844
+ // Simple values
845
+ if ( ! isObject ( source ) ) {
846
+ return source ;
847
+ }
848
+
849
+ // Already copied values
850
+ var index = stackSource . indexOf ( source ) ;
851
+ if ( index !== - 1 ) {
852
+ return stackDest [ index ] ;
853
+ }
854
+
855
+ if ( isWindow ( source ) || isScope ( source ) ) {
856
+ throw ngMinErr ( 'cpws' ,
857
+ "Can't copy! Making copies of Window or Scope instances is not supported." ) ;
858
+ }
859
+
860
+ var needsRecurse = false ;
861
+ var destination ;
862
+
863
+ if ( isArray ( source ) ) {
864
+ destination = [ ] ;
865
+ needsRecurse = true ;
866
+ } else if ( isTypedArray ( source ) ) {
867
+ destination = new source . constructor ( source ) ;
868
+ } else if ( isDate ( source ) ) {
869
+ destination = new Date ( source . getTime ( ) ) ;
870
+ } else if ( isRegExp ( source ) ) {
871
+ destination = new RegExp ( source . source , source . toString ( ) . match ( / [ ^ \/ ] * $ / ) [ 0 ] ) ;
872
+ destination . lastIndex = source . lastIndex ;
873
+ } else {
874
+ destination = Object . create ( getPrototypeOf ( source ) ) ;
875
+ needsRecurse = true ;
876
+ }
877
+
878
+ stackSource . push ( source ) ;
879
+ stackDest . push ( destination ) ;
880
+
881
+ return needsRecurse
882
+ ? _copyRecurse ( source , destination , stackSource , stackDest )
883
+ : destination ;
884
+ }
885
+
880
886
/**
881
887
* Creates a shallow copy of an object, an array or a primitive.
882
888
*
0 commit comments