Iterative version of the serializer
Summary: Iterative version of the custom serializer. The recursive implementation led to call stack overflow for news feed surface in fb4a. Reviewed By: danielbuechele Differential Revision: D15251643 fbshipit-source-id: b8af921b1a4d85c52d4d45a7abf95a5bb5f283f7
This commit is contained in:
committed by
Facebook Github Bot
parent
3fa0a92754
commit
4dcb41f5e6
@@ -13,33 +13,149 @@ export function deserialize(str: string): Object {
|
|||||||
return deserializeObject(JSON.parse(str));
|
return deserializeObject(JSON.parse(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processArray(
|
||||||
|
element: any,
|
||||||
|
array: [any],
|
||||||
|
stack: Array<any>,
|
||||||
|
dict: Map<any, any>,
|
||||||
|
): {premature: boolean, outputArr: Array<any>} {
|
||||||
|
let outputArr = [];
|
||||||
|
let premature = false;
|
||||||
|
for (const item of array) {
|
||||||
|
if (!dict.has(item)) {
|
||||||
|
if (!(item instanceof Object)) {
|
||||||
|
dict.set(item, item);
|
||||||
|
} else {
|
||||||
|
stack.push(element);
|
||||||
|
stack.push(item);
|
||||||
|
premature = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dict.has(item)) {
|
||||||
|
dict.set(item, dict.get(item));
|
||||||
|
outputArr.push(dict.get(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {premature, outputArr};
|
||||||
|
}
|
||||||
|
|
||||||
|
function processKeyValuePair(
|
||||||
|
element: any,
|
||||||
|
key: any,
|
||||||
|
value: any,
|
||||||
|
stack: Array<any>,
|
||||||
|
dict: Map<any, any>,
|
||||||
|
): {premature: boolean} {
|
||||||
|
let premature = false;
|
||||||
|
if (!dict.has(key)) {
|
||||||
|
if (!(key instanceof Object)) {
|
||||||
|
dict.set(key, key);
|
||||||
|
} else {
|
||||||
|
stack.push(element);
|
||||||
|
stack.push(key);
|
||||||
|
premature = true;
|
||||||
|
return {premature};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dict.has(value)) {
|
||||||
|
if (!(value instanceof Object)) {
|
||||||
|
dict.set(value, value);
|
||||||
|
} else {
|
||||||
|
stack.push(element);
|
||||||
|
stack.push(value);
|
||||||
|
premature = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {premature};
|
||||||
|
}
|
||||||
|
|
||||||
export function makeObjectSerializable(obj: any): any {
|
export function makeObjectSerializable(obj: any): any {
|
||||||
if (!(obj instanceof Object)) {
|
if (!(obj instanceof Object)) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
if (obj instanceof Map) {
|
let stack = [obj];
|
||||||
return {
|
const dict: Map<any, any> = new Map();
|
||||||
__flipper_object_type__: 'Map',
|
while (stack.length > 0) {
|
||||||
data: [...obj].map(makeObjectSerializable),
|
const element = stack.pop();
|
||||||
};
|
if (element instanceof Map) {
|
||||||
} else if (obj instanceof Set) {
|
const arr = [];
|
||||||
return {
|
let premature = false;
|
||||||
__flipper_object_type__: 'Set',
|
for (const item of [...element]) {
|
||||||
data: [...obj].map(makeObjectSerializable),
|
const key = item[0];
|
||||||
};
|
const value = item[1];
|
||||||
} else if (obj instanceof Date) {
|
premature = processKeyValuePair(element, key, value, stack, dict)
|
||||||
return {
|
.premature;
|
||||||
__flipper_object_type__: 'Date',
|
if (premature) {
|
||||||
data: obj.toString(),
|
break;
|
||||||
};
|
}
|
||||||
} else if (obj instanceof Array) {
|
if (dict.has(key) && dict.has(value)) {
|
||||||
return obj.map(makeObjectSerializable);
|
dict.set(item, [dict.get(key), dict.get(value)]);
|
||||||
|
arr.push([dict.get(key), dict.get(value)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (premature) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dict.set(element, {
|
||||||
|
__flipper_object_type__: 'Map',
|
||||||
|
data: arr,
|
||||||
|
});
|
||||||
|
} else if (element instanceof Set) {
|
||||||
|
const {premature, outputArr} = processArray(
|
||||||
|
element,
|
||||||
|
[...element],
|
||||||
|
stack,
|
||||||
|
dict,
|
||||||
|
);
|
||||||
|
if (premature) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dict.set(element, {
|
||||||
|
__flipper_object_type__: 'Set',
|
||||||
|
data: outputArr,
|
||||||
|
});
|
||||||
|
} else if (element instanceof Date) {
|
||||||
|
dict.set(element, {
|
||||||
|
__flipper_object_type__: 'Date',
|
||||||
|
data: element.toString(),
|
||||||
|
});
|
||||||
|
} else if (element instanceof Array) {
|
||||||
|
const {premature, outputArr} = processArray(
|
||||||
|
element,
|
||||||
|
element,
|
||||||
|
stack,
|
||||||
|
dict,
|
||||||
|
);
|
||||||
|
if (premature) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dict.set(element, outputArr);
|
||||||
|
} else if (element instanceof Object) {
|
||||||
|
const array = Object.entries(element);
|
||||||
|
let obj = {};
|
||||||
|
let premature = false;
|
||||||
|
for (const item of array) {
|
||||||
|
const key = item[0];
|
||||||
|
const value = item[1];
|
||||||
|
premature = processKeyValuePair(element, key, value, stack, dict)
|
||||||
|
.premature;
|
||||||
|
if (premature) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const serializedKey = dict.get(key);
|
||||||
|
const serializedValue = dict.get(value);
|
||||||
|
if (serializedValue && serializedKey) {
|
||||||
|
obj = {...obj, [serializedKey]: serializedValue};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (premature) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dict.set(element, obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return dict.get(obj);
|
||||||
return Object.entries(obj).reduce(
|
|
||||||
(acc, [key, value]) => ({...acc, [key]: makeObjectSerializable(value)}),
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deserializeObject(obj: any): any {
|
export function deserializeObject(obj: any): any {
|
||||||
|
|||||||
Reference in New Issue
Block a user