@@ -75,55 +75,65 @@ function deepCopy(
7575 visitedObjects : WeakMap < object , string > ,
7676 replacer ?: ReplacerFunction ,
7777) : unknown {
78- let existingPath : string | undefined ;
79- let copy : unknown [ ] | DecycledObject ;
80-
81- if ( replacer !== undefined ) {
78+ if ( typeof replacer === 'function' ) {
8279 value = replacer ( value ) ;
8380 }
8481
85- if (
86- typeof value === 'object' &&
87- value !== null &&
88- ! ( value instanceof Boolean ) &&
89- ! ( value instanceof Date ) &&
90- ! ( value instanceof Number ) &&
91- ! ( value instanceof RegExp ) &&
92- ! ( value instanceof String )
93- ) {
94- existingPath = visitedObjects . get ( value ) ;
82+ if ( isPlainObjectOrArray ( value ) ) {
83+ const existingPath = visitedObjects . get ( value ) ;
84+
9585 if ( existingPath !== undefined ) {
9686 return { $ref : existingPath } ;
9787 }
9888
9989 visitedObjects . set ( value , path ) ;
10090
10191 if ( Array . isArray ( value ) ) {
102- copy = [ ] ;
103- ( value as unknown [ ] ) . forEach ( ( element : unknown , index : number ) => {
104- ( copy as unknown [ ] ) [ index ] = deepCopy (
92+ const copy : unknown [ ] = [ ] ;
93+ value . forEach ( ( element , index ) => {
94+ copy [ index ] = deepCopy (
10595 element ,
10696 `${ path } [${ index . toString ( ) } ]` ,
10797 visitedObjects ,
10898 replacer ,
10999 ) ;
110100 } ) ;
111- } else {
112- copy = { } as DecycledObject ;
113- Object . keys ( value as Record < string , unknown > ) . forEach ( function (
114- key : string ,
115- ) {
116- ( copy as DecycledObject ) [ key ] = deepCopy (
117- ( value as Record < string , unknown > ) [ key ] ,
118- `${ path } [${ JSON . stringify ( key ) } ]` ,
119- visitedObjects ,
120- replacer ,
121- ) ;
122- } ) ;
101+ return copy ;
123102 }
124103
104+ const record = value as Record < string , unknown > ;
105+ const copy : DecycledObject = { } ;
106+
107+ Object . keys ( record ) . forEach ( ( key ) => {
108+ copy [ key ] = deepCopy (
109+ record [ key ] ,
110+ `${ path } [${ JSON . stringify ( key ) } ]` ,
111+ visitedObjects ,
112+ replacer ,
113+ ) ;
114+ } ) ;
115+
125116 return copy ;
126117 }
127118
128119 return value ;
129120}
121+
122+ /**
123+ * Checks whether a value is a plain object or array (not a primitive or
124+ * built-in wrapper like `Boolean`, `Date`, `Number`, `RegExp`, or `String`).
125+ *
126+ * @param value - The value to check.
127+ * @returns `true` if the value is a plain object or array.
128+ */
129+ function isPlainObjectOrArray ( value : unknown ) : value is object {
130+ return (
131+ typeof value === 'object' &&
132+ value !== null &&
133+ ! ( value instanceof Boolean ) &&
134+ ! ( value instanceof Date ) &&
135+ ! ( value instanceof Number ) &&
136+ ! ( value instanceof RegExp ) &&
137+ ! ( value instanceof String )
138+ ) ;
139+ }
0 commit comments