mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
fix(core): Do not mark duplicates as circular references in jsonStringify
(#5789)
* fix(core): jsonStringify should not mark duplicates as circular references * not mark duplicates as circular references in the code node as well
This commit is contained in:
parent
f15f4bdcf2
commit
18efaf397a
|
@ -12,9 +12,7 @@ function isTraversable(maybe: unknown): maybe is IDataObject {
|
||||||
* Stringify any non-standard JS objects (e.g. `Date`, `RegExp`) inside output items at any depth.
|
* Stringify any non-standard JS objects (e.g. `Date`, `RegExp`) inside output items at any depth.
|
||||||
*/
|
*/
|
||||||
export function standardizeOutput(output: IDataObject) {
|
export function standardizeOutput(output: IDataObject) {
|
||||||
const knownObjects = new WeakSet();
|
function standardizeOutputRecursive(obj: IDataObject, knownObjects = new WeakSet()): IDataObject {
|
||||||
|
|
||||||
function standardizeOutputRecursive(obj: IDataObject): IDataObject {
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
if (!isTraversable(value)) continue;
|
if (!isTraversable(value)) continue;
|
||||||
|
|
||||||
|
@ -29,7 +27,7 @@ export function standardizeOutput(output: IDataObject) {
|
||||||
obj[key] =
|
obj[key] =
|
||||||
value.constructor.name !== 'Object'
|
value.constructor.name !== 'Object'
|
||||||
? JSON.stringify(value) // Date, RegExp, etc.
|
? JSON.stringify(value) // Date, RegExp, etc.
|
||||||
: standardizeOutputRecursive(value);
|
: standardizeOutputRecursive(value, knownObjects);
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,27 +64,24 @@ export const jsonParse = <T>(jsonString: string, options?: JSONParseOptions<T>):
|
||||||
|
|
||||||
type JSONStringifyOptions = {
|
type JSONStringifyOptions = {
|
||||||
replaceCircularRefs?: boolean;
|
replaceCircularRefs?: boolean;
|
||||||
circularRefReplacement?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getReplaceCircularReferencesFn = (options: JSONStringifyOptions) => {
|
const replaceCircularReferences = <T>(value: T, knownObjects = new WeakSet()): T => {
|
||||||
const knownObjects = new WeakSet();
|
if (value && typeof value === 'object') {
|
||||||
return (key: any, value: any) => {
|
if (knownObjects.has(value)) return '[Circular Reference]' as T;
|
||||||
if (typeof value === 'object' && value !== null) {
|
knownObjects.add(value);
|
||||||
if (knownObjects.has(value)) {
|
const copy = (Array.isArray(value) ? [] : {}) as T;
|
||||||
return options?.circularRefReplacement ?? '[Circular Reference]';
|
for (const key in value) {
|
||||||
}
|
copy[key] = replaceCircularReferences(value[key], knownObjects);
|
||||||
knownObjects.add(value);
|
|
||||||
}
|
}
|
||||||
return value;
|
knownObjects.delete(value);
|
||||||
};
|
return copy;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const jsonStringify = (obj: unknown, options: JSONStringifyOptions = {}): string => {
|
export const jsonStringify = (obj: unknown, options: JSONStringifyOptions = {}): string => {
|
||||||
const replacer = options?.replaceCircularRefs
|
return JSON.stringify(options?.replaceCircularRefs ? replaceCircularReferences(obj) : obj);
|
||||||
? getReplaceCircularReferencesFn(options)
|
|
||||||
: undefined;
|
|
||||||
return JSON.stringify(obj, replacer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const sleep = async (ms: number): Promise<void> =>
|
export const sleep = async (ms: number): Promise<void> =>
|
||||||
|
|
|
@ -30,6 +30,14 @@ describe('jsonStringify', () => {
|
||||||
'{"a":1,"b":2,"c":"[Circular Reference]"}',
|
'{"a":1,"b":2,"c":"[Circular Reference]"}',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not detect duplicates as circular references', () => {
|
||||||
|
const y = { z: 5 };
|
||||||
|
const x = [y, y, { y }];
|
||||||
|
expect(jsonStringify(x, { replaceCircularRefs: true })).toEqual(
|
||||||
|
'[{"z":5},{"z":5},{"y":{"z":5}}]',
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deepCopy', () => {
|
describe('deepCopy', () => {
|
||||||
|
|
Loading…
Reference in a new issue