@@ -709,77 +709,82 @@ function arrayRemove(array, value) {
709
709
</example>
710
710
*/
711
711
function copy ( source , destination , stackSource , stackDest ) {
712
- if ( isWindow ( source ) || isScope ( source ) ) {
713
- throw ngMinErr ( 'cpws' ,
714
- "Can't copy! Making copies of Window or Scope instances is not supported." ) ;
715
- }
716
- if ( isTypedArray ( destination ) ) {
717
- throw ngMinErr ( 'cpta' ,
718
- "Can't copy! TypedArray destination cannot be mutated." ) ;
719
- }
720
-
721
- if ( ! destination ) {
722
- destination = source ;
723
- if ( isObject ( source ) ) {
724
- var index ;
725
- if ( stackSource && ( index = stackSource . indexOf ( source ) ) !== - 1 ) {
726
- return stackDest [ index ] ;
727
- }
728
-
729
- if ( isArray ( source ) ) {
730
- return copy ( source , [ ] , stackSource , stackDest ) ;
731
- } else if ( isTypedArray ( source ) ) {
732
- destination = new source . constructor ( source ) ;
733
- } else if ( isDate ( source ) ) {
734
- destination = new Date ( source . getTime ( ) ) ;
735
- } else if ( isRegExp ( source ) ) {
736
- destination = new RegExp ( source . source , source . toString ( ) . match ( / [ ^ \/ ] * $ / ) [ 0 ] ) ;
737
- destination . lastIndex = source . lastIndex ;
738
- } else {
739
- var emptyObject = Object . create ( Object . getPrototypeOf ( source ) ) ;
740
- return copy ( source , emptyObject , stackSource , stackDest ) ;
741
- }
712
+ // Validate and clear any passed destination
713
+ var destinationHashKey ;
714
+ if ( destination ) {
715
+ if ( source === destination ) {
716
+ throw ngMinErr ( 'cpi' , "Can't copy! Source and destination are identical." ) ;
717
+ }
718
+ if ( isTypedArray ( destination ) ) {
719
+ throw ngMinErr ( 'cpta' , "Can't copy! TypedArray destination cannot be mutated." ) ;
720
+ }
742
721
743
- if ( stackDest ) {
744
- stackSource . push ( source ) ;
745
- stackDest . push ( destination ) ;
722
+ if ( isArray ( destination ) ) {
723
+ destination . length = 0 ;
724
+ } else if ( isObject ( destination ) ) {
725
+ destinationHashKey = destination . $$hashKey ;
726
+ for ( var dkey in destination ) {
727
+ if ( destination . hasOwnProperty ( dkey ) ) {
728
+ delete destination [ dkey ] ;
729
+ }
746
730
}
747
731
}
748
- } else {
749
- if ( source === destination ) throw ngMinErr ( 'cpi' ,
750
- "Can't copy! Source and destination are identical." ) ;
751
-
752
- stackSource = stackSource || [ ] ;
753
- stackDest = stackDest || [ ] ;
732
+ }
754
733
755
- if ( isObject ( source ) ) {
756
- stackSource . push ( source ) ;
757
- stackDest . push ( destination ) ;
734
+ // Copy and recurse objects
735
+ if ( isObject ( source ) ) {
736
+ var index ;
737
+ if ( stackSource && ( index = stackSource . indexOf ( source ) ) !== - 1 ) {
738
+ return stackDest [ index ] ;
758
739
}
759
740
741
+ var traverse = false ;
760
742
if ( isArray ( source ) ) {
761
- destination . length = 0 ;
762
- for ( var i = 0 ; i < source . length ; i ++ ) {
763
- destination . push ( copy ( source [ i ] , null , stackSource , stackDest ) ) ;
764
- }
743
+ destination = destination || new Array ( source . length ) ;
744
+ traverse = true ;
745
+ } else if ( ! destination && isTypedArray ( source ) ) {
746
+ destination = new source . constructor ( source ) ;
747
+ } else if ( ! destination && isDate ( source ) ) {
748
+ destination = new Date ( source . getTime ( ) ) ;
749
+ } else if ( ! destination && isRegExp ( source ) ) {
750
+ destination = new RegExp ( source . source , source . toString ( ) . match ( / [ ^ \/ ] * $ / ) [ 0 ] ) ;
751
+ destination . lastIndex = source . lastIndex ;
765
752
} else {
766
- var h = destination . $$hashKey ;
767
- if ( isArray ( destination ) ) {
768
- destination . length = 0 ;
769
- } else {
770
- forEach ( destination , function ( value , key ) {
771
- delete destination [ key ] ;
772
- } ) ;
753
+ if ( isWindow ( source ) || isScope ( source ) ) {
754
+ throw ngMinErr ( 'cpws' ,
755
+ "Can't copy! Making copies of Window or Scope instances is not supported." ) ;
773
756
}
774
- for ( var key in source ) {
775
- if ( source . hasOwnProperty ( key ) ) {
776
- destination [ key ] = copy ( source [ key ] , null , stackSource , stackDest ) ;
757
+
758
+ destination = destination || Object . create ( Object . getPrototypeOf ( source ) ) ;
759
+ traverse = true ;
760
+ }
761
+
762
+ ( stackSource || ( stackSource = [ ] ) ) . push ( source ) ;
763
+ ( stackDest || ( stackDest = [ ] ) ) . push ( destination ) ;
764
+
765
+ if ( traverse ) {
766
+ if ( isArray ( source ) ) {
767
+ for ( var i = 0 , ii = destination . length = source . length ; i < ii ; i ++ ) {
768
+ destination [ i ] = copy ( source [ i ] , null , stackSource , stackDest ) ;
769
+ }
770
+ } else {
771
+ destinationHashKey = destinationHashKey || false ;
772
+ for ( var key in source ) {
773
+ if ( source . hasOwnProperty ( key ) ) {
774
+ destination [ key ] = copy ( source [ key ] , null , stackSource , stackDest ) ;
775
+ }
777
776
}
778
777
}
779
- setHashKey ( destination , h ) ;
780
778
}
779
+ // Otherwise assign simple properties
780
+ } else if ( ! destination ) {
781
+ destination = source ;
782
+ }
781
783
784
+ if ( destinationHashKey !== undefined ) {
785
+ setHashKey ( destination , destinationHashKey ) ;
782
786
}
787
+
783
788
return destination ;
784
789
}
785
790
0 commit comments