Skip to content

Commit

Permalink
fix(core): Fix AssetInterceptor stack overflow with cyclic response
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Jun 21, 2019
1 parent 0470e03 commit c90a2a4
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
26 changes: 26 additions & 0 deletions packages/core/src/api/middleware/asset-interceptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,30 @@ describe('AssetInterceptor', () => {
},
),
);

describe('cyclic objects', () => {
const fido: any = {
name: 'fido',
avatar: mockAsset(),
};
const person = {
name: 'joe',
pet: fido,
};
fido.owner = person;

it(
'handles objects with cycles',
testInterceptor(
{
result: person,
},
(response, result, toAbsoluteUrl) => {
expect(result.result.pet.avatar).toEqual({ source: 'visited', preview: 'visited' });
expect(toAbsoluteUrl).toHaveBeenCalledTimes(2);
},
),
);
});

});
10 changes: 7 additions & 3 deletions packages/core/src/api/middleware/asset-interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class AssetInterceptor implements NestInterceptor {
* Traverses the object and when encountering a property with a value which
* is an instance of class T, invokes the visitor function on that value.
*/
function visitType<T>(obj: any, types: Array<Type<T> | string>, visit: (instance: T | string) => T | string) {
function visitType<T>(obj: any, types: Array<Type<T> | string>, visit: (instance: T | string) => T | string, seen: Set<any> = new Set()) {
const keys = Object.keys(obj || {});
for (const key of keys) {
const value = obj[key];
Expand All @@ -72,8 +72,12 @@ function visitType<T>(obj: any, types: Array<Type<T> | string>, visit: (instance
visit(value);
}
}
if (typeof value === 'object') {
visitType(value, types, visit);
if (typeof value === 'object' && !seen.has(value)) {
// add this object to the set of "seen" objects,
// which prevents us getting stuck in the case of a
// cyclic graph.
seen.add(value);
visitType(value, types, visit, seen);
}
}
}

0 comments on commit c90a2a4

Please sign in to comment.