@@ -108,12 +108,36 @@ export function installHook (target) {
108
108
} )
109
109
110
110
// Clone deep utility for cloning initial state of the store
111
- // REFERENCE: https://github.com/buunguyen/node-clone/commit/63afda9de9d94b9332586e34a646a13e8d719244
111
+ // REFERENCE: https://github.com/pvorb/clone
112
+
113
+ let NativeMap
114
+ try {
115
+ NativeMap = Map
116
+ } catch ( _ ) {
117
+ // maybe a reference error because no `Map`. Give it a dummy value that no
118
+ // value will ever be an instanceof.
119
+ NativeMap = function ( ) { }
120
+ }
121
+
122
+ let NativeSet
123
+ try {
124
+ NativeSet = Set
125
+ } catch ( _ ) {
126
+ NativeSet = function ( ) { }
127
+ }
112
128
113
- function clone ( parent , circular , depth , prototype ) {
129
+ let NativePromise
130
+ try {
131
+ NativePromise = Promise
132
+ } catch ( _ ) {
133
+ NativePromise = function ( ) { }
134
+ }
135
+
136
+ function clone ( parent , circular , depth , prototype , includeNonEnumerable ) {
114
137
if ( typeof circular === 'object' ) {
115
138
depth = circular . depth
116
139
prototype = circular . prototype
140
+ includeNonEnumerable = circular . includeNonEnumerable
117
141
circular = circular . circular
118
142
}
119
143
// maintain two arrays for circular references, where corresponding parents
@@ -140,30 +164,37 @@ export function installHook (target) {
140
164
return parent
141
165
}
142
166
143
- if ( parent instanceof Map ) {
144
- child = new Map ( )
145
- } else if ( parent instanceof Set ) {
146
- child = new Set ( )
147
- } else if ( parent instanceof Promise ) {
148
- child = new Promise ( function ( resolve , reject ) {
167
+ if ( _instanceof ( parent , NativeMap ) ) {
168
+ child = new NativeMap ( )
169
+ } else if ( _instanceof ( parent , NativeSet ) ) {
170
+ child = new NativeSet ( )
171
+ } else if ( _instanceof ( parent , NativePromise ) ) {
172
+ child = new NativePromise ( function ( resolve , reject ) {
149
173
parent . then ( function ( value ) {
150
174
resolve ( _clone ( value , depth - 1 ) )
151
175
} , function ( err ) {
152
176
reject ( _clone ( err , depth - 1 ) )
153
177
} )
154
178
} )
155
- } else if ( _isArray ( parent ) ) {
179
+ } else if ( clone . __isArray ( parent ) ) {
156
180
child = [ ]
157
- } else if ( _isRegExp ( parent ) ) {
158
- child = new RegExp ( parent . source , _getRegExpFlags ( parent ) )
181
+ } else if ( clone . __isRegExp ( parent ) ) {
182
+ child = new RegExp ( parent . source , __getRegExpFlags ( parent ) )
159
183
if ( parent . lastIndex ) child . lastIndex = parent . lastIndex
160
- } else if ( _isDate ( parent ) ) {
184
+ } else if ( clone . __isDate ( parent ) ) {
161
185
child = new Date ( parent . getTime ( ) )
162
186
} else if ( useBuffer && Buffer . isBuffer ( parent ) ) {
163
- child = Buffer . alloc ( parent . length )
164
- parent . copy ( child )
187
+ if ( Buffer . from ) {
188
+ // Node.js >= 5.10.0
189
+ child = Buffer . from ( parent )
190
+ } else {
191
+ // Older Node.js versions
192
+ // eslint-disable-next-line node/no-deprecated-api
193
+ child = new Buffer ( parent . length )
194
+ parent . copy ( child )
195
+ }
165
196
return child
166
- } else if ( parent instanceof Error ) {
197
+ } else if ( _instanceof ( parent , Error ) ) {
167
198
child = Object . create ( parent )
168
199
} else {
169
200
if ( typeof prototype === 'undefined' ) {
@@ -185,40 +216,25 @@ export function installHook (target) {
185
216
allChildren . push ( child )
186
217
}
187
218
188
- if ( parent instanceof Map ) {
189
- var keyIterator = parent . keys ( )
190
- while ( true ) {
191
- let next = keyIterator . next ( )
192
- if ( next . done ) {
193
- break
194
- }
195
- var keyChild = _clone ( next . value , depth - 1 )
196
- var valueChild = _clone ( parent . get ( next . value ) , depth - 1 )
219
+ if ( _instanceof ( parent , NativeMap ) ) {
220
+ parent . forEach ( function ( value , key ) {
221
+ var keyChild = _clone ( key , depth - 1 )
222
+ var valueChild = _clone ( value , depth - 1 )
197
223
child . set ( keyChild , valueChild )
198
- }
224
+ } )
199
225
}
200
- if ( parent instanceof Set ) {
201
- var iterator = parent . keys ( )
202
- while ( true ) {
203
- let next = iterator . next ( )
204
- if ( next . done ) {
205
- break
206
- }
207
- var entryChild = _clone ( next . value , depth - 1 )
226
+ if ( _instanceof ( parent , NativeSet ) ) {
227
+ parent . forEach ( function ( value ) {
228
+ var entryChild = _clone ( value , depth - 1 )
208
229
child . add ( entryChild )
209
- }
230
+ } )
210
231
}
211
232
212
- for ( let i in parent ) {
213
- var attrs
214
- if ( proto ) {
215
- attrs = Object . getOwnPropertyDescriptor ( proto , i )
216
- }
217
-
218
- if ( attrs && attrs . set == null ) {
219
- continue
233
+ for ( var i in parent ) {
234
+ var attrs = Object . getOwnPropertyDescriptor ( parent , i )
235
+ if ( attrs ) {
236
+ child [ i ] = _clone ( parent [ i ] , depth - 1 )
220
237
}
221
- child [ i ] = _clone ( parent [ i ] , depth - 1 )
222
238
}
223
239
224
240
if ( Object . getOwnPropertySymbols ) {
@@ -228,10 +244,24 @@ export function installHook (target) {
228
244
// like a number or string.
229
245
var symbol = symbols [ i ]
230
246
var descriptor = Object . getOwnPropertyDescriptor ( parent , symbol )
231
- if ( descriptor && ! descriptor . enumerable ) {
247
+ if ( descriptor && ! descriptor . enumerable && ! includeNonEnumerable ) {
232
248
continue
233
249
}
234
250
child [ symbol ] = _clone ( parent [ symbol ] , depth - 1 )
251
+ Object . defineProperty ( child , symbol , descriptor )
252
+ }
253
+ }
254
+
255
+ if ( includeNonEnumerable ) {
256
+ var allPropertyNames = Object . getOwnPropertyNames ( parent )
257
+ for ( let i = 0 ; i < allPropertyNames . length ; i ++ ) {
258
+ const propertyName = allPropertyNames [ i ]
259
+ let descriptor = Object . getOwnPropertyDescriptor ( parent , propertyName )
260
+ if ( descriptor && descriptor . enumerable ) {
261
+ continue
262
+ }
263
+ child [ propertyName ] = _clone ( parent [ propertyName ] , depth - 1 )
264
+ Object . defineProperty ( child , propertyName , descriptor )
235
265
}
236
266
}
237
267
@@ -243,27 +273,36 @@ export function installHook (target) {
243
273
244
274
// private utility functions
245
275
246
- function _objToStr ( o ) {
276
+ function __objToStr ( o ) {
247
277
return Object . prototype . toString . call ( o )
248
278
}
279
+ clone . __objToStr = __objToStr
249
280
250
- function _isDate ( o ) {
251
- return typeof o === 'object' && _objToStr ( o ) === '[object Date]'
281
+ function __isDate ( o ) {
282
+ return typeof o === 'object' && __objToStr ( o ) === '[object Date]'
252
283
}
284
+ clone . __isDate = __isDate
253
285
254
- function _isArray ( o ) {
255
- return typeof o === 'object' && _objToStr ( o ) === '[object Array]'
286
+ function __isArray ( o ) {
287
+ return typeof o === 'object' && __objToStr ( o ) === '[object Array]'
256
288
}
289
+ clone . __isArray = __isArray
257
290
258
- function _isRegExp ( o ) {
259
- return typeof o === 'object' && _objToStr ( o ) === '[object RegExp]'
291
+ function __isRegExp ( o ) {
292
+ return typeof o === 'object' && __objToStr ( o ) === '[object RegExp]'
260
293
}
294
+ clone . __isRegExp = __isRegExp
261
295
262
- function _getRegExpFlags ( re ) {
296
+ function __getRegExpFlags ( re ) {
263
297
var flags = ''
264
298
if ( re . global ) flags += 'g'
265
299
if ( re . ignoreCase ) flags += 'i'
266
300
if ( re . multiline ) flags += 'm'
267
301
return flags
268
302
}
303
+ clone . __getRegExpFlags = __getRegExpFlags
304
+
305
+ function _instanceof ( obj , type ) {
306
+ return type != null && obj instanceof type
307
+ }
269
308
}
0 commit comments