fix: ignore circular references when checking serializable

This commit is contained in:
Satyajit Sahoo
2020-02-03 05:18:03 +01:00
parent ec35bd5821
commit e5063b9339
2 changed files with 86 additions and 3 deletions

View File

@@ -0,0 +1,70 @@
import isSerializable from '../isSerializable';
it('returns true for serializable object', () => {
expect(
isSerializable({
index: 0,
key: '7',
routeNames: ['foo', 'bar'],
routes: [
{
key: 'foo',
name: 'foo',
state: {
index: 0,
key: '8',
routeNames: ['qux', 'lex'],
routes: [
{ key: 'qux', name: 'qux' },
{ key: 'lex', name: 'lex' },
],
},
},
],
})
).toBe(true);
});
it('returns false for non-serializable object', () => {
expect(
isSerializable({
index: 0,
key: '7',
routeNames: ['foo', 'bar'],
routes: [
{
key: 'foo',
name: 'foo',
state: {
index: 0,
key: '8',
routeNames: ['qux', 'lex'],
routes: [
{ key: 'qux', name: 'qux', params: () => 42 },
{ key: 'lex', name: 'lex' },
],
},
},
],
})
).toBe(false);
});
it('returns false for circular references', () => {
const o = {
index: 0,
key: '7',
routeNames: ['foo', 'bar'],
routes: [
{
key: 'foo',
name: 'foo',
},
],
};
// @ts-ignore
o.routes[0].state = o;
expect(isSerializable(o)).toBe(false);
});

View File

@@ -1,4 +1,7 @@
export default function isSerializable(o: { [key: string]: any }): boolean {
const isSerializableWithoutCircularReference = (
o: { [key: string]: any },
seen = new Set<any>()
): boolean => {
if (
o === undefined ||
o === null ||
@@ -16,19 +19,29 @@ export default function isSerializable(o: { [key: string]: any }): boolean {
return false;
}
if (seen.has(o)) {
return false;
}
seen.add(o);
if (Array.isArray(o)) {
for (const it of o) {
if (!isSerializable(it)) {
if (!isSerializableWithoutCircularReference(it, seen)) {
return false;
}
}
} else {
for (const key in o) {
if (!isSerializable(o[key])) {
if (!isSerializableWithoutCircularReference(o[key], seen)) {
return false;
}
}
}
return true;
};
export default function isSerializable(o: { [key: string]: any }) {
return isSerializableWithoutCircularReference(o);
}