mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-29 04:45:19 +08:00
fix: ignore circular references when checking serializable
This commit is contained in:
70
packages/core/src/__tests__/isSerializable.test.tsx
Normal file
70
packages/core/src/__tests__/isSerializable.test.tsx
Normal 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);
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user