Skip to content
This repository was archived by the owner on Feb 8, 2020. It is now read-only.

Commit e5063b9

Browse files
committed
fix: ignore circular references when checking serializable
1 parent ec35bd5 commit e5063b9

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import isSerializable from '../isSerializable';
2+
3+
it('returns true for serializable object', () => {
4+
expect(
5+
isSerializable({
6+
index: 0,
7+
key: '7',
8+
routeNames: ['foo', 'bar'],
9+
routes: [
10+
{
11+
key: 'foo',
12+
name: 'foo',
13+
state: {
14+
index: 0,
15+
key: '8',
16+
routeNames: ['qux', 'lex'],
17+
routes: [
18+
{ key: 'qux', name: 'qux' },
19+
{ key: 'lex', name: 'lex' },
20+
],
21+
},
22+
},
23+
],
24+
})
25+
).toBe(true);
26+
});
27+
28+
it('returns false for non-serializable object', () => {
29+
expect(
30+
isSerializable({
31+
index: 0,
32+
key: '7',
33+
routeNames: ['foo', 'bar'],
34+
routes: [
35+
{
36+
key: 'foo',
37+
name: 'foo',
38+
state: {
39+
index: 0,
40+
key: '8',
41+
routeNames: ['qux', 'lex'],
42+
routes: [
43+
{ key: 'qux', name: 'qux', params: () => 42 },
44+
{ key: 'lex', name: 'lex' },
45+
],
46+
},
47+
},
48+
],
49+
})
50+
).toBe(false);
51+
});
52+
53+
it('returns false for circular references', () => {
54+
const o = {
55+
index: 0,
56+
key: '7',
57+
routeNames: ['foo', 'bar'],
58+
routes: [
59+
{
60+
key: 'foo',
61+
name: 'foo',
62+
},
63+
],
64+
};
65+
66+
// @ts-ignore
67+
o.routes[0].state = o;
68+
69+
expect(isSerializable(o)).toBe(false);
70+
});

packages/core/src/isSerializable.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
export default function isSerializable(o: { [key: string]: any }): boolean {
1+
const isSerializableWithoutCircularReference = (
2+
o: { [key: string]: any },
3+
seen = new Set<any>()
4+
): boolean => {
25
if (
36
o === undefined ||
47
o === null ||
@@ -16,19 +19,29 @@ export default function isSerializable(o: { [key: string]: any }): boolean {
1619
return false;
1720
}
1821

22+
if (seen.has(o)) {
23+
return false;
24+
}
25+
26+
seen.add(o);
27+
1928
if (Array.isArray(o)) {
2029
for (const it of o) {
21-
if (!isSerializable(it)) {
30+
if (!isSerializableWithoutCircularReference(it, seen)) {
2231
return false;
2332
}
2433
}
2534
} else {
2635
for (const key in o) {
27-
if (!isSerializable(o[key])) {
36+
if (!isSerializableWithoutCircularReference(o[key], seen)) {
2837
return false;
2938
}
3039
}
3140
}
3241

3342
return true;
43+
};
44+
45+
export default function isSerializable(o: { [key: string]: any }) {
46+
return isSerializableWithoutCircularReference(o);
3447
}

0 commit comments

Comments
 (0)