File tree Expand file tree Collapse file tree 2 files changed +58
-1
lines changed Expand file tree Collapse file tree 2 files changed +58
-1
lines changed Original file line number Diff line number Diff line change @@ -12,8 +12,15 @@ export function deepCopy(src: any, des: any): void {
12
12
while ( stack . length ) {
13
13
const { src, des } = stack . pop ( ) !
14
14
15
+ // using `Object.keys` which skips prototype properties
15
16
Object . keys ( src ) . forEach ( key => {
16
- if ( isNotObjectOrIsArray ( src [ key ] ) || isNotObjectOrIsArray ( des [ key ] ) ) {
17
+ // if src[key] is an object/array, set des[key]
18
+ // to empty object/array to prevent setting by reference
19
+ if ( isObject ( src [ key ] ) && ! isObject ( des [ key ] ) ) {
20
+ des [ key ] = Array . isArray ( src [ key ] ) ? [ ] : { }
21
+ }
22
+
23
+ if ( isNotObjectOrIsArray ( des [ key ] ) || isNotObjectOrIsArray ( src [ key ] ) ) {
17
24
// replace with src[key] when:
18
25
// src[key] or des[key] is not an object, or
19
26
// src[key] or des[key] is an array
Original file line number Diff line number Diff line change
1
+ import { deepCopy } from '../src/index'
2
+
3
+ test ( 'deepCopy merges without mutating src argument' , ( ) => {
4
+ const msg1 = {
5
+ hello : 'Greetings' ,
6
+ about : {
7
+ title : 'About us'
8
+ } ,
9
+ overwritten : 'Original text' ,
10
+ fruit : [ { name : 'Apple' } ]
11
+ }
12
+ const copy1 = structuredClone ( msg1 )
13
+
14
+ const msg2 = {
15
+ bye : 'Goodbye' ,
16
+ about : {
17
+ content : 'Some text'
18
+ } ,
19
+ overwritten : 'New text' ,
20
+ fruit : [ { name : 'Strawberry' } ] ,
21
+ // @ts -ignore
22
+ car : ( { plural } ) => plural ( [ 'car' , 'cars' ] )
23
+ }
24
+
25
+ const merged = { }
26
+
27
+ deepCopy ( msg1 , merged )
28
+ deepCopy ( msg2 , merged )
29
+
30
+ expect ( merged ) . toMatchInlineSnapshot ( `
31
+ {
32
+ "about": {
33
+ "content": "Some text",
34
+ "title": "About us",
35
+ },
36
+ "bye": "Goodbye",
37
+ "car": [Function],
38
+ "fruit": [
39
+ {
40
+ "name": "Strawberry",
41
+ },
42
+ ],
43
+ "hello": "Greetings",
44
+ "overwritten": "New text",
45
+ }
46
+ ` )
47
+
48
+ // should not mutate source object
49
+ expect ( msg1 ) . toStrictEqual ( copy1 )
50
+ } )
You can’t perform that action at this time.
0 commit comments