seroval 0.6.0 → 0.8.0
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 +15 -3
- package/dist/cjs/development/index.cjs +1431 -991
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1431 -991
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/assert.d.ts +1 -1
- package/dist/types/compat.d.ts +1 -1
- package/dist/types/context.d.ts +13 -7
- package/dist/types/index.d.ts +3 -4
- package/dist/types/string.d.ts +3 -0
- package/dist/types/tree/UnsupportedTypeError.d.ts +3 -0
- package/dist/types/tree/async.d.ts +3 -3
- package/dist/types/tree/constants.d.ts +11 -0
- package/dist/types/tree/deserialize.d.ts +2 -2
- package/dist/types/tree/primitives.d.ts +11 -14
- package/dist/types/tree/serialize.d.ts +2 -2
- package/dist/types/tree/shared.d.ts +10 -8
- package/dist/types/tree/sync.d.ts +3 -3
- package/dist/types/tree/types.d.ts +106 -70
- package/dist/types/tree/web-api.d.ts +4 -2
- package/dist/types/types.d.ts +4 -4
- package/package.json +11 -8
- package/src/assert.ts +2 -2
- package/src/compat.ts +1 -2
- package/src/context.ts +24 -13
- package/src/get-identifier.ts +1 -1
- package/src/index.ts +35 -26
- package/src/string.ts +53 -0
- package/src/tree/UnsupportedTypeError.ts +8 -0
- package/src/tree/async.ts +313 -222
- package/src/tree/constants.ts +72 -0
- package/src/tree/deserialize.ts +239 -119
- package/src/tree/primitives.ts +154 -143
- package/src/tree/reference.ts +4 -3
- package/src/tree/serialize.ts +394 -170
- package/src/tree/shared.ts +31 -22
- package/src/tree/symbols.ts +13 -13
- package/src/tree/sync.ts +288 -191
- package/src/tree/types.ts +173 -91
- package/src/tree/web-api.ts +59 -6
- package/src/types.ts +7 -3
- package/dist/types/quote.d.ts +0 -2
- package/src/quote.ts +0 -56
package/src/tree/sync.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import assert from '../assert';
|
|
3
3
|
import { Feature } from '../compat';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
4
|
+
import type { ParserContext } from '../context';
|
|
5
|
+
import { createIndexedValue } from '../context';
|
|
6
|
+
import { serializeString } from '../string';
|
|
7
|
+
import type { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
8
|
+
import UnsupportedTypeError from './UnsupportedTypeError';
|
|
9
|
+
import {
|
|
10
|
+
TRUE_NODE,
|
|
11
|
+
FALSE_NODE,
|
|
12
|
+
UNDEFINED_NODE,
|
|
13
|
+
NULL_NODE,
|
|
14
|
+
} from './constants';
|
|
7
15
|
import {
|
|
8
16
|
createBigIntNode,
|
|
9
17
|
createBigIntTypedArrayNode,
|
|
@@ -13,16 +21,11 @@ import {
|
|
|
13
21
|
createRegExpNode,
|
|
14
22
|
createStringNode,
|
|
15
23
|
createTypedArrayNode,
|
|
16
|
-
createWKSymbolNode,
|
|
17
|
-
FALSE_NODE,
|
|
18
|
-
INFINITY_NODE,
|
|
19
|
-
NAN_NODE,
|
|
20
|
-
NEG_INFINITY_NODE,
|
|
21
|
-
NEG_ZERO_NODE,
|
|
22
|
-
NULL_NODE,
|
|
23
|
-
TRUE_NODE,
|
|
24
|
-
UNDEFINED_NODE,
|
|
25
24
|
createReferenceNode,
|
|
25
|
+
createArrayBufferNode,
|
|
26
|
+
createDataViewNode,
|
|
27
|
+
createSymbolNode,
|
|
28
|
+
createFunctionNode,
|
|
26
29
|
} from './primitives';
|
|
27
30
|
import {
|
|
28
31
|
hasReferenceID,
|
|
@@ -30,28 +33,33 @@ import {
|
|
|
30
33
|
import {
|
|
31
34
|
getErrorConstructorName,
|
|
32
35
|
getErrorOptions,
|
|
33
|
-
getIterableOptions,
|
|
34
36
|
isIterable,
|
|
35
37
|
} from './shared';
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
+
import type {
|
|
38
39
|
SerovalAggregateErrorNode,
|
|
39
40
|
SerovalArrayNode,
|
|
41
|
+
SerovalBoxedNode,
|
|
40
42
|
SerovalErrorNode,
|
|
41
|
-
|
|
43
|
+
SerovalFormDataNode,
|
|
44
|
+
SerovalHeadersNode,
|
|
42
45
|
SerovalMapNode,
|
|
43
46
|
SerovalNode,
|
|
44
|
-
SerovalNodeType,
|
|
45
47
|
SerovalNullConstructorNode,
|
|
46
48
|
SerovalObjectNode,
|
|
49
|
+
SerovalObjectRecordKey,
|
|
47
50
|
SerovalObjectRecordNode,
|
|
51
|
+
SerovalPlainRecordNode,
|
|
48
52
|
SerovalSetNode,
|
|
49
53
|
} from './types';
|
|
54
|
+
import {
|
|
55
|
+
SerovalNodeType,
|
|
56
|
+
SerovalObjectRecordSpecialKey,
|
|
57
|
+
} from './types';
|
|
50
58
|
import { createURLNode, createURLSearchParamsNode } from './web-api';
|
|
51
59
|
|
|
52
|
-
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode
|
|
60
|
+
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
|
|
53
61
|
|
|
54
|
-
function generateNodeList(ctx: ParserContext, current: unknown[]) {
|
|
62
|
+
function generateNodeList(ctx: ParserContext, current: unknown[]): SerovalNode[] {
|
|
55
63
|
const size = current.length;
|
|
56
64
|
const nodes = new Array<SerovalNode>(size);
|
|
57
65
|
const deferred = new Array<unknown>(size);
|
|
@@ -62,13 +70,13 @@ function generateNodeList(ctx: ParserContext, current: unknown[]) {
|
|
|
62
70
|
if (isIterable(item)) {
|
|
63
71
|
deferred[i] = item;
|
|
64
72
|
} else {
|
|
65
|
-
nodes[i] =
|
|
73
|
+
nodes[i] = parseSync(ctx, item);
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
}
|
|
69
77
|
for (let i = 0; i < size; i++) {
|
|
70
78
|
if (i in deferred) {
|
|
71
|
-
nodes[i] =
|
|
79
|
+
nodes[i] = parseSync(ctx, deferred[i]);
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
return nodes;
|
|
@@ -89,6 +97,7 @@ function generateArrayNode(
|
|
|
89
97
|
d: undefined,
|
|
90
98
|
a: generateNodeList(ctx, current),
|
|
91
99
|
f: undefined,
|
|
100
|
+
b: undefined,
|
|
92
101
|
};
|
|
93
102
|
}
|
|
94
103
|
|
|
@@ -97,7 +106,7 @@ function generateMapNode(
|
|
|
97
106
|
id: number,
|
|
98
107
|
current: Map<unknown, unknown>,
|
|
99
108
|
): SerovalMapNode {
|
|
100
|
-
assert(ctx.features & Feature.Map,
|
|
109
|
+
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
101
110
|
const len = current.size;
|
|
102
111
|
const keyNodes = new Array<SerovalNode>(len);
|
|
103
112
|
const valueNodes = new Array<SerovalNode>(len);
|
|
@@ -112,14 +121,14 @@ function generateMapNode(
|
|
|
112
121
|
deferredValue[deferredSize] = value;
|
|
113
122
|
deferredSize++;
|
|
114
123
|
} else {
|
|
115
|
-
keyNodes[nodeSize] =
|
|
116
|
-
valueNodes[nodeSize] =
|
|
124
|
+
keyNodes[nodeSize] = parseSync(ctx, key);
|
|
125
|
+
valueNodes[nodeSize] = parseSync(ctx, value);
|
|
117
126
|
nodeSize++;
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
for (let i = 0; i < deferredSize; i++) {
|
|
121
|
-
keyNodes[nodeSize + i] =
|
|
122
|
-
valueNodes[nodeSize + i] =
|
|
130
|
+
keyNodes[nodeSize + i] = parseSync(ctx, deferredKey[i]);
|
|
131
|
+
valueNodes[nodeSize + i] = parseSync(ctx, deferredValue[i]);
|
|
123
132
|
}
|
|
124
133
|
return {
|
|
125
134
|
t: SerovalNodeType.Map,
|
|
@@ -131,6 +140,7 @@ function generateMapNode(
|
|
|
131
140
|
d: { k: keyNodes, v: valueNodes, s: len },
|
|
132
141
|
a: undefined,
|
|
133
142
|
f: undefined,
|
|
143
|
+
b: undefined,
|
|
134
144
|
};
|
|
135
145
|
}
|
|
136
146
|
|
|
@@ -139,7 +149,7 @@ function generateSetNode(
|
|
|
139
149
|
id: number,
|
|
140
150
|
current: Set<unknown>,
|
|
141
151
|
): SerovalSetNode {
|
|
142
|
-
assert(ctx.features & Feature.Set,
|
|
152
|
+
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
143
153
|
const len = current.size;
|
|
144
154
|
const nodes = new Array<SerovalNode>(len);
|
|
145
155
|
const deferred = new Array<unknown>(len);
|
|
@@ -150,12 +160,12 @@ function generateSetNode(
|
|
|
150
160
|
if (isIterable(item)) {
|
|
151
161
|
deferred[deferredSize++] = item;
|
|
152
162
|
} else {
|
|
153
|
-
nodes[nodeSize++] =
|
|
163
|
+
nodes[nodeSize++] = parseSync(ctx, item);
|
|
154
164
|
}
|
|
155
165
|
}
|
|
156
166
|
// Parse deferred items
|
|
157
167
|
for (let i = 0; i < deferredSize; i++) {
|
|
158
|
-
nodes[nodeSize + i] =
|
|
168
|
+
nodes[nodeSize + i] = parseSync(ctx, deferred[i]);
|
|
159
169
|
}
|
|
160
170
|
return {
|
|
161
171
|
t: SerovalNodeType.Set,
|
|
@@ -167,6 +177,7 @@ function generateSetNode(
|
|
|
167
177
|
d: undefined,
|
|
168
178
|
a: nodes,
|
|
169
179
|
f: undefined,
|
|
180
|
+
b: undefined,
|
|
170
181
|
};
|
|
171
182
|
}
|
|
172
183
|
|
|
@@ -175,29 +186,40 @@ function generateProperties(
|
|
|
175
186
|
properties: Record<string, unknown>,
|
|
176
187
|
): SerovalObjectRecordNode {
|
|
177
188
|
const keys = Object.keys(properties);
|
|
178
|
-
|
|
179
|
-
const keyNodes = new Array<
|
|
189
|
+
let size = keys.length;
|
|
190
|
+
const keyNodes = new Array<SerovalObjectRecordKey>(size);
|
|
180
191
|
const valueNodes = new Array<SerovalNode>(size);
|
|
181
|
-
const deferredKeys = new Array<
|
|
192
|
+
const deferredKeys = new Array<SerovalObjectRecordKey>(size);
|
|
182
193
|
const deferredValues = new Array<unknown>(size);
|
|
183
194
|
let deferredSize = 0;
|
|
184
195
|
let nodesSize = 0;
|
|
185
196
|
let item: unknown;
|
|
197
|
+
let escaped: SerovalObjectRecordKey;
|
|
186
198
|
for (const key of keys) {
|
|
187
199
|
item = properties[key];
|
|
200
|
+
escaped = serializeString(key);
|
|
188
201
|
if (isIterable(item)) {
|
|
189
|
-
deferredKeys[deferredSize] =
|
|
202
|
+
deferredKeys[deferredSize] = escaped;
|
|
190
203
|
deferredValues[deferredSize] = item;
|
|
191
204
|
deferredSize++;
|
|
192
205
|
} else {
|
|
193
|
-
keyNodes[nodesSize] =
|
|
194
|
-
valueNodes[nodesSize] =
|
|
206
|
+
keyNodes[nodesSize] = escaped;
|
|
207
|
+
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
195
208
|
nodesSize++;
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
211
|
for (let i = 0; i < deferredSize; i++) {
|
|
199
212
|
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
200
|
-
valueNodes[nodesSize + i] =
|
|
213
|
+
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
214
|
+
}
|
|
215
|
+
if (ctx.features & Feature.Symbol) {
|
|
216
|
+
if (Symbol.iterator in properties) {
|
|
217
|
+
keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
|
|
218
|
+
const items = Array.from(properties as Iterable<unknown>);
|
|
219
|
+
const id = createIndexedValue(ctx, items);
|
|
220
|
+
valueNodes[size] = generateArrayNode(ctx, id, items);
|
|
221
|
+
size++;
|
|
222
|
+
}
|
|
201
223
|
}
|
|
202
224
|
return {
|
|
203
225
|
k: keyNodes,
|
|
@@ -206,39 +228,50 @@ function generateProperties(
|
|
|
206
228
|
};
|
|
207
229
|
}
|
|
208
230
|
|
|
209
|
-
function
|
|
231
|
+
function generatePlainProperties(
|
|
210
232
|
ctx: ParserContext,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
const
|
|
216
|
-
const
|
|
233
|
+
properties: Record<string, unknown>,
|
|
234
|
+
): SerovalPlainRecordNode {
|
|
235
|
+
const keys = Object.keys(properties);
|
|
236
|
+
const size = keys.length;
|
|
237
|
+
const keyNodes = new Array<string>(size);
|
|
238
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
239
|
+
const deferredKeys = new Array<string>(size);
|
|
240
|
+
const deferredValues = new Array<unknown>(size);
|
|
241
|
+
let deferredSize = 0;
|
|
242
|
+
let nodesSize = 0;
|
|
243
|
+
let item: unknown;
|
|
244
|
+
let escaped: string;
|
|
245
|
+
for (const key of keys) {
|
|
246
|
+
item = properties[key];
|
|
247
|
+
escaped = serializeString(key);
|
|
248
|
+
if (isIterable(item)) {
|
|
249
|
+
deferredKeys[deferredSize] = escaped;
|
|
250
|
+
deferredValues[deferredSize] = item;
|
|
251
|
+
deferredSize++;
|
|
252
|
+
} else {
|
|
253
|
+
keyNodes[nodesSize] = escaped;
|
|
254
|
+
valueNodes[nodesSize] = parseSync(ctx, item);
|
|
255
|
+
nodesSize++;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
259
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
260
|
+
valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
|
|
261
|
+
}
|
|
217
262
|
return {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
s:
|
|
221
|
-
l: array.length,
|
|
222
|
-
c: undefined,
|
|
223
|
-
m: undefined,
|
|
224
|
-
// Parse options first before the items
|
|
225
|
-
d: options
|
|
226
|
-
? generateProperties(ctx, options)
|
|
227
|
-
: undefined,
|
|
228
|
-
a: generateNodeList(ctx, array),
|
|
229
|
-
f: undefined,
|
|
263
|
+
k: keyNodes,
|
|
264
|
+
v: valueNodes,
|
|
265
|
+
s: size,
|
|
230
266
|
};
|
|
231
267
|
}
|
|
232
268
|
|
|
233
269
|
function generateObjectNode(
|
|
234
270
|
ctx: ParserContext,
|
|
235
271
|
id: number,
|
|
236
|
-
current: Record<string, unknown
|
|
272
|
+
current: Record<string, unknown>,
|
|
237
273
|
empty: boolean,
|
|
238
274
|
): ObjectLikeNode {
|
|
239
|
-
if (Symbol.iterator in current) {
|
|
240
|
-
return generateIterableNode(ctx, id, current);
|
|
241
|
-
}
|
|
242
275
|
return {
|
|
243
276
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
244
277
|
i: id,
|
|
@@ -249,6 +282,7 @@ function generateObjectNode(
|
|
|
249
282
|
d: generateProperties(ctx, current),
|
|
250
283
|
a: undefined,
|
|
251
284
|
f: undefined,
|
|
285
|
+
b: undefined,
|
|
252
286
|
};
|
|
253
287
|
}
|
|
254
288
|
|
|
@@ -265,12 +299,13 @@ function generateAggregateErrorNode(
|
|
|
265
299
|
t: SerovalNodeType.AggregateError,
|
|
266
300
|
i: id,
|
|
267
301
|
s: undefined,
|
|
268
|
-
l:
|
|
302
|
+
l: undefined,
|
|
269
303
|
c: undefined,
|
|
270
|
-
m:
|
|
304
|
+
m: serializeString(current.message),
|
|
271
305
|
d: optionsNode,
|
|
272
|
-
a:
|
|
306
|
+
a: undefined,
|
|
273
307
|
f: undefined,
|
|
308
|
+
b: undefined,
|
|
274
309
|
};
|
|
275
310
|
}
|
|
276
311
|
|
|
@@ -289,14 +324,196 @@ function generateErrorNode(
|
|
|
289
324
|
s: undefined,
|
|
290
325
|
l: undefined,
|
|
291
326
|
c: getErrorConstructorName(current),
|
|
292
|
-
m:
|
|
327
|
+
m: serializeString(current.message),
|
|
293
328
|
d: optionsNode,
|
|
294
329
|
a: undefined,
|
|
295
330
|
f: undefined,
|
|
331
|
+
b: undefined,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function generateHeadersNode(
|
|
336
|
+
ctx: ParserContext,
|
|
337
|
+
id: number,
|
|
338
|
+
current: Headers,
|
|
339
|
+
): SerovalHeadersNode {
|
|
340
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
341
|
+
const items: Record<string, string> = {};
|
|
342
|
+
// TS Headers not an Iterable
|
|
343
|
+
current.forEach((value, key) => {
|
|
344
|
+
items[key] = value;
|
|
345
|
+
});
|
|
346
|
+
return {
|
|
347
|
+
t: SerovalNodeType.Headers,
|
|
348
|
+
i: id,
|
|
349
|
+
s: undefined,
|
|
350
|
+
l: undefined,
|
|
351
|
+
c: undefined,
|
|
352
|
+
m: undefined,
|
|
353
|
+
d: generatePlainProperties(ctx, items),
|
|
354
|
+
a: undefined,
|
|
355
|
+
f: undefined,
|
|
356
|
+
b: undefined,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function generateFormDataNode(
|
|
361
|
+
ctx: ParserContext,
|
|
362
|
+
id: number,
|
|
363
|
+
current: FormData,
|
|
364
|
+
): SerovalFormDataNode {
|
|
365
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
366
|
+
const items: Record<string, FormDataEntryValue> = {};
|
|
367
|
+
// TS FormData isn't an Iterable sadly
|
|
368
|
+
current.forEach((value, key) => {
|
|
369
|
+
items[key] = value;
|
|
370
|
+
});
|
|
371
|
+
return {
|
|
372
|
+
t: SerovalNodeType.FormData,
|
|
373
|
+
i: id,
|
|
374
|
+
s: undefined,
|
|
375
|
+
l: undefined,
|
|
376
|
+
c: undefined,
|
|
377
|
+
m: undefined,
|
|
378
|
+
d: generatePlainProperties(ctx, items),
|
|
379
|
+
a: undefined,
|
|
380
|
+
f: undefined,
|
|
381
|
+
b: undefined,
|
|
296
382
|
};
|
|
297
383
|
}
|
|
298
384
|
|
|
299
|
-
function
|
|
385
|
+
function generateBoxedNode(
|
|
386
|
+
ctx: ParserContext,
|
|
387
|
+
id: number,
|
|
388
|
+
current: object,
|
|
389
|
+
): SerovalBoxedNode {
|
|
390
|
+
return {
|
|
391
|
+
t: SerovalNodeType.Boxed,
|
|
392
|
+
i: id,
|
|
393
|
+
s: undefined,
|
|
394
|
+
l: undefined,
|
|
395
|
+
c: undefined,
|
|
396
|
+
m: undefined,
|
|
397
|
+
d: undefined,
|
|
398
|
+
a: undefined,
|
|
399
|
+
f: parseSync(ctx, current.valueOf()),
|
|
400
|
+
b: undefined,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function parseObject(
|
|
405
|
+
ctx: ParserContext,
|
|
406
|
+
current: object | null,
|
|
407
|
+
): SerovalNode {
|
|
408
|
+
if (!current) {
|
|
409
|
+
return NULL_NODE;
|
|
410
|
+
}
|
|
411
|
+
// Non-primitive values needs a reference ID
|
|
412
|
+
// mostly because the values themselves are stateful
|
|
413
|
+
const id = createIndexedValue(ctx, current);
|
|
414
|
+
if (ctx.markedRefs.has(id)) {
|
|
415
|
+
return createIndexedValueNode(id);
|
|
416
|
+
}
|
|
417
|
+
if (hasReferenceID(current)) {
|
|
418
|
+
return createReferenceNode(id, current);
|
|
419
|
+
}
|
|
420
|
+
// Well well well
|
|
421
|
+
if (Array.isArray(current)) {
|
|
422
|
+
return generateArrayNode(ctx, id, current);
|
|
423
|
+
}
|
|
424
|
+
// Fast path
|
|
425
|
+
switch (current.constructor) {
|
|
426
|
+
case Number:
|
|
427
|
+
case Boolean:
|
|
428
|
+
case String:
|
|
429
|
+
case BigInt:
|
|
430
|
+
case Function:
|
|
431
|
+
case Symbol:
|
|
432
|
+
return generateBoxedNode(ctx, id, current);
|
|
433
|
+
case Date:
|
|
434
|
+
return createDateNode(id, current as unknown as Date);
|
|
435
|
+
case RegExp:
|
|
436
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
437
|
+
case ArrayBuffer:
|
|
438
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
439
|
+
case Int8Array:
|
|
440
|
+
case Int16Array:
|
|
441
|
+
case Int32Array:
|
|
442
|
+
case Uint8Array:
|
|
443
|
+
case Uint16Array:
|
|
444
|
+
case Uint32Array:
|
|
445
|
+
case Uint8ClampedArray:
|
|
446
|
+
case Float32Array:
|
|
447
|
+
case Float64Array:
|
|
448
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
449
|
+
case BigInt64Array:
|
|
450
|
+
case BigUint64Array:
|
|
451
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
452
|
+
case DataView:
|
|
453
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
454
|
+
case Map:
|
|
455
|
+
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
456
|
+
case Set:
|
|
457
|
+
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
458
|
+
case Object:
|
|
459
|
+
return generateObjectNode(
|
|
460
|
+
ctx,
|
|
461
|
+
id,
|
|
462
|
+
current as unknown as Record<string, unknown>,
|
|
463
|
+
false,
|
|
464
|
+
);
|
|
465
|
+
case undefined:
|
|
466
|
+
return generateObjectNode(
|
|
467
|
+
ctx,
|
|
468
|
+
id,
|
|
469
|
+
current as unknown as Record<string, unknown>,
|
|
470
|
+
true,
|
|
471
|
+
);
|
|
472
|
+
case AggregateError:
|
|
473
|
+
// Compile-down AggregateError to Error if disabled
|
|
474
|
+
if (ctx.features & Feature.AggregateError) {
|
|
475
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
476
|
+
}
|
|
477
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
478
|
+
case Error:
|
|
479
|
+
case EvalError:
|
|
480
|
+
case RangeError:
|
|
481
|
+
case ReferenceError:
|
|
482
|
+
case SyntaxError:
|
|
483
|
+
case TypeError:
|
|
484
|
+
case URIError:
|
|
485
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
486
|
+
case URL:
|
|
487
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
488
|
+
case URLSearchParams:
|
|
489
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
490
|
+
case Headers:
|
|
491
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
492
|
+
case FormData:
|
|
493
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
494
|
+
default:
|
|
495
|
+
break;
|
|
496
|
+
}
|
|
497
|
+
// Slow path. We only need to handle Errors and Iterators
|
|
498
|
+
// since they have very broad implementations.
|
|
499
|
+
if (current instanceof AggregateError) {
|
|
500
|
+
if (ctx.features & Feature.AggregateError) {
|
|
501
|
+
return generateAggregateErrorNode(ctx, id, current);
|
|
502
|
+
}
|
|
503
|
+
return generateErrorNode(ctx, id, current);
|
|
504
|
+
}
|
|
505
|
+
if (current instanceof Error) {
|
|
506
|
+
return generateErrorNode(ctx, id, current);
|
|
507
|
+
}
|
|
508
|
+
// Generator functions don't have a global constructor
|
|
509
|
+
// despite existing
|
|
510
|
+
if (Symbol.iterator in current) {
|
|
511
|
+
return generateObjectNode(ctx, id, current, !!current.constructor);
|
|
512
|
+
}
|
|
513
|
+
throw new UnsupportedTypeError(current);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export default function parseSync<T>(
|
|
300
517
|
ctx: ParserContext,
|
|
301
518
|
current: T,
|
|
302
519
|
): SerovalNode {
|
|
@@ -308,136 +525,16 @@ function parse<T>(
|
|
|
308
525
|
case 'string':
|
|
309
526
|
return createStringNode(current);
|
|
310
527
|
case 'number':
|
|
311
|
-
|
|
312
|
-
case Infinity: return INFINITY_NODE;
|
|
313
|
-
case -Infinity: return NEG_INFINITY_NODE;
|
|
314
|
-
default:
|
|
315
|
-
// eslint-disable-next-line no-self-compare
|
|
316
|
-
if (current !== current) {
|
|
317
|
-
return NAN_NODE;
|
|
318
|
-
}
|
|
319
|
-
if (Object.is(current, -0)) {
|
|
320
|
-
return NEG_ZERO_NODE;
|
|
321
|
-
}
|
|
322
|
-
return createNumberNode(current);
|
|
323
|
-
}
|
|
528
|
+
return createNumberNode(current);
|
|
324
529
|
case 'bigint':
|
|
325
530
|
return createBigIntNode(ctx, current);
|
|
326
|
-
case 'object':
|
|
327
|
-
|
|
328
|
-
return NULL_NODE;
|
|
329
|
-
}
|
|
330
|
-
// Non-primitive values needs a reference ID
|
|
331
|
-
// mostly because the values themselves are stateful
|
|
332
|
-
const id = createIndexedValue(ctx, current);
|
|
333
|
-
if (ctx.markedRefs.has(id)) {
|
|
334
|
-
return createIndexedValueNode(id);
|
|
335
|
-
}
|
|
336
|
-
if (hasReferenceID(current)) {
|
|
337
|
-
return createReferenceNode(id, current);
|
|
338
|
-
}
|
|
339
|
-
if (Array.isArray(current)) {
|
|
340
|
-
return generateArrayNode(ctx, id, current);
|
|
341
|
-
}
|
|
342
|
-
switch (current.constructor) {
|
|
343
|
-
case Date:
|
|
344
|
-
return createDateNode(id, current as unknown as Date);
|
|
345
|
-
case RegExp:
|
|
346
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
347
|
-
case Int8Array:
|
|
348
|
-
case Int16Array:
|
|
349
|
-
case Int32Array:
|
|
350
|
-
case Uint8Array:
|
|
351
|
-
case Uint16Array:
|
|
352
|
-
case Uint32Array:
|
|
353
|
-
case Uint8ClampedArray:
|
|
354
|
-
case Float32Array:
|
|
355
|
-
case Float64Array:
|
|
356
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
357
|
-
case BigInt64Array:
|
|
358
|
-
case BigUint64Array:
|
|
359
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
360
|
-
case Map:
|
|
361
|
-
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
362
|
-
case Set:
|
|
363
|
-
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
364
|
-
case Object:
|
|
365
|
-
return generateObjectNode(
|
|
366
|
-
ctx,
|
|
367
|
-
id,
|
|
368
|
-
current as unknown as Record<string, unknown>,
|
|
369
|
-
false,
|
|
370
|
-
);
|
|
371
|
-
case undefined:
|
|
372
|
-
return generateObjectNode(
|
|
373
|
-
ctx,
|
|
374
|
-
id,
|
|
375
|
-
current as unknown as Record<string, unknown>,
|
|
376
|
-
true,
|
|
377
|
-
);
|
|
378
|
-
case AggregateError:
|
|
379
|
-
if (ctx.features & Feature.AggregateError) {
|
|
380
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
381
|
-
}
|
|
382
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
383
|
-
case Error:
|
|
384
|
-
case EvalError:
|
|
385
|
-
case RangeError:
|
|
386
|
-
case ReferenceError:
|
|
387
|
-
case SyntaxError:
|
|
388
|
-
case TypeError:
|
|
389
|
-
case URIError:
|
|
390
|
-
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
391
|
-
case URL:
|
|
392
|
-
return createURLNode(ctx, id, current as unknown as URL);
|
|
393
|
-
case URLSearchParams:
|
|
394
|
-
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
395
|
-
default:
|
|
396
|
-
break;
|
|
397
|
-
}
|
|
398
|
-
if (current instanceof AggregateError) {
|
|
399
|
-
if (ctx.features & Feature.AggregateError) {
|
|
400
|
-
return generateAggregateErrorNode(ctx, id, current);
|
|
401
|
-
}
|
|
402
|
-
return generateErrorNode(ctx, id, current);
|
|
403
|
-
}
|
|
404
|
-
if (current instanceof Error) {
|
|
405
|
-
return generateErrorNode(ctx, id, current);
|
|
406
|
-
}
|
|
407
|
-
// Generator functions don't have a global constructor
|
|
408
|
-
if (Symbol.iterator in current) {
|
|
409
|
-
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
410
|
-
}
|
|
411
|
-
throw new Error('Unsupported type');
|
|
412
|
-
}
|
|
531
|
+
case 'object':
|
|
532
|
+
return parseObject(ctx, current);
|
|
413
533
|
case 'symbol':
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
return createIndexedValueNode(id);
|
|
418
|
-
}
|
|
419
|
-
return createReferenceNode(id, current);
|
|
420
|
-
}
|
|
421
|
-
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
422
|
-
case 'function': {
|
|
423
|
-
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
424
|
-
const id = createIndexedValue(ctx, current);
|
|
425
|
-
if (ctx.markedRefs.has(id)) {
|
|
426
|
-
return createIndexedValueNode(id);
|
|
427
|
-
}
|
|
428
|
-
return createReferenceNode(id, current);
|
|
429
|
-
}
|
|
534
|
+
return createSymbolNode(ctx, current);
|
|
535
|
+
case 'function':
|
|
536
|
+
return createFunctionNode(ctx, current);
|
|
430
537
|
default:
|
|
431
|
-
throw new
|
|
538
|
+
throw new UnsupportedTypeError(current);
|
|
432
539
|
}
|
|
433
540
|
}
|
|
434
|
-
|
|
435
|
-
export default function parseSync<T>(
|
|
436
|
-
ctx: ParserContext,
|
|
437
|
-
current: T,
|
|
438
|
-
) {
|
|
439
|
-
const result = parse(ctx, current);
|
|
440
|
-
const isObject = result.t === SerovalNodeType.Object
|
|
441
|
-
|| result.t === SerovalNodeType.Iterable;
|
|
442
|
-
return [result, getRootID(ctx, current), isObject] as const;
|
|
443
|
-
}
|