@@ -143,6 +143,8 @@ export function installHook (target) {
143
143
144
144
// Clone deep utility for cloning initial state of the store
145
145
// REFERENCE: https://github.com/pvorb/clone
146
+ // last updated: 2019-10-30
147
+ // ⚠️ DON'T FORGET TO UPDATE IT IN ./hook.js
146
148
147
149
let NativeMap
148
150
try {
@@ -167,25 +169,20 @@ export function installHook (target) {
167
169
NativePromise = function ( ) { }
168
170
}
169
171
170
- function clone ( parent , circular , depth , prototype , includeNonEnumerable ) {
171
- if ( typeof circular === 'object' ) {
172
- depth = circular . depth
173
- prototype = circular . prototype
174
- includeNonEnumerable = circular . includeNonEnumerable
175
- circular = circular . circular
176
- }
172
+ function clone ( parent , {
173
+ circular = true ,
174
+ depth = Infinity ,
175
+ prototype,
176
+ includeNonEnumerable
177
+ } = { } ) {
177
178
// maintain two arrays for circular references, where corresponding parents
178
179
// and children have the same index
179
180
let allParents = [ ]
180
181
let allChildren = [ ]
181
182
182
183
let useBuffer = typeof Buffer !== 'undefined' && typeof Buffer . isBuffer === 'function'
183
184
184
- let isBuffer = typeof window !== 'undefined' ? browserIsBuffer : Buffer . isBuffer
185
-
186
- if ( typeof circular === 'undefined' ) { circular = true }
187
-
188
- if ( typeof depth === 'undefined' ) { depth = Infinity }
185
+ const isBuffer = typeof window !== 'undefined' ? browserIsBuffer : Buffer . isBuffer
189
186
190
187
// recurse this function so we don't reset allParents and allChildren
191
188
function _clone ( parent , depth ) {
@@ -200,6 +197,8 @@ export function installHook (target) {
200
197
return parent
201
198
}
202
199
200
+ let walkProperties = true
201
+
203
202
if ( _instanceof ( parent , NativeMap ) ) {
204
203
child = new NativeMap ( )
205
204
} else if ( _instanceof ( parent , NativeSet ) ) {
@@ -233,7 +232,10 @@ export function installHook (target) {
233
232
} else if ( _instanceof ( parent , Error ) ) {
234
233
child = Object . create ( parent )
235
234
} else {
236
- if ( typeof prototype === 'undefined' ) {
235
+ if ( parent instanceof HTMLElement ) {
236
+ child = parent . cloneNode ( false )
237
+ walkProperties = false
238
+ } else if ( typeof prototype === 'undefined' ) {
237
239
proto = Object . getPrototypeOf ( parent )
238
240
child = Object . create ( proto )
239
241
} else {
@@ -266,43 +268,64 @@ export function installHook (target) {
266
268
} )
267
269
}
268
270
269
- for ( let i in parent ) {
270
- let attrs = Object . getOwnPropertyDescriptor ( parent , i )
271
- if ( attrs ) {
272
- if ( attrs . hasOwnProperty ( 'get' ) && attrs . get . name === 'computedGetter' ) {
273
- Object . defineProperty ( child , i , attrs )
274
- continue
271
+ if ( walkProperties ) {
272
+ for ( let i in parent ) {
273
+ let attrs = Object . getOwnPropertyDescriptor ( parent , i )
274
+ if ( attrs ) {
275
+ if ( attrs . hasOwnProperty ( 'get' ) && attrs . get . name === 'computedGetter' ) {
276
+ Object . defineProperty ( child , i , attrs )
277
+ continue
278
+ }
279
+
280
+ child [ i ] = _clone ( parent [ i ] , depth - 1 )
275
281
}
276
282
277
- child [ i ] = _clone ( parent [ i ] , depth - 1 )
283
+ // Huge performance impact
284
+ // try {
285
+ // const objProperty = Object.getOwnPropertyDescriptor(parent, i)
286
+ // if (objProperty.set === 'undefined') {
287
+ // // no setter defined. Skip cloning this property
288
+ // continue
289
+ // }
290
+ // child[i] = _clone(parent[i], depth - 1)
291
+ // } catch (e) {
292
+ // if (e instanceof TypeError) {
293
+ // // when in strict mode, TypeError will be thrown if child[i] property only has a getter
294
+ // // we can't do anything about this, other than inform the user that this property cannot be set.
295
+ // continue
296
+ // } else if (e instanceof ReferenceError) {
297
+ // // this may happen in non strict mode
298
+ // continue
299
+ // }
300
+ // }
278
301
}
279
- }
280
302
281
- if ( Object . getOwnPropertySymbols ) {
282
- let symbols = Object . getOwnPropertySymbols ( parent )
283
- for ( let i = 0 ; i < symbols . length ; i ++ ) {
284
- // Don't need to worry about cloning a symbol because it is a primitive,
285
- // like a number or string.
286
- let symbol = symbols [ i ]
287
- let descriptor = Object . getOwnPropertyDescriptor ( parent , symbol )
288
- if ( descriptor && ! descriptor . enumerable && ! includeNonEnumerable ) {
289
- continue
303
+ if ( Object . getOwnPropertySymbols ) {
304
+ let symbols = Object . getOwnPropertySymbols ( parent )
305
+ for ( let i = 0 ; i < symbols . length ; i ++ ) {
306
+ // Don't need to worry about cloning a symbol because it is a primitive,
307
+ // like a number or string.
308
+ const symbol = symbols [ i ]
309
+ const descriptor = Object . getOwnPropertyDescriptor ( parent , symbol )
310
+ if ( descriptor && ! descriptor . enumerable && ! includeNonEnumerable ) {
311
+ continue
312
+ }
313
+ child [ symbol ] = _clone ( parent [ symbol ] , depth - 1 )
314
+ Object . defineProperty ( child , symbol , descriptor )
290
315
}
291
- child [ symbol ] = _clone ( parent [ symbol ] , depth - 1 )
292
- Object . defineProperty ( child , symbol , descriptor )
293
316
}
294
- }
295
317
296
- if ( includeNonEnumerable ) {
297
- let allPropertyNames = Object . getOwnPropertyNames ( parent )
298
- for ( let i = 0 ; i < allPropertyNames . length ; i ++ ) {
299
- const propertyName = allPropertyNames [ i ]
300
- let descriptor = Object . getOwnPropertyDescriptor ( parent , propertyName )
301
- if ( descriptor && descriptor . enumerable ) {
302
- continue
318
+ if ( includeNonEnumerable ) {
319
+ let allPropertyNames = Object . getOwnPropertyNames ( parent )
320
+ for ( let i = 0 ; i < allPropertyNames . length ; i ++ ) {
321
+ const propertyName = allPropertyNames [ i ]
322
+ const descriptor = Object . getOwnPropertyDescriptor ( parent , propertyName )
323
+ if ( descriptor && descriptor . enumerable ) {
324
+ continue
325
+ }
326
+ child [ propertyName ] = _clone ( parent [ propertyName ] , depth - 1 )
327
+ Object . defineProperty ( child , propertyName , descriptor )
303
328
}
304
- child [ propertyName ] = _clone ( parent [ propertyName ] , depth - 1 )
305
- Object . defineProperty ( child , propertyName , descriptor )
306
329
}
307
330
}
308
331
0 commit comments