seroval 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -9
- package/dist/cjs/development/index.cjs +682 -225
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -2
- package/dist/esm/development/index.mjs +682 -225
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -2
- package/dist/types/compat.d.ts +1 -1
- package/dist/types/context.d.ts +4 -4
- package/dist/types/quote.d.ts +1 -0
- package/dist/types/tree/deserialize.d.ts +4 -0
- package/dist/types/tree/primitives.d.ts +13 -9
- package/dist/types/tree/shared.d.ts +4 -1
- package/dist/types/tree/symbols.d.ts +33 -0
- package/dist/types/tree/types.d.ts +74 -28
- package/dist/types/types.d.ts +2 -1
- package/package.json +4 -4
- package/src/compat.ts +1 -1
- package/src/context.ts +39 -45
- package/src/index.ts +6 -1
- package/src/quote.ts +12 -1
- package/src/tree/async.ts +48 -32
- package/src/tree/deserialize.ts +288 -0
- package/src/tree/iterator.ts +14 -0
- package/src/tree/primitives.ts +155 -32
- package/src/tree/serialize.ts +109 -73
- package/src/tree/shared.ts +46 -2
- package/src/tree/symbols.ts +65 -0
- package/src/tree/sync.ts +47 -31
- package/src/tree/types.ts +85 -17
- package/src/types.ts +4 -1
package/src/tree/primitives.ts
CHANGED
|
@@ -1,23 +1,121 @@
|
|
|
1
1
|
import assert from '../assert';
|
|
2
2
|
import { Feature } from '../compat';
|
|
3
3
|
import { ParserContext } from '../context';
|
|
4
|
+
import quote from '../quote';
|
|
4
5
|
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
6
|
+
import { INV_SYMBOL_REF, WellKnownSymbols } from './symbols';
|
|
5
7
|
import {
|
|
6
8
|
SerovalBigIntNode,
|
|
7
9
|
SerovalBigIntTypedArrayNode,
|
|
10
|
+
SerovalBooleanNode,
|
|
8
11
|
SerovalDateNode,
|
|
12
|
+
SerovalInfinityNode,
|
|
13
|
+
SerovalNaNNode,
|
|
14
|
+
SerovalNegativeInfinityNode,
|
|
15
|
+
SerovalNegativeZeroNode,
|
|
9
16
|
SerovalNodeType,
|
|
10
|
-
|
|
17
|
+
SerovalNullNode,
|
|
18
|
+
SerovalNumberNode,
|
|
11
19
|
SerovalReferenceNode,
|
|
12
20
|
SerovalRegExpNode,
|
|
21
|
+
SerovalStringNode,
|
|
13
22
|
SerovalTypedArrayNode,
|
|
23
|
+
SerovalUndefinedNode,
|
|
24
|
+
SerovalWKSymbolNode,
|
|
14
25
|
} from './types';
|
|
15
26
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
export const TRUE_NODE: SerovalBooleanNode = {
|
|
28
|
+
t: SerovalNodeType.Boolean,
|
|
29
|
+
i: undefined,
|
|
30
|
+
s: true,
|
|
31
|
+
l: undefined,
|
|
32
|
+
c: undefined,
|
|
33
|
+
m: undefined,
|
|
34
|
+
d: undefined,
|
|
35
|
+
a: undefined,
|
|
36
|
+
f: undefined,
|
|
37
|
+
};
|
|
38
|
+
export const FALSE_NODE: SerovalBooleanNode = {
|
|
39
|
+
t: SerovalNodeType.Boolean,
|
|
40
|
+
i: undefined,
|
|
41
|
+
s: false,
|
|
42
|
+
l: undefined,
|
|
43
|
+
c: undefined,
|
|
44
|
+
m: undefined,
|
|
45
|
+
d: undefined,
|
|
46
|
+
a: undefined,
|
|
47
|
+
f: undefined,
|
|
48
|
+
};
|
|
49
|
+
export const UNDEFINED_NODE: SerovalUndefinedNode = {
|
|
50
|
+
t: SerovalNodeType.Undefined,
|
|
51
|
+
i: undefined,
|
|
52
|
+
s: undefined,
|
|
53
|
+
l: undefined,
|
|
54
|
+
c: undefined,
|
|
55
|
+
m: undefined,
|
|
56
|
+
d: undefined,
|
|
57
|
+
a: undefined,
|
|
58
|
+
f: undefined,
|
|
59
|
+
};
|
|
60
|
+
export const NULL_NODE: SerovalNullNode = {
|
|
61
|
+
t: SerovalNodeType.Null,
|
|
62
|
+
i: undefined,
|
|
63
|
+
s: undefined,
|
|
64
|
+
l: undefined,
|
|
65
|
+
c: undefined,
|
|
66
|
+
m: undefined,
|
|
67
|
+
d: undefined,
|
|
68
|
+
a: undefined,
|
|
69
|
+
f: undefined,
|
|
70
|
+
};
|
|
71
|
+
export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
|
|
72
|
+
t: SerovalNodeType.NegativeZero,
|
|
73
|
+
i: undefined,
|
|
74
|
+
s: undefined,
|
|
75
|
+
l: undefined,
|
|
76
|
+
c: undefined,
|
|
77
|
+
m: undefined,
|
|
78
|
+
d: undefined,
|
|
79
|
+
a: undefined,
|
|
80
|
+
f: undefined,
|
|
81
|
+
};
|
|
82
|
+
export const INFINITY_NODE: SerovalInfinityNode = {
|
|
83
|
+
t: SerovalNodeType.Infinity,
|
|
84
|
+
i: undefined,
|
|
85
|
+
s: undefined,
|
|
86
|
+
l: undefined,
|
|
87
|
+
c: undefined,
|
|
88
|
+
m: undefined,
|
|
89
|
+
d: undefined,
|
|
90
|
+
a: undefined,
|
|
91
|
+
f: undefined,
|
|
92
|
+
};
|
|
93
|
+
export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
|
|
94
|
+
t: SerovalNodeType.NegativeInfinity,
|
|
95
|
+
i: undefined,
|
|
96
|
+
s: undefined,
|
|
97
|
+
l: undefined,
|
|
98
|
+
c: undefined,
|
|
99
|
+
m: undefined,
|
|
100
|
+
d: undefined,
|
|
101
|
+
a: undefined,
|
|
102
|
+
f: undefined,
|
|
103
|
+
};
|
|
104
|
+
export const NAN_NODE: SerovalNaNNode = {
|
|
105
|
+
t: SerovalNodeType.NaN,
|
|
106
|
+
i: undefined,
|
|
107
|
+
s: undefined,
|
|
108
|
+
l: undefined,
|
|
109
|
+
c: undefined,
|
|
110
|
+
m: undefined,
|
|
111
|
+
d: undefined,
|
|
112
|
+
a: undefined,
|
|
113
|
+
f: undefined,
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export function createNumberNode(value: number): SerovalNumberNode {
|
|
19
117
|
return {
|
|
20
|
-
t: SerovalNodeType.
|
|
118
|
+
t: SerovalNodeType.Number,
|
|
21
119
|
i: undefined,
|
|
22
120
|
s: value,
|
|
23
121
|
l: undefined,
|
|
@@ -25,17 +123,23 @@ export function createPrimitiveNode(
|
|
|
25
123
|
m: undefined,
|
|
26
124
|
d: undefined,
|
|
27
125
|
a: undefined,
|
|
28
|
-
|
|
126
|
+
f: undefined,
|
|
29
127
|
};
|
|
30
128
|
}
|
|
31
129
|
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
130
|
+
export function createStringNode(value: string): SerovalStringNode {
|
|
131
|
+
return {
|
|
132
|
+
t: SerovalNodeType.String,
|
|
133
|
+
i: undefined,
|
|
134
|
+
s: quote(value),
|
|
135
|
+
l: undefined,
|
|
136
|
+
c: undefined,
|
|
137
|
+
m: undefined,
|
|
138
|
+
d: undefined,
|
|
139
|
+
a: undefined,
|
|
140
|
+
f: undefined,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
39
143
|
|
|
40
144
|
export function createBigIntNode(
|
|
41
145
|
ctx: ParserContext,
|
|
@@ -45,13 +149,13 @@ export function createBigIntNode(
|
|
|
45
149
|
return {
|
|
46
150
|
t: SerovalNodeType.BigInt,
|
|
47
151
|
i: undefined,
|
|
48
|
-
s:
|
|
152
|
+
s: '' + current,
|
|
49
153
|
l: undefined,
|
|
50
154
|
c: undefined,
|
|
51
155
|
m: undefined,
|
|
52
156
|
d: undefined,
|
|
53
157
|
a: undefined,
|
|
54
|
-
|
|
158
|
+
f: undefined,
|
|
55
159
|
};
|
|
56
160
|
}
|
|
57
161
|
|
|
@@ -65,7 +169,7 @@ export function createReferenceNode(id: number): SerovalReferenceNode {
|
|
|
65
169
|
m: undefined,
|
|
66
170
|
d: undefined,
|
|
67
171
|
a: undefined,
|
|
68
|
-
|
|
172
|
+
f: undefined,
|
|
69
173
|
};
|
|
70
174
|
}
|
|
71
175
|
|
|
@@ -78,7 +182,7 @@ export function createDateNode(id: number, current: Date): SerovalDateNode {
|
|
|
78
182
|
c: undefined,
|
|
79
183
|
m: undefined,
|
|
80
184
|
d: undefined,
|
|
81
|
-
|
|
185
|
+
f: undefined,
|
|
82
186
|
a: undefined,
|
|
83
187
|
};
|
|
84
188
|
}
|
|
@@ -87,13 +191,13 @@ export function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode
|
|
|
87
191
|
return {
|
|
88
192
|
t: SerovalNodeType.RegExp,
|
|
89
193
|
i: id,
|
|
90
|
-
s:
|
|
194
|
+
s: undefined,
|
|
91
195
|
l: undefined,
|
|
92
|
-
c:
|
|
93
|
-
m:
|
|
196
|
+
c: current.source,
|
|
197
|
+
m: current.flags,
|
|
94
198
|
d: undefined,
|
|
95
199
|
a: undefined,
|
|
96
|
-
|
|
200
|
+
f: undefined,
|
|
97
201
|
};
|
|
98
202
|
}
|
|
99
203
|
|
|
@@ -104,16 +208,21 @@ export function createTypedArrayNode(
|
|
|
104
208
|
): SerovalTypedArrayNode {
|
|
105
209
|
const constructor = current.constructor.name;
|
|
106
210
|
assert(ctx.features & Feature.TypedArray, `Unsupported value type "${constructor}"`);
|
|
211
|
+
const len = current.length;
|
|
212
|
+
const values = new Array<string>(len);
|
|
213
|
+
for (let i = 0; i < len; i++) {
|
|
214
|
+
values[i] = '' + current[i];
|
|
215
|
+
}
|
|
107
216
|
return {
|
|
108
217
|
t: SerovalNodeType.TypedArray,
|
|
109
218
|
i: id,
|
|
110
|
-
s:
|
|
219
|
+
s: values,
|
|
111
220
|
l: current.byteOffset,
|
|
112
221
|
c: constructor,
|
|
113
222
|
m: undefined,
|
|
114
223
|
d: undefined,
|
|
115
224
|
a: undefined,
|
|
116
|
-
|
|
225
|
+
f: undefined,
|
|
117
226
|
};
|
|
118
227
|
}
|
|
119
228
|
|
|
@@ -129,22 +238,36 @@ export function createBigIntTypedArrayNode(
|
|
|
129
238
|
(ctx.features & BIGINT_FLAG) === BIGINT_FLAG,
|
|
130
239
|
`Unsupported value type "${constructor}"`,
|
|
131
240
|
);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
result += current[i].toString() + 'n';
|
|
241
|
+
const len = current.length;
|
|
242
|
+
const values = new Array<string>(len);
|
|
243
|
+
for (let i = 0; i < len; i++) {
|
|
244
|
+
values[i] = '' + current[i];
|
|
138
245
|
}
|
|
139
246
|
return {
|
|
140
247
|
t: SerovalNodeType.BigIntTypedArray,
|
|
141
248
|
i: id,
|
|
142
|
-
s:
|
|
143
|
-
l:
|
|
249
|
+
s: values,
|
|
250
|
+
l: current.byteOffset,
|
|
144
251
|
c: constructor,
|
|
145
252
|
m: undefined,
|
|
146
253
|
d: undefined,
|
|
147
254
|
a: undefined,
|
|
148
|
-
|
|
255
|
+
f: undefined,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function createWKSymbolNode(
|
|
260
|
+
current: WellKnownSymbols,
|
|
261
|
+
): SerovalWKSymbolNode {
|
|
262
|
+
return {
|
|
263
|
+
t: SerovalNodeType.WKSymbol,
|
|
264
|
+
i: undefined,
|
|
265
|
+
s: INV_SYMBOL_REF[current],
|
|
266
|
+
l: undefined,
|
|
267
|
+
c: undefined,
|
|
268
|
+
m: undefined,
|
|
269
|
+
d: undefined,
|
|
270
|
+
a: undefined,
|
|
271
|
+
f: undefined,
|
|
149
272
|
};
|
|
150
273
|
}
|
package/src/tree/serialize.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
markRef,
|
|
8
8
|
} from '../context';
|
|
9
9
|
import quote from '../quote';
|
|
10
|
+
import { isValidIdentifier } from './shared';
|
|
11
|
+
import { SYMBOL_STRING } from './symbols';
|
|
10
12
|
import {
|
|
11
13
|
SerovalAggregateErrorNode,
|
|
12
14
|
SerovalArrayNode,
|
|
@@ -17,6 +19,7 @@ import {
|
|
|
17
19
|
SerovalNode,
|
|
18
20
|
SerovalNodeType,
|
|
19
21
|
SerovalNullConstructorNode,
|
|
22
|
+
SerovalObjectNode,
|
|
20
23
|
SerovalObjectRecordNode,
|
|
21
24
|
SerovalPromiseNode,
|
|
22
25
|
SerovalReferenceNode,
|
|
@@ -45,35 +48,55 @@ function mergeAssignments(assignments: Assignment[]) {
|
|
|
45
48
|
for (let i = 1, len = assignments.length; i < len; i++) {
|
|
46
49
|
item = assignments[i];
|
|
47
50
|
if (item.t === prev.t) {
|
|
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
|
-
|
|
51
|
+
switch (item.t) {
|
|
52
|
+
case 'index':
|
|
53
|
+
if (item.v === prev.v) {
|
|
54
|
+
// Merge if the right-hand value is the same
|
|
55
|
+
// saves at least 2 chars
|
|
56
|
+
current = {
|
|
57
|
+
t: 'index',
|
|
58
|
+
s: item.s,
|
|
59
|
+
k: undefined,
|
|
60
|
+
v: getAssignmentExpression(current),
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
// Different assignment, push current
|
|
64
|
+
newAssignments.push(current);
|
|
65
|
+
current = item;
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
case 'map':
|
|
69
|
+
if (item.s === prev.s) {
|
|
70
|
+
// Maps has chaining methods, merge if source is the same
|
|
71
|
+
current = {
|
|
72
|
+
t: 'map',
|
|
73
|
+
s: getAssignmentExpression(current),
|
|
74
|
+
k: item.k,
|
|
75
|
+
v: item.v,
|
|
76
|
+
};
|
|
77
|
+
} else {
|
|
78
|
+
// Different assignment, push current
|
|
79
|
+
newAssignments.push(current);
|
|
80
|
+
current = item;
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case 'set':
|
|
84
|
+
if (item.s === prev.s) {
|
|
85
|
+
// Sets has chaining methods too
|
|
86
|
+
current = {
|
|
87
|
+
t: 'set',
|
|
88
|
+
s: getAssignmentExpression(current),
|
|
89
|
+
k: undefined,
|
|
90
|
+
v: item.v,
|
|
91
|
+
};
|
|
92
|
+
} else {
|
|
93
|
+
// Different assignment, push current
|
|
94
|
+
newAssignments.push(current);
|
|
95
|
+
current = item;
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
break;
|
|
77
100
|
}
|
|
78
101
|
} else {
|
|
79
102
|
newAssignments.push(current);
|
|
@@ -158,7 +181,7 @@ function createArrayAssign(
|
|
|
158
181
|
value: string,
|
|
159
182
|
) {
|
|
160
183
|
markRef(ctx, ref);
|
|
161
|
-
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index
|
|
184
|
+
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
|
|
162
185
|
}
|
|
163
186
|
|
|
164
187
|
function createObjectAssign(
|
|
@@ -189,16 +212,14 @@ function isReferenceInStack(
|
|
|
189
212
|
return node.t === SerovalNodeType.Reference && ctx.stack.includes(node.i);
|
|
190
213
|
}
|
|
191
214
|
|
|
192
|
-
const IDENTIFIER_CHECK = /^([$A-Z_][0-9A-Z_$]*)$/i;
|
|
193
|
-
|
|
194
215
|
function serializeNodeList(
|
|
195
216
|
ctx: SerializationContext,
|
|
196
|
-
node: SerovalArrayNode | SerovalIterableNode,
|
|
217
|
+
node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
|
|
197
218
|
) {
|
|
198
219
|
// This is different than Map and Set
|
|
199
220
|
// because we also need to serialize
|
|
200
221
|
// the holes of the Array
|
|
201
|
-
const size = node.
|
|
222
|
+
const size = node.l;
|
|
202
223
|
let values = '';
|
|
203
224
|
let item: SerovalNode;
|
|
204
225
|
let isHoley = false;
|
|
@@ -222,10 +243,7 @@ function serializeNodeList(
|
|
|
222
243
|
isHoley = true;
|
|
223
244
|
}
|
|
224
245
|
}
|
|
225
|
-
|
|
226
|
-
values += ',';
|
|
227
|
-
}
|
|
228
|
-
return '[' + values + ']';
|
|
246
|
+
return '[' + values + (isHoley ? ',]' : ']');
|
|
229
247
|
}
|
|
230
248
|
|
|
231
249
|
function serializeArray(
|
|
@@ -238,7 +256,7 @@ function serializeArray(
|
|
|
238
256
|
return assignRef(ctx, node.i, result);
|
|
239
257
|
}
|
|
240
258
|
|
|
241
|
-
function
|
|
259
|
+
function serializeProperties(
|
|
242
260
|
ctx: SerializationContext,
|
|
243
261
|
sourceID: number,
|
|
244
262
|
node: SerovalObjectRecordNode,
|
|
@@ -260,20 +278,18 @@ function serializeObject(
|
|
|
260
278
|
check = Number(key);
|
|
261
279
|
// Test if key is a valid number or JS identifier
|
|
262
280
|
// so that we don't have to serialize the key and wrap with brackets
|
|
263
|
-
isIdentifier = check >= 0 ||
|
|
281
|
+
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
264
282
|
if (isReferenceInStack(ctx, val)) {
|
|
265
283
|
refParam = getRefParam(ctx, val.i);
|
|
266
284
|
if (isIdentifier && Number.isNaN(check)) {
|
|
267
285
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
268
286
|
} else {
|
|
269
|
-
createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
|
|
287
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
|
|
270
288
|
}
|
|
271
289
|
} else {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
result += isIdentifier ? key : quote(key);
|
|
276
|
-
result += ':' + serializeTree(ctx, val);
|
|
290
|
+
result += (hasPrev ? ',' : '')
|
|
291
|
+
+ (isIdentifier ? key : ('"' + quote(key) + '"'))
|
|
292
|
+
+ ':' + serializeTree(ctx, val);
|
|
277
293
|
hasPrev = true;
|
|
278
294
|
}
|
|
279
295
|
}
|
|
@@ -287,7 +303,7 @@ function serializeWithObjectAssign(
|
|
|
287
303
|
id: number,
|
|
288
304
|
serialized: string,
|
|
289
305
|
) {
|
|
290
|
-
const fields =
|
|
306
|
+
const fields = serializeProperties(ctx, id, value);
|
|
291
307
|
if (fields !== '{}') {
|
|
292
308
|
return 'Object.assign(' + serialized + ',' + fields + ')';
|
|
293
309
|
}
|
|
@@ -318,11 +334,11 @@ function serializeAssignments(
|
|
|
318
334
|
ctx.assignments = mainAssignments;
|
|
319
335
|
// Test if key is a valid number or JS identifier
|
|
320
336
|
// so that we don't have to serialize the key and wrap with brackets
|
|
321
|
-
isIdentifier = check >= 0 ||
|
|
337
|
+
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
322
338
|
if (isIdentifier && Number.isNaN(check)) {
|
|
323
339
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
324
340
|
} else {
|
|
325
|
-
createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
|
|
341
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
|
|
326
342
|
}
|
|
327
343
|
ctx.assignments = parentAssignment;
|
|
328
344
|
}
|
|
@@ -343,8 +359,7 @@ function serializeDictionary(
|
|
|
343
359
|
markRef(ctx, i);
|
|
344
360
|
const assignments = serializeAssignments(ctx, i, d);
|
|
345
361
|
if (assignments) {
|
|
346
|
-
|
|
347
|
-
return '(' + assignRef(ctx, i, init) + ',' + assignments + ref + ')';
|
|
362
|
+
return '(' + assignRef(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
|
|
348
363
|
}
|
|
349
364
|
}
|
|
350
365
|
}
|
|
@@ -358,12 +373,19 @@ function serializeNullConstructor(
|
|
|
358
373
|
return serializeDictionary(ctx, node.i, node.d, 'Object.create(null)');
|
|
359
374
|
}
|
|
360
375
|
|
|
376
|
+
function serializeObject(
|
|
377
|
+
ctx: SerializationContext,
|
|
378
|
+
node: SerovalObjectNode,
|
|
379
|
+
) {
|
|
380
|
+
return assignRef(ctx, node.i, serializeProperties(ctx, node.i, node.d));
|
|
381
|
+
}
|
|
382
|
+
|
|
361
383
|
function serializeSet(
|
|
362
384
|
ctx: SerializationContext,
|
|
363
385
|
node: SerovalSetNode,
|
|
364
386
|
) {
|
|
365
387
|
let serialized = 'new Set';
|
|
366
|
-
const size = node.
|
|
388
|
+
const size = node.l;
|
|
367
389
|
if (size) {
|
|
368
390
|
let result = '';
|
|
369
391
|
ctx.stack.push(node.i);
|
|
@@ -375,10 +397,7 @@ function serializeSet(
|
|
|
375
397
|
createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
|
|
376
398
|
} else {
|
|
377
399
|
// Push directly
|
|
378
|
-
|
|
379
|
-
result += ',';
|
|
380
|
-
}
|
|
381
|
-
result += serializeTree(ctx, item);
|
|
400
|
+
result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
|
|
382
401
|
hasPrev = true;
|
|
383
402
|
}
|
|
384
403
|
}
|
|
@@ -438,10 +457,7 @@ function serializeMap(
|
|
|
438
457
|
createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
|
|
439
458
|
ctx.stack = parent;
|
|
440
459
|
} else {
|
|
441
|
-
|
|
442
|
-
result += ',';
|
|
443
|
-
}
|
|
444
|
-
result += '[' + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
|
|
460
|
+
result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
|
|
445
461
|
hasPrev = true;
|
|
446
462
|
}
|
|
447
463
|
}
|
|
@@ -462,7 +478,7 @@ function serializeAggregateError(
|
|
|
462
478
|
) {
|
|
463
479
|
// Serialize the required arguments
|
|
464
480
|
ctx.stack.push(node.i);
|
|
465
|
-
const serialized = 'new AggregateError(' +
|
|
481
|
+
const serialized = 'new AggregateError(' + serializeNodeList(ctx, node) + ',"' + quote(node.m) + '")';
|
|
466
482
|
ctx.stack.pop();
|
|
467
483
|
// `AggregateError` might've been extended
|
|
468
484
|
// either through class or custom properties
|
|
@@ -474,7 +490,7 @@ function serializeError(
|
|
|
474
490
|
ctx: SerializationContext,
|
|
475
491
|
node: SerovalErrorNode,
|
|
476
492
|
) {
|
|
477
|
-
const serialized = 'new ' + node.c + '(' + quote(node.m) + ')';
|
|
493
|
+
const serialized = 'new ' + node.c + '("' + quote(node.m) + '")';
|
|
478
494
|
return serializeDictionary(ctx, node.i, node.d, serialized);
|
|
479
495
|
}
|
|
480
496
|
|
|
@@ -484,12 +500,12 @@ function serializePromise(
|
|
|
484
500
|
) {
|
|
485
501
|
let serialized: string;
|
|
486
502
|
// Check if resolved value is a parent expression
|
|
487
|
-
if (isReferenceInStack(ctx, node.
|
|
503
|
+
if (isReferenceInStack(ctx, node.f)) {
|
|
488
504
|
// A Promise trick, reference the value
|
|
489
505
|
// inside the `then` expression so that
|
|
490
506
|
// the Promise evaluates after the parent
|
|
491
507
|
// has initialized
|
|
492
|
-
const ref = getRefParam(ctx, node.
|
|
508
|
+
const ref = getRefParam(ctx, node.f.i);
|
|
493
509
|
if (ctx.features & Feature.ArrowFunction) {
|
|
494
510
|
serialized = 'Promise.resolve().then(()=>' + ref + ')';
|
|
495
511
|
} else {
|
|
@@ -497,7 +513,7 @@ function serializePromise(
|
|
|
497
513
|
}
|
|
498
514
|
} else {
|
|
499
515
|
ctx.stack.push(node.i);
|
|
500
|
-
const result = serializeTree(ctx, node.
|
|
516
|
+
const result = serializeTree(ctx, node.f);
|
|
501
517
|
ctx.stack.pop();
|
|
502
518
|
// just inline the value/reference here
|
|
503
519
|
serialized = 'Promise.resolve(' + result + ')';
|
|
@@ -509,10 +525,12 @@ function serializeTypedArray(
|
|
|
509
525
|
ctx: SerializationContext,
|
|
510
526
|
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
511
527
|
) {
|
|
512
|
-
let
|
|
513
|
-
|
|
514
|
-
|
|
528
|
+
let result = '';
|
|
529
|
+
const isBigInt = node.t === SerovalNodeType.BigIntTypedArray;
|
|
530
|
+
for (let i = 0, len = node.s.length; i < len; i++) {
|
|
531
|
+
result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
|
|
515
532
|
}
|
|
533
|
+
const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
|
|
516
534
|
return assignRef(ctx, node.i, 'new ' + node.c + '(' + args + ')');
|
|
517
535
|
}
|
|
518
536
|
|
|
@@ -545,22 +563,38 @@ export default function serializeTree(
|
|
|
545
563
|
node: SerovalNode,
|
|
546
564
|
): string {
|
|
547
565
|
switch (node.t) {
|
|
548
|
-
case SerovalNodeType.
|
|
549
|
-
return
|
|
566
|
+
case SerovalNodeType.Number:
|
|
567
|
+
return '' + node.s;
|
|
568
|
+
case SerovalNodeType.String:
|
|
569
|
+
return '"' + node.s + '"';
|
|
570
|
+
case SerovalNodeType.Boolean:
|
|
571
|
+
return node.s ? '!0' : '!1';
|
|
572
|
+
case SerovalNodeType.Undefined:
|
|
573
|
+
return 'void 0';
|
|
574
|
+
case SerovalNodeType.Null:
|
|
575
|
+
return 'null';
|
|
576
|
+
case SerovalNodeType.NegativeZero:
|
|
577
|
+
return '-0';
|
|
578
|
+
case SerovalNodeType.Infinity:
|
|
579
|
+
return '1/0';
|
|
580
|
+
case SerovalNodeType.NegativeInfinity:
|
|
581
|
+
return '-1/0';
|
|
582
|
+
case SerovalNodeType.NaN:
|
|
583
|
+
return 'NaN';
|
|
550
584
|
case SerovalNodeType.BigInt:
|
|
551
|
-
return node.s;
|
|
585
|
+
return node.s + 'n';
|
|
552
586
|
case SerovalNodeType.Reference:
|
|
553
587
|
return getRefParam(ctx, node.i);
|
|
554
588
|
case SerovalNodeType.Array:
|
|
555
589
|
return serializeArray(ctx, node);
|
|
556
590
|
case SerovalNodeType.Object:
|
|
557
|
-
return
|
|
591
|
+
return serializeObject(ctx, node);
|
|
558
592
|
case SerovalNodeType.NullConstructor:
|
|
559
593
|
return serializeNullConstructor(ctx, node);
|
|
560
594
|
case SerovalNodeType.Date:
|
|
561
595
|
return assignRef(ctx, node.i, 'new Date("' + node.s + '")');
|
|
562
596
|
case SerovalNodeType.RegExp:
|
|
563
|
-
return assignRef(ctx, node.i, node.
|
|
597
|
+
return assignRef(ctx, node.i, '/' + node.c + '/' + node.m);
|
|
564
598
|
case SerovalNodeType.Set:
|
|
565
599
|
return serializeSet(ctx, node);
|
|
566
600
|
case SerovalNodeType.Map:
|
|
@@ -576,6 +610,8 @@ export default function serializeTree(
|
|
|
576
610
|
return serializeIterable(ctx, node);
|
|
577
611
|
case SerovalNodeType.Promise:
|
|
578
612
|
return serializePromise(ctx, node);
|
|
613
|
+
case SerovalNodeType.WKSymbol:
|
|
614
|
+
return SYMBOL_STRING[node.s];
|
|
579
615
|
default:
|
|
580
616
|
throw new Error('Unsupported type');
|
|
581
617
|
}
|