@@ -231,20 +231,20 @@ function serializeValue(value: any): any {
231231 return '[Array]' ;
232232 }
233233
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 ;
236238}
237239
238240/**
239- * normalizeValue ()
241+ * makeSerializable ()
240242 *
241- * Takes unserializable input and make it serializable friendly
243+ * Takes unserializable input and make it serializer- friendly.
242244 *
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.
246246 */
247- function normalizeValue < T > ( value : T , key ?: any ) : T | string {
247+ function makeSerializable < T > ( value : T , key ?: any ) : T | string {
248248 if ( key === 'domain' && value && typeof value === 'object' && ( value as unknown as { _events : any } ) . _events ) {
249249 return '[Domain]' ;
250250 }
@@ -310,6 +310,8 @@ function normalizeValue<T>(value: T, key?: any): T | string {
310310 */
311311// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
312312export function walk ( key : string , value : any , depth : number = + Infinity , memo : MemoFunc = memoBuilder ( ) ) : any {
313+ const [ memoize , unmemoize ] = memo ;
314+
313315 // If we reach the maximum depth, serialize whatever is left
314316 if ( depth === 0 ) {
315317 return serializeValue ( value ) ;
@@ -322,21 +324,23 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
322324 }
323325 /* eslint-enable @typescript-eslint/no-unsafe-member-access */
324326
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 ;
329333 }
330334
331335 // Create source that we will use for the next iteration. It will either be an objectified error object (`Error` type
332336 // with extracted key:value pairs) or the input itself.
333337 const source = getWalkSource ( value ) ;
334338
335339 // 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 ) ? [ ] : { } ;
337341
338342 // If we already walked that branch, bail out, as it's circular reference
339- if ( memo [ 0 ] ( value ) ) {
343+ if ( memoize ( value ) ) {
340344 return '[Circular ~]' ;
341345 }
342346
@@ -347,11 +351,12 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
347351 continue ;
348352 }
349353 // 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 ) ;
351356 }
352357
353358 // Once walked through all the branches, remove the parent from memo storage
354- memo [ 1 ] ( value ) ;
359+ unmemoize ( value ) ;
355360
356361 // Return accumulated values
357362 return acc ;
@@ -372,7 +377,8 @@ export function walk(key: string, value: any, depth: number = +Infinity, memo: M
372377// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
373378export function normalize ( input : any , depth ?: number ) : any {
374379 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 ) ;
376382 } catch ( _oO ) {
377383 return '**non-serializable**' ;
378384 }
0 commit comments