in desktop/flipper-plugin/src/utils/shallowSerialization.tsx [93:174]
function check(value: any) {
if (value === null || done) {
return;
}
switch (typeof value) {
case 'undefined':
// undefined is not strictly speaking serializable, but behaves fine.
// JSON.stringify({x : undefined}) ==> '{}'
break;
case 'boolean':
case 'number':
case 'string':
break;
case 'object':
// A cycle is truly not serializable, as it would create an unending serialization loop...
if (stack.has(value)) {
throw new Error(
`Cycle detected: object at path '.${path.join(
'.',
)}' is referring to itself: '${value}'`,
);
}
// Encountering an object multiple times is bad, as reference equality will be lost upon
// deserialization, so the data isn't properly normalised.
// But it *might* work fine, and can serialize, so we just warn
// Warning is only printed during the second check loop, so that we know *both* paths
// - Second walk (which finds first object)
if (duplicateFound && duplicateObject && value === duplicateObject) {
console.warn(
`Duplicate value, object lives at path '.${duplicatePath!.join(
'.',
)}', but also at path '.${path!.join(
'.',
)}': '${value}'. This might not behave correct after import and lead to unnecessary big exports.`,
);
done = true; // no need to finish the second walk
break;
}
// - First walk (which detects the duplicate and stores location of duplicate)
if (!duplicateFound) {
if (seen.has(value)) {
duplicateFound = true;
duplicateObject = value;
duplicatePath = path.slice();
}
seen.add(value);
}
stack.add(value);
const proto = Object.getPrototypeOf(value);
if (Array.isArray(value)) {
value.forEach((child, index) => {
path.push('' + index);
check(child);
path.pop();
});
} else if (proto === null || proto === Object.prototype) {
for (const key in value) {
path.push(key);
check(value[key]);
path.pop();
}
} else {
throw new Error(
`Unserializable object type (${
proto?.constructor?.name ?? 'Unknown'
}) at path '.${path.join('')}': ${value}.`,
);
}
stack.delete(value);
break;
case 'bigint':
case 'function':
case 'symbol':
default:
throw new Error(
`Unserializable value (${typeof value}) at path '.${path.join(
'.',
)}': '${value}'`,
);
}
}