-
Notifications
You must be signed in to change notification settings - Fork 0
/
serialization.js
116 lines (97 loc) · 2.37 KB
/
serialization.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const serializeError = require('serialize-error')
const dateRegex = require('regex-iso-date')()
function serialize(value) {
if (null === value) {
return null
}
switch (typeof value) {
case 'boolean':
case 'string':
case 'number':
return value
}
if (Array.isArray(value)) {
return value.map(serialize)
}
if (value instanceof Error) {
return serializeError(value)
}
if (
'object' === typeof value && (
value instanceof Set ||
'function' === typeof value[Symbol.iterator]
)
) {
return serialize(Array.from(value))
}
if (
value instanceof Map || (
'object' === typeof value &&
'function' === typeof value.entries
)
) {
const entries = Array.from(value.entries())
const reduce = (o, kv) => Object.assign({ [kv[0]]: kv[1] })
return serialize(entries.reduce(reduce, {}))
}
if ('function' === typeof value) {
const original = value
const isAsync = value.toString().match(/^async\s+/)
let string = value.toString().replace(/^async\s+/, '')
if (!/^function/.test(string)) {
if ('(' !== string.toString()[0]) {
value = `${isAsync ? 'async ' : ''}function ${string}`
}
}
try {
const source = `return ${value.toString()}`
return String(new Function(source))
} catch (err) {
return null
}
}
try {
if ('object' === typeof value) {
const copy = value
value = {}
for (const k in copy) {
value[k] = serialize(copy[k])
}
}
} catch (err) {
return null
}
return value
}
function deserialize(value) {
if (Array.isArray(value)) {
return value.map(deserialize)
}
if (null !== value && 'object' === typeof value) {
if ('Buffer' === value.type && Array.isArray(value.data)) {
return Buffer.from(value)
}
if ('name' in value && 'message' in value) {
const error = new Error(value.message)
Object.assign(error, value)
return error
}
}
if ('string' === typeof value) {
if ('null' === value) {
return null
}
if ((24 === value.length || 27 === value.length) && dateRegex.test(value)) {
return new Date(Date.parse(value))
}
if ('function' === value.slice(0, 8)) {
const holder = new Function(`return ${value}`)
return holder()()
}
}
return value
}
module.exports = {
deserialize,
serialize
}