mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
fix(core): Prevent augmentObject from creating infinitely deep proxies (#5893)
fixes #5848
This commit is contained in:
parent
35cf783e83
commit
6906b00b0e
|
@ -1,18 +1,9 @@
|
|||
import type { IDataObject } from './Interfaces';
|
||||
|
||||
const augmentedObjects = new WeakSet<object>();
|
||||
|
||||
function augment<T>(value: T): T {
|
||||
if (
|
||||
typeof value !== 'object' ||
|
||||
value === null ||
|
||||
value instanceof RegExp ||
|
||||
augmentedObjects.has(value)
|
||||
)
|
||||
return value;
|
||||
|
||||
// Track augmented objects to prevent infinite recursion in cases where an object contains circular references
|
||||
augmentedObjects.add(value);
|
||||
|
||||
if (typeof value !== 'object' || value === null || value instanceof RegExp) return value;
|
||||
if (value instanceof Date) return new Date(value.valueOf()) as T;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
|
@ -23,6 +14,8 @@ function augment<T>(value: T): T {
|
|||
}
|
||||
|
||||
export function augmentArray<T>(data: T[]): T[] {
|
||||
if (augmentedObjects.has(data)) return data;
|
||||
|
||||
let newData: unknown[] | undefined = undefined;
|
||||
|
||||
function getData(): unknown[] {
|
||||
|
@ -32,7 +25,7 @@ export function augmentArray<T>(data: T[]): T[] {
|
|||
return newData;
|
||||
}
|
||||
|
||||
return new Proxy(data, {
|
||||
const proxy = new Proxy(data, {
|
||||
deleteProperty(target, key: string) {
|
||||
return Reflect.deleteProperty(getData(), key);
|
||||
},
|
||||
|
@ -63,24 +56,25 @@ export function augmentArray<T>(data: T[]): T[] {
|
|||
return Reflect.ownKeys(newData !== undefined ? newData : target);
|
||||
},
|
||||
set(target, key: string, newValue: unknown) {
|
||||
if (newValue !== null && typeof newValue === 'object') {
|
||||
// Always proxy all objects. Like that we can check in get simply if it
|
||||
// is a proxy and it does then not matter if it was already there from the
|
||||
// beginning and it got proxied at some point or set later and so theoretically
|
||||
// does not have to get proxied
|
||||
newValue = new Proxy(newValue, {});
|
||||
}
|
||||
|
||||
return Reflect.set(getData(), key, newValue);
|
||||
// Always proxy all objects. Like that we can check in get simply if it
|
||||
// is a proxy and it does then not matter if it was already there from the
|
||||
// beginning and it got proxied at some point or set later and so theoretically
|
||||
// does not have to get proxied
|
||||
return Reflect.set(getData(), key, augment(newValue));
|
||||
},
|
||||
});
|
||||
|
||||
augmentedObjects.add(proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
export function augmentObject<T extends object>(data: T): T {
|
||||
if (augmentedObjects.has(data)) return data;
|
||||
|
||||
const newData = {} as IDataObject;
|
||||
const deletedProperties: Array<string | symbol> = [];
|
||||
|
||||
return new Proxy(data, {
|
||||
const proxy = new Proxy(data, {
|
||||
get(target, key: string, receiver): unknown {
|
||||
if (deletedProperties.indexOf(key) !== -1) {
|
||||
return undefined;
|
||||
|
@ -144,4 +138,7 @@ export function augmentObject<T extends object>(data: T): T {
|
|||
};
|
||||
},
|
||||
});
|
||||
|
||||
augmentedObjects.add(proxy);
|
||||
return proxy;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue