Skip to content

Commit

Permalink
fix(core): Prevent augmentObject from creating infinitely deep proxies (
Browse files Browse the repository at this point in the history
#5893)

fixes #5848
  • Loading branch information
netroy committed Apr 4, 2023
1 parent 35cf783 commit 6906b00
Showing 1 changed file with 19 additions and 22 deletions.
41 changes: 19 additions & 22 deletions packages/workflow/src/AugmentObject.ts
Original file line number Diff line number Diff line change
@@ -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);

function augment<T>(value: T): T {
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
Expand All @@ -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[] {
Expand All @@ -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);
},
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -144,4 +138,7 @@ export function augmentObject<T extends object>(data: T): T {
};
},
});

augmentedObjects.add(proxy);
return proxy;
}

0 comments on commit 6906b00

Please sign in to comment.