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