serialization

Summary: Remove serialisation utilities which are now unused

Reviewed By: priteshrnandgaonkar

Differential Revision: D29394737

fbshipit-source-id: 19ead40dfdb493cbbaee09745b3fc313272da34d
This commit is contained in:
Michel Weststrate
2021-06-30 10:40:50 -07:00
committed by Facebook GitHub Bot
parent 7c3d9f0cf0
commit 4b3772ced4
3 changed files with 0 additions and 579 deletions

View File

@@ -13,7 +13,6 @@ export {produce} from 'immer';
export * from './ui/index';
export {getStringFromErrorLike, textContent, sleep} from './utils/index';
export {serialize, deserialize} from './utils/serialization';
export * from './utils/jsonTypes';
export {default as GK, loadGKs, loadDistilleryGK} from './fb-stubs/GK';
export {default as createPaste} from './fb-stubs/createPaste';

View File

@@ -1,337 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {makeObjectSerializable, deserializeObject} from '../serialization';
class TestObject extends Object {
constructor(title: Object, map?: Map<any, any>, set?: Set<any>) {
super();
this.title = title;
this.map = map;
this.set = set;
}
title: Object;
map?: Map<any, any>;
set?: Set<any>;
}
test('test makeObjectSerializable function for unnested object with no Set and Map', async () => {
const obj = {key1: 'value1', key2: 'value2'};
const output = await makeObjectSerializable(obj);
expect(output).toEqual(obj);
// Testing numbers
const obj2 = {key1: 1, key2: 2};
const output2 = await makeObjectSerializable(obj2);
expect(output2).toEqual(obj2);
});
test('makeObjectSerializable function for unnested object with values which returns false when put in an if condition', async () => {
const obj2 = {key1: 0, key2: ''};
const output2 = await makeObjectSerializable(obj2);
return expect(output2).toEqual(obj2);
});
test('test deserializeObject function for unnested object with no Set and Map', () => {
const obj = {key1: 'value1', key2: 'value2'};
const output = deserializeObject(obj);
expect(output).toEqual(obj);
// Testing numbers
const obj2 = {key1: 1, key2: 2};
const output2 = deserializeObject(obj2);
expect(output2).toEqual(obj2);
});
test('test makeObjectSerializable and deserializeObject function for nested object with no Set and Map', async () => {
const subObj = {key1: 'value1', key2: 'value2'};
const subObj2 = {key21: 'value21', key22: 'value22'};
const obj = {key1: subObj, key2: subObj2};
const output = await makeObjectSerializable(obj);
expect(output).toEqual(obj);
expect(deserializeObject(output)).toEqual(obj);
const subObjNum = {key1: 1, key2: 2};
const subObjNum2 = {key21: 21, key22: 22};
const obj2 = {key1: subObjNum, key2: subObjNum2};
const output2 = await makeObjectSerializable(obj2);
expect(output2).toEqual(obj2);
expect(deserializeObject(output2)).toEqual(obj2);
});
test('test makeObjectSerializable and deserializeObject function for Map and Set with no nesting', async () => {
const map = new Map([
['k1', 'v1'],
['k2', 'v2'],
]);
const output = await makeObjectSerializable(map);
const expected = {
__flipper_object_type__: 'Map',
data: [
['k1', 'v1'],
['k2', 'v2'],
],
};
expect(output).toEqual(expected);
expect(deserializeObject(output)).toEqual(map);
const set = new Set([1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]);
const outputSet = await makeObjectSerializable(set);
const expectedSet = {
__flipper_object_type__: 'Set',
data: [1, 2, 3, 4, 5, 6],
};
expect(outputSet).toEqual(expectedSet);
expect(deserializeObject(outputSet)).toEqual(set);
});
test('test makeObjectSerializable and deserializeObject function for Map and Set with nesting', async () => {
const map = new Map([
[{title: 'k1'}, {title: 'v1'}],
[{title: 'k2'}, {title: 'v2'}],
]);
const output = await makeObjectSerializable(map);
const expected = {
__flipper_object_type__: 'Map',
data: [
[{title: 'k1'}, {title: 'v1'}],
[{title: 'k2'}, {title: 'v2'}],
],
};
expect(output).toEqual(expected);
expect(deserializeObject(output)).toEqual(map);
const set = new Set([
{title: '1'},
{title: '2'},
{title: '3'},
{title: '4'},
{title: '5'},
{title: '6'},
]);
const outputSet = await makeObjectSerializable(set);
const expectedSet = {
__flipper_object_type__: 'Set',
data: [
{title: '1'},
{title: '2'},
{title: '3'},
{title: '4'},
{title: '5'},
{title: '6'},
],
};
expect(outputSet).toEqual(expectedSet);
expect(deserializeObject(outputSet)).toEqual(set);
});
test('test makeObjectSerializable and deserializeObject function for custom Object', async () => {
const obj = new TestObject('title');
const output = await makeObjectSerializable(obj);
expect(output).toEqual(obj);
expect(deserializeObject(output)).toEqual(obj);
const nestedObj = new TestObject({title: 'nestedTitle'});
const nestedoutput = await makeObjectSerializable(nestedObj);
expect(nestedoutput).toEqual(nestedObj);
expect(deserializeObject(nestedoutput)).toEqual(nestedObj);
const nestedObjWithMap = new TestObject(
{title: 'nestedTitle'},
new Map([
['k1', 'v1'],
['k2', 'v2'],
]),
);
const nestedObjWithMapOutput = await makeObjectSerializable(nestedObjWithMap);
const expectedNestedObjWithMapOutput = {
title: {title: 'nestedTitle'},
map: {
__flipper_object_type__: 'Map',
data: [
['k1', 'v1'],
['k2', 'v2'],
],
},
set: undefined,
};
expect(nestedObjWithMapOutput).toEqual(expectedNestedObjWithMapOutput);
expect(deserializeObject(nestedObjWithMapOutput)).toEqual(nestedObjWithMap);
const nestedObjWithMapSet = new TestObject(
{title: 'nestedTitle'},
new Map([
['k1', 'v1'],
['k2', 'v2'],
]),
new Set([
{title: '1'},
{title: '2'},
{title: '3'},
{title: '4'},
{title: '5'},
{title: '6'},
]),
);
const nestedObjWithMapSetOutput = await makeObjectSerializable(
nestedObjWithMapSet,
);
const expectedNestedObjWithMapSetOutput = {
title: {title: 'nestedTitle'},
map: {
__flipper_object_type__: 'Map',
data: [
['k1', 'v1'],
['k2', 'v2'],
],
},
set: {
__flipper_object_type__: 'Set',
data: [
{title: '1'},
{title: '2'},
{title: '3'},
{title: '4'},
{title: '5'},
{title: '6'},
],
},
};
expect(nestedObjWithMapSetOutput).toEqual(expectedNestedObjWithMapSetOutput);
expect(deserializeObject(nestedObjWithMapSetOutput)).toEqual(
nestedObjWithMapSet,
);
});
test('test makeObjectSerializable and deserializeObject function for Array as input', async () => {
const arr = [1, 2, 4, 5];
const output = await makeObjectSerializable(arr);
expect(output).toEqual(arr);
expect(deserializeObject(output)).toEqual(arr);
const arrMap = [
new Map([
['a1', 'v1'],
['a2', 'v2'],
]),
new Map([
['b1', 'v1'],
['b2', 'v2'],
]),
new Map([
['c1', 'v1'],
['c2', 'v2'],
]),
new Map([
['d1', 'v1'],
['d2', 'v2'],
]),
];
const expectedArr = [
{
__flipper_object_type__: 'Map',
data: [
['a1', 'v1'],
['a2', 'v2'],
],
},
{
__flipper_object_type__: 'Map',
data: [
['b1', 'v1'],
['b2', 'v2'],
],
},
{
__flipper_object_type__: 'Map',
data: [
['c1', 'v1'],
['c2', 'v2'],
],
},
{
__flipper_object_type__: 'Map',
data: [
['d1', 'v1'],
['d2', 'v2'],
],
},
];
const outputMap = await makeObjectSerializable(arrMap);
expect(outputMap).toEqual(expectedArr);
expect(deserializeObject(outputMap)).toEqual(arrMap);
const arrStr = ['first', 'second', 'third', 'fourth'];
const outputStr = await makeObjectSerializable(arrStr);
expect(outputStr).toEqual(arrStr);
expect(deserializeObject(outputStr)).toEqual(arrStr);
});
test('test serialize and deserializeObject function for non Object input', async () => {
expect(await makeObjectSerializable('octopus')).toEqual('octopus');
expect(deserializeObject(await makeObjectSerializable('octopus'))).toEqual(
'octopus',
);
expect(await makeObjectSerializable(24567)).toEqual(24567);
expect(deserializeObject(await makeObjectSerializable(24567))).toEqual(24567);
});
test('test makeObjectSerializable and deserializeObject function for Date input', async () => {
const date = new Date(2021, 1, 29, 10, 31, 7, 205);
expect(await makeObjectSerializable(date)).toMatchInlineSnapshot(`
Object {
"__flipper_object_type__": "Date",
"data": "${date.toJSON()}",
}
`);
expect(deserializeObject(await makeObjectSerializable(date))).toEqual(date);
});
test('test makeObjectSerializable and deserializeObject function for Map of Sets', async () => {
const map = new Map([
['k1', new Set([1, 2, 3, 4, 5, 6])],
[new Set([1, 2]), new Map([['k3', 'v3']])],
] as any);
const expectedOutput = {
__flipper_object_type__: 'Map',
data: [
['k1', {__flipper_object_type__: 'Set', data: [1, 2, 3, 4, 5, 6]}],
[
{__flipper_object_type__: 'Set', data: [1, 2]},
{__flipper_object_type__: 'Map', data: [['k3', 'v3']]},
],
],
};
expect(await makeObjectSerializable(map)).toEqual(expectedOutput);
expect(deserializeObject(await makeObjectSerializable(map))).toEqual(map);
});
test('test makeObjectSerializable and deserializeObject function for Map, Dates and Set with complex nesting', async () => {
const date1 = new Date('2019-02-15');
const date2 = new Date('2019-02-16');
const map = new Map([
['k1', date1],
['k2', new Set([date2])],
] as any);
const expectedOutput = {
__flipper_object_type__: 'Map',
data: [
['k1', {__flipper_object_type__: 'Date', data: date1.toJSON()}],
[
'k2',
{
__flipper_object_type__: 'Set',
data: [{__flipper_object_type__: 'Date', data: date2.toJSON()}],
},
],
],
};
expect(await makeObjectSerializable(map)).toEqual(expectedOutput);
expect(deserializeObject(await makeObjectSerializable(map))).toEqual(map);
});

