-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(dereference): modification for circular ref for delete objects (#132
) * fix(dereference): modification for circular ref * fix(dereference): added comments * fix: update test cases for circular objects * fix: update variable name
- Loading branch information
1 parent
3ddde69
commit ccea3e3
Showing
2 changed files
with
33 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,46 @@ | ||
import { isPlainObject } from './isPlainObject'; | ||
import { pathToPointer } from './pathToPointer'; | ||
|
||
export const decycle = (obj: unknown, replacer?: (value: any) => any) => { | ||
export function decycle(obj: unknown, replacer?: (value: any) => any) { | ||
const objs = new WeakMap<object, string>(); | ||
return (function derez(value: any, path: string[]) { | ||
// The new object or array | ||
let curObj: any; | ||
|
||
// If a replacer function was provided, then call it to get a replacement value. | ||
if (replacer) value = replacer(value); | ||
const objectsToBeDeleted: object[] = []; // To keep track of objects to delete later | ||
|
||
function derez(value: any, path: (string | number)[]): any { | ||
if (replacer) { | ||
value = replacer(value); | ||
} | ||
if (isPlainObject(value) || Array.isArray(value)) { | ||
// The path of an earlier occurance of value | ||
const oldPath = objs.get(value); | ||
|
||
// If the value is an object or array, look to see if we have already | ||
// encountered it. If so, return a {"$ref":PATH} object. | ||
if (oldPath) return { $ref: oldPath }; | ||
|
||
if (oldPath) { | ||
return { $ref: oldPath }; | ||
} | ||
objs.set(value, pathToPointer(path)); | ||
// If it is an array, replicate the array. | ||
if (Array.isArray(value)) { | ||
curObj = value.map((element, i) => derez(element, [...path, String(i)])); | ||
} else { | ||
// It is an object, replicate the object. | ||
curObj = {}; | ||
Object.keys(value).forEach(name => { | ||
curObj[name] = derez(value[name], [...path, name]); | ||
}); | ||
return value.map((element, i) => derez(element, [...path, i])); | ||
} | ||
objs.delete(value); | ||
return curObj; | ||
const newObj: Record<string, any> = {}; | ||
for (const name in value) { | ||
if (Object.prototype.hasOwnProperty.call(value, name)) { | ||
newObj[name] = derez(value[name], [...path, name]); | ||
} | ||
} | ||
// Schedule object for deletion after derez completes | ||
objectsToBeDeleted.push(value); | ||
return newObj; | ||
} | ||
return value; | ||
})(obj, []); | ||
}; | ||
} | ||
|
||
const result = derez(obj, []); | ||
|
||
// Clean up objs for objects that were processed | ||
objectsToBeDeleted.forEach(obj => { | ||
objs.delete(obj); | ||
}); | ||
|
||
return result; | ||
} |