@@ -719,45 +719,72 @@ function isLeafNode (node) {
719
719
</doc:source>
720
720
</doc:example>
721
721
*/
722
- function copy ( source , destination ) {
722
+ function copy ( source , destination , recursiveKeys , recursiveValues ) {
723
+ if ( ! recursiveKeys ) {
724
+ recursiveKeys = [ ] ;
725
+ recursiveValues = [ ] ;
726
+ }
727
+
728
+ function storePair ( key , value ) {
729
+ recursiveKeys . push ( key ) ;
730
+ recursiveValues . push ( value ) ;
731
+ }
732
+
723
733
if ( isWindow ( source ) || isScope ( source ) ) {
724
734
throw ngMinErr ( 'cpws' ,
725
735
"Can't copy! Making copies of Window or Scope instances is not supported." ) ;
726
736
}
727
737
728
- if ( ! destination ) {
729
- destination = source ;
730
- if ( source ) {
731
- if ( isArray ( source ) ) {
732
- destination = copy ( source , [ ] ) ;
733
- } else if ( isDate ( source ) ) {
734
- destination = new Date ( source . getTime ( ) ) ;
735
- } else if ( isRegExp ( source ) ) {
736
- destination = new RegExp ( source . source ) ;
737
- } else if ( isObject ( source ) ) {
738
- destination = copy ( source , { } ) ;
739
- }
740
- }
741
- } else {
742
- if ( source === destination ) throw ngMinErr ( 'cpi' ,
743
- "Can't copy! Source and destination are identical." ) ;
744
- if ( isArray ( source ) ) {
745
- destination . length = 0 ;
746
- for ( var i = 0 ; i < source . length ; i ++ ) {
747
- destination . push ( copy ( source [ i ] ) ) ;
738
+ var existingSourceIndex = recursiveKeys . indexOf ( source ) ;
739
+ if ( existingSourceIndex === - 1 ) {
740
+ if ( ! destination ) {
741
+ destination = source ;
742
+ if ( source ) {
743
+ if ( isArray ( source ) ) {
744
+ destination = copy ( source , [ ] , recursiveKeys , recursiveValues ) ;
745
+ } else if ( isDate ( source ) ) {
746
+ destination = new Date ( source . getTime ( ) ) ;
747
+ storePair ( source , destination ) ;
748
+ } else if ( isRegExp ( source ) ) {
749
+ destination = new RegExp ( source . source ) ;
750
+ storePair ( source , destination ) ;
751
+ } else if ( source . cloneNode ) {
752
+ destination = source . cloneNode ( ) ;
753
+ storePair ( source , destination ) ;
754
+ } else if ( isObject ( source ) ) {
755
+ destination = copy ( source , { } , recursiveKeys , recursiveValues ) ;
756
+ } else {
757
+ storePair ( source , destination ) ;
758
+ }
759
+ } else {
760
+ storePair ( source , destination ) ;
748
761
}
749
762
} else {
750
- var h = destination . $$hashKey ;
751
- forEach ( destination , function ( value , key ) {
752
- delete destination [ key ] ;
753
- } ) ;
754
- for ( var key in source ) {
755
- destination [ key ] = copy ( source [ key ] ) ;
763
+ if ( source === destination ) throw ngMinErr ( 'cpi' ,
764
+ "Can't copy! Source and destination are identical." ) ;
765
+
766
+ storePair ( source , destination ) ;
767
+ if ( isArray ( source ) ) {
768
+ destination . length = 0 ;
769
+ for ( var i = 0 ; i < source . length ; i ++ ) {
770
+ destination . push ( copy ( source [ i ] , null , recursiveKeys , recursiveValues ) ) ;
771
+ }
772
+ } else {
773
+ var h = destination . $$hashKey ;
774
+ forEach ( destination , function ( value , key ) {
775
+ delete destination [ key ] ;
776
+ } ) ;
777
+ for ( var key in source ) {
778
+ destination [ key ] = copy ( source [ key ] , null , recursiveKeys , recursiveValues ) ;
779
+ }
780
+ setHashKey ( destination , h ) ;
756
781
}
757
- setHashKey ( destination , h ) ;
758
782
}
783
+
784
+ return destination ;
785
+ } else {
786
+ return recursiveValues [ existingSourceIndex ] ;
759
787
}
760
- return destination ;
761
788
}
762
789
763
790
/**
0 commit comments