View File

@@ -1,241 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Idler} from 'flipper-plugin';
export async function serialize(
obj: Object,
idler?: Idler,
statusUpdate?: (msg: string) => void,
statusMsg?: string,
): Promise<string> {
return makeObjectSerializable(obj, idler, statusUpdate, statusMsg).then(
(obj) => JSON.stringify(obj),
);
}
export function deserialize(str: string): any {
return deserializeObject(JSON.parse(str));
}
function processArray(
_element: any,
array: Array<any>,
stack: Array<any>,
dict: Map<any, any>,
): {childNeedsIteration: boolean; outputArr: Array<any>} {
// Adds the array item to the stack if it needs to undergo iteration to serialise it. Otherwise it adds the serialized version of the item to the memoization dict
const outputArr = [];
let childNeedsIteration = false;
for (const item of array) {
const isItemInstanceOfObject = item instanceof Object;
if (!dict.has(item) && isItemInstanceOfObject) {
stack.push(item);
childNeedsIteration = true;
continue;
} else if (!dict.has(item) && !isItemInstanceOfObject) {
dict.set(item, item);
}
outputArr.push(dict.get(item));
}
return {childNeedsIteration, outputArr};
}
function processKeyValuePair(
_element: any,
key: any,
value: any,
stack: Array<any>,
dict: Map<any, any>,
): {childNeedsIteration: boolean} {
// Adds the key and value to the stack if it needs to undergo iteration to serialise it. Otherwise it adds the serialized version of key and value to the memoization dict
let childNeedsIteration = false;
const isKeyInstanceOfObject = key instanceof Object;
if (!dict.has(key) && !isKeyInstanceOfObject) {
dict.set(key, key);
} else if (!dict.has(key) && isKeyInstanceOfObject) {
stack.push(key);
childNeedsIteration = true;
}
const isValueInstanceOfObject = value instanceof Object;
if (!dict.has(value) && !isValueInstanceOfObject) {
dict.set(value, value);
} else if (!dict.has(value) && isValueInstanceOfObject) {
stack.push(value);
childNeedsIteration = true;
}
return {childNeedsIteration};
}
export function processMapElement(
obj: Map<any, any>,
dict: Map<any, any>,
stack: Array<any>,
): {childNeedsIteration: boolean; outputArray: Array<any>} {
const arr = [];
let childNeedsIteration = false;
for (const item of [...obj]) {
const key = item[0];
const value = item[1];
childNeedsIteration =
childNeedsIteration ||
processKeyValuePair(obj, key, value, stack, dict).childNeedsIteration;
if (!childNeedsIteration && dict.has(key) && dict.has(value)) {
dict.set(item, [dict.get(key), dict.get(value)]);
arr.push([dict.get(key), dict.get(value)]);
}
}
return {childNeedsIteration, outputArray: arr};
}
export function processObjectToBeSerialized(
element: Object,
dict: Map<any, any>,
stack: Array<any>,
): {childNeedsIteration: boolean; outputObject: Object} {
const array = Object.entries(element);
let obj = {};
let childNeedsIteration = false;
for (const item of array) {
const key = item[0];
const value = item[1];
childNeedsIteration =
childNeedsIteration ||
processKeyValuePair(element, key, value, stack, dict).childNeedsIteration;
if (!childNeedsIteration && dict.has(key) && dict.has(value)) {
const serializedKey = dict.get(key);
const serializedValue = dict.get(value);
if (
typeof serializedKey !== 'undefined' &&
typeof serializedValue !== 'undefined'
) {
obj = {...obj, [serializedKey]: serializedValue};
}
}
}
return {childNeedsIteration, outputObject: obj};
}
export async function makeObjectSerializable(
obj: any,
idler?: Idler,
statusUpdate?: (msg: string) => void,
statusMsg?: string,
): Promise<any> {
if (!(obj instanceof Object)) {
return obj;
}
const stack = [obj];
const dict: Map<any, any> = new Map();
let numIterations = 0;
let prevStackLength = stack.length;
let accumulator = prevStackLength;
while (stack.length > 0) {
const element = stack[stack.length - 1];
if (element instanceof Map) {
const {childNeedsIteration, outputArray} = processMapElement(
element,
dict,
stack,
);
if (childNeedsIteration) {
continue;
}
dict.set(element, {
__flipper_object_type__: 'Map',
data: outputArray,
});
} else if (element instanceof Set) {
const {childNeedsIteration, outputArr} = processArray(
element,
[...element],
stack,
dict,
);
if (childNeedsIteration) {
continue;
}
dict.set(element, {
__flipper_object_type__: 'Set',
data: outputArr,
});
} else if (element instanceof Date) {
dict.set(element, {
__flipper_object_type__: 'Date',
data: element.toJSON(),
});
} else if (element instanceof Array) {
const {childNeedsIteration, outputArr} = processArray(
element,
element,
stack,
dict,
);
if (childNeedsIteration) {
continue;
}
dict.set(element, outputArr);
} else if (element instanceof Object) {
const {childNeedsIteration, outputObject} = processObjectToBeSerialized(
element,
dict,
stack,
);
if (childNeedsIteration) {
continue;
}
dict.set(element, outputObject);
}
stack.pop();
++numIterations;
accumulator +=
stack.length >= prevStackLength ? stack.length - prevStackLength + 1 : 0;
if (idler && idler.shouldIdle()) {
const percentage = (numIterations / accumulator) * 100;
statusUpdate &&
statusUpdate(
`${
statusMsg || 'Serializing Flipper '
}: ${numIterations} / ${accumulator} (${percentage.toFixed(2)}%) `,
);
await idler.idle();
}
prevStackLength = stack.length;
}
return dict.get(obj);
}
export function deserializeObject(obj: any): any {
if (!(obj instanceof Object)) {
return obj;
}
if (obj instanceof Array) {
return obj.map(deserializeObject);
} else if (obj['__flipper_object_type__']) {
const type = obj['__flipper_object_type__'];
switch (type) {
case 'Map': {
return new Map(
// @ts-ignore
[...obj.data].map((item) => [...item].map(deserializeObject)),
);
}
case 'Set': {
return new Set([...obj.data].map(deserializeObject));
}
case 'Date':
return new Date(obj.data);
}
}
return Object.entries(obj).reduce(
(acc, [key, value]) => ({...acc, [key]: deserializeObject(value)}),
{},
);
}