@@ -231,20 +231,20 @@ function serializeValue(value: any): any {
231
231
return '[Array]' ;
232
232
}
233
233
234
- const normalized = normalizeValue ( value ) ;
235
- return isPrimitive ( normalized ) ? normalized : type ;
234
+ // `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
235
+ // pass-through.
236
+ const serializable = makeSerializable ( value ) ;
237
+ return isPrimitive ( serializable ) ? serializable : type ;
236
238
}
237
239
238
240
/**
239
- * normalizeValue ()
241
+ * makeSerializable ()
240
242
*
241
- * Takes unserializable input and make it serializable friendly
243
+ * Takes unserializable input and make it serializer- friendly.
242
244
*
243
- * - translates undefined/NaN values to "[undefined]"/"[NaN]" respectively,
244
- * - serializes Error objects
245
- * - filter global objects
245
+ * Handles globals, functions, `undefined`, `NaN`, and other non-serializable values.
246
246
*/
247
- function normalizeValue < T > ( value : T , key ?: any ) : T | string {
247
+ function makeSerializable < T > ( value : T , key ?: any ) : T | string {
248
248
if ( key === 'domain' && value && typeof value === 'object' && ( value as unknown as { _events : any } ) . _events ) {
249
249
return '[Domain]' ;
250
250
}
@@ -310,6 +310,8 @@ function normalizeValue<T>(value: T, key?: any): T | string {
310
310
*/
311
311
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
312
312
export function walk ( key : string , value : any , depth : number = + Infinity , memo : MemoFunc = memoBuilder ( ) ) : any {
313
+ const [ memoize , unmemoize ] = memo ;
314
+
313
315
// If we reach the maximum depth, serialize whatever is left
314
316
if ( depth === 0 ) {
315
317
return serializeValue ( value ) ;
@@ -322,21 +324,23 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
322
324
}
323
325
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
324
326
325
- // If normalized value is a primitive, there are no branches left to walk, so bail out
326
- const normalized = normalizeValue ( value , key ) ;
327
- if ( isPrimitive ( normalized ) ) {
328
- return normalized ;
327
+ // `makeSerializable` provides a string representation of certain non-serializable values. For all others, it's a
328
+ // pass-through. If what comes back is a primitive (either because it's been stringified or because it was primitive
329
+ // all along), we're done.
330
+ const serializable = makeSerializable ( value , key ) ;
331
+ if ( isPrimitive ( serializable ) ) {
332
+ return serializable ;
329
333
}
330
334
331
335
// Create source that we will use for the next iteration. It will either be an objectified error object (`Error` type
332
336
// with extracted key:value pairs) or the input itself.
333
337
const source = getWalkSource ( value ) ;
334
338
335
339
// Create an accumulator that will act as a parent for all future itterations of that branch
336
- const acc = Array . isArray ( value ) ? [ ] : { } ;
340
+ const acc : { [ key : string ] : any } = Array . isArray ( value ) ? [ ] : { } ;
337
341
338
342
// If we already walked that branch, bail out, as it's circular reference
339
- if ( memo [ 0 ] ( value ) ) {
343
+ if ( memoize ( value ) ) {
340
344
return '[Circular ~]' ;
341
345
}
342
346
@@ -347,11 +351,12 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
347
351
continue ;
348
352
}
349
353
// Recursively walk through all the child nodes
350
- ( acc as { [ key : string ] : any } ) [ innerKey ] = walk ( innerKey , source [ innerKey ] , depth - 1 , memo ) ;
354
+ const innerValue : any = source [ innerKey ] ;
355
+ acc [ innerKey ] = walk ( innerKey , innerValue , depth - 1 , memo ) ;
351
356
}
352
357
353
358
// Once walked through all the branches, remove the parent from memo storage
354
- memo [ 1 ] ( value ) ;
359
+ unmemoize ( value ) ;
355
360
356
361
// Return accumulated values
357
362
return acc ;
@@ -372,7 +377,8 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
372
377
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
373
378
export function normalize ( input : any , depth ?: number ) : any {
374
379
try {
375
- return JSON . parse ( JSON . stringify ( input , ( key : string , value : any ) => walk ( key , value , depth ) ) ) ;
380
+ // since we're at the outermost level, there is no key
381
+ return walk ( '' , input , depth ) ;
376
382
} catch ( _oO ) {
377
383
return '**non-serializable**' ;
378
384
}
0 commit comments