|
1 | 1 | import { isPlainObject } from './isPlainObject'; |
2 | 2 | import { pathToPointer } from './pathToPointer'; |
3 | 3 |
|
4 | | -export function decycle(obj: unknown, replacer?: (value: any) => any) { |
| 4 | +export const decycle = (obj: unknown, replacer?: (value: any) => any) => { |
5 | 5 | const objs = new WeakMap<object, string>(); |
6 | 6 | const processedObjs = new WeakSet<object>(); |
7 | | - function derez(value: any, path: (string | number)[]): any { |
8 | | - if (replacer) { |
9 | | - value = replacer(value); |
10 | | - } |
| 7 | + |
| 8 | + return (function derez(value: any, path: string[]) { |
| 9 | + // The new object or array |
| 10 | + let curObj: any; |
| 11 | + |
| 12 | + // If a replacer function was provided, then call it to get a replacement value. |
| 13 | + if (replacer) value = replacer(value); |
| 14 | + |
11 | 15 | if (isPlainObject(value) || Array.isArray(value)) { |
12 | 16 | // The path of an earlier occurance of value |
13 | 17 | const oldPath = objs.get(value); |
14 | 18 | // If the value is an object or array, look to see if we have already |
15 | 19 | // encountered it. If so, return a {"$ref":PATH} object. |
16 | | - if (oldPath) { |
17 | | - return { $ref: oldPath }; |
18 | | - } |
| 20 | + if (oldPath) return { $ref: oldPath }; |
| 21 | + |
19 | 22 | objs.set(value, pathToPointer(path)); |
20 | 23 | // If it is an array, replicate the array. |
21 | 24 | if (Array.isArray(value)) { |
22 | | - return value.map((element, i) => derez(element, [...path, i])); |
23 | | - } |
24 | | - const newObj: Record<string, any> = {}; |
25 | | - for (const name in value) { |
26 | | - if (Object.prototype.hasOwnProperty.call(value, name)) { |
27 | | - newObj[name] = derez(value[name], [...path, name]); |
28 | | - } |
| 25 | + curObj = value.map((element, i) => derez(element, [...path, String(i)])); |
| 26 | + } else { |
| 27 | + // It is an object, replicate the object. |
| 28 | + curObj = {}; |
| 29 | + Object.keys(value).forEach(name => { |
| 30 | + curObj[name] = derez(value[name], [...path, name]); |
| 31 | + }); |
29 | 32 | } |
30 | | - // Only delete the object from the map if it has not been processed before |
31 | 33 | if (!processedObjs.has(value)) { |
32 | 34 | objs.delete(value); |
33 | 35 | } |
34 | 36 | processedObjs.add(value); |
35 | | - return newObj; |
| 37 | + return curObj; |
36 | 38 | } |
37 | 39 | return value; |
38 | | - } |
39 | | - return derez(obj, []); |
40 | | -} |
| 40 | + })(obj, []); |
| 41 | +}; |
0 commit comments