seroval 0.7.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/dist/cjs/development/index.cjs +1109 -1039
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1109 -1039
- 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/context.d.ts +2 -2
- package/dist/types/index.d.ts +3 -4
- package/dist/types/string.d.ts +1 -1
- 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 +9 -15
- 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 +64 -71
- package/dist/types/tree/web-api.d.ts +2 -2
- package/dist/types/types.d.ts +4 -4
- package/package.json +10 -8
- package/src/assert.ts +2 -2
- package/src/compat.ts +0 -1
- package/src/context.ts +10 -7
- package/src/get-identifier.ts +1 -1
- package/src/index.ts +35 -26
- package/src/string.ts +2 -2
- package/src/tree/UnsupportedTypeError.ts +8 -0
- package/src/tree/async.ts +245 -233
- package/src/tree/constants.ts +72 -0
- package/src/tree/deserialize.ts +96 -93
- package/src/tree/primitives.ts +81 -134
- package/src/tree/reference.ts +4 -3
- package/src/tree/serialize.ts +251 -197
- package/src/tree/shared.ts +31 -22
- package/src/tree/symbols.ts +13 -13
- package/src/tree/sync.ts +226 -198
- package/src/tree/types.ts +74 -93
- package/src/tree/web-api.ts +10 -7
- package/src/types.ts +7 -3
package/src/tree/async.ts
CHANGED
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
3
3
|
import assert from '../assert';
|
|
4
4
|
import { Feature } from '../compat';
|
|
5
|
-
import {
|
|
6
|
-
import { serializeString } from '../string';
|
|
5
|
+
import type { ParserContext } from '../context';
|
|
7
6
|
import {
|
|
7
|
+
createIndexedValue,
|
|
8
|
+
} from '../context';
|
|
9
|
+
import { serializeString } from '../string';
|
|
10
|
+
import type {
|
|
8
11
|
BigIntTypedArrayValue,
|
|
9
12
|
TypedArrayValue,
|
|
10
13
|
} from '../types';
|
|
14
|
+
import UnsupportedTypeError from './UnsupportedTypeError';
|
|
15
|
+
import {
|
|
16
|
+
TRUE_NODE,
|
|
17
|
+
FALSE_NODE,
|
|
18
|
+
UNDEFINED_NODE,
|
|
19
|
+
NULL_NODE,
|
|
20
|
+
} from './constants';
|
|
11
21
|
import {
|
|
12
22
|
createBigIntNode,
|
|
13
23
|
createBigIntTypedArrayNode,
|
|
@@ -17,43 +27,39 @@ import {
|
|
|
17
27
|
createRegExpNode,
|
|
18
28
|
createStringNode,
|
|
19
29
|
createTypedArrayNode,
|
|
20
|
-
createWKSymbolNode,
|
|
21
|
-
FALSE_NODE,
|
|
22
|
-
INFINITY_NODE,
|
|
23
|
-
NAN_NODE,
|
|
24
|
-
NEG_INFINITY_NODE,
|
|
25
|
-
NEG_ZERO_NODE,
|
|
26
|
-
NULL_NODE,
|
|
27
|
-
TRUE_NODE,
|
|
28
|
-
UNDEFINED_NODE,
|
|
29
30
|
createReferenceNode,
|
|
30
31
|
createArrayBufferNode,
|
|
31
32
|
createDataViewNode,
|
|
33
|
+
createSymbolNode,
|
|
34
|
+
createFunctionNode,
|
|
32
35
|
} from './primitives';
|
|
33
36
|
import { hasReferenceID } from './reference';
|
|
34
37
|
import {
|
|
35
38
|
getErrorConstructorName,
|
|
36
39
|
getErrorOptions,
|
|
37
|
-
getIterableOptions,
|
|
38
40
|
isIterable,
|
|
39
41
|
} from './shared';
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
+
import type {
|
|
42
43
|
SerovalAggregateErrorNode,
|
|
43
44
|
SerovalArrayNode,
|
|
45
|
+
SerovalBoxedNode,
|
|
44
46
|
SerovalErrorNode,
|
|
45
47
|
SerovalFormDataNode,
|
|
46
48
|
SerovalHeadersNode,
|
|
47
|
-
SerovalIterableNode,
|
|
48
49
|
SerovalMapNode,
|
|
49
50
|
SerovalNode,
|
|
50
|
-
SerovalNodeType,
|
|
51
51
|
SerovalNullConstructorNode,
|
|
52
52
|
SerovalObjectNode,
|
|
53
|
+
SerovalObjectRecordKey,
|
|
53
54
|
SerovalObjectRecordNode,
|
|
55
|
+
SerovalPlainRecordNode,
|
|
54
56
|
SerovalPromiseNode,
|
|
55
57
|
SerovalSetNode,
|
|
56
58
|
} from './types';
|
|
59
|
+
import {
|
|
60
|
+
SerovalNodeType,
|
|
61
|
+
SerovalObjectRecordSpecialKey,
|
|
62
|
+
} from './types';
|
|
57
63
|
import {
|
|
58
64
|
createBlobNode,
|
|
59
65
|
createFileNode,
|
|
@@ -64,18 +70,12 @@ import {
|
|
|
64
70
|
type ObjectLikeNode =
|
|
65
71
|
| SerovalObjectNode
|
|
66
72
|
| SerovalNullConstructorNode
|
|
67
|
-
| SerovalIterableNode
|
|
68
73
|
| SerovalPromiseNode;
|
|
69
74
|
|
|
70
|
-
type ObjectLikeValue =
|
|
71
|
-
| Record<string, unknown>
|
|
72
|
-
| Iterable<unknown>
|
|
73
|
-
| PromiseLike<unknown>;
|
|
74
|
-
|
|
75
75
|
async function generateNodeList(
|
|
76
76
|
ctx: ParserContext,
|
|
77
77
|
current: unknown[],
|
|
78
|
-
) {
|
|
78
|
+
): Promise<SerovalNode[]> {
|
|
79
79
|
const size = current.length;
|
|
80
80
|
const nodes = new Array<SerovalNode>(size);
|
|
81
81
|
const deferred = new Array<unknown>(size);
|
|
@@ -86,13 +86,13 @@ async function generateNodeList(
|
|
|
86
86
|
if (isIterable(item)) {
|
|
87
87
|
deferred[i] = item;
|
|
88
88
|
} else {
|
|
89
|
-
nodes[i] = await
|
|
89
|
+
nodes[i] = await parseAsync(ctx, item);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
for (let i = 0; i < size; i++) {
|
|
94
94
|
if (i in deferred) {
|
|
95
|
-
nodes[i] = await
|
|
95
|
+
nodes[i] = await parseAsync(ctx, deferred[i]);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
return nodes;
|
|
@@ -122,7 +122,7 @@ async function generateMapNode(
|
|
|
122
122
|
id: number,
|
|
123
123
|
current: Map<unknown, unknown>,
|
|
124
124
|
): Promise<SerovalMapNode> {
|
|
125
|
-
assert(ctx.features & Feature.Map,
|
|
125
|
+
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
126
126
|
const len = current.size;
|
|
127
127
|
const keyNodes = new Array<SerovalNode>(len);
|
|
128
128
|
const valueNodes = new Array<SerovalNode>(len);
|
|
@@ -137,14 +137,14 @@ async function generateMapNode(
|
|
|
137
137
|
deferredValue[deferredSize] = value;
|
|
138
138
|
deferredSize++;
|
|
139
139
|
} else {
|
|
140
|
-
keyNodes[nodeSize] = await
|
|
141
|
-
valueNodes[nodeSize] = await
|
|
140
|
+
keyNodes[nodeSize] = await parseAsync(ctx, key);
|
|
141
|
+
valueNodes[nodeSize] = await parseAsync(ctx, value);
|
|
142
142
|
nodeSize++;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
for (let i = 0; i < deferredSize; i++) {
|
|
146
|
-
keyNodes[nodeSize + i] = await
|
|
147
|
-
valueNodes[nodeSize + i] = await
|
|
146
|
+
keyNodes[nodeSize + i] = await parseAsync(ctx, deferredKey[i]);
|
|
147
|
+
valueNodes[nodeSize + i] = await parseAsync(ctx, deferredValue[i]);
|
|
148
148
|
}
|
|
149
149
|
return {
|
|
150
150
|
t: SerovalNodeType.Map,
|
|
@@ -165,7 +165,7 @@ async function generateSetNode(
|
|
|
165
165
|
id: number,
|
|
166
166
|
current: Set<unknown>,
|
|
167
167
|
): Promise<SerovalSetNode> {
|
|
168
|
-
assert(ctx.features & Feature.Set,
|
|
168
|
+
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
169
169
|
const len = current.size;
|
|
170
170
|
const nodes = new Array<SerovalNode>(len);
|
|
171
171
|
const deferred = new Array<unknown>(len);
|
|
@@ -176,12 +176,12 @@ async function generateSetNode(
|
|
|
176
176
|
if (isIterable(item)) {
|
|
177
177
|
deferred[deferredSize++] = item;
|
|
178
178
|
} else {
|
|
179
|
-
nodes[nodeSize++] = await
|
|
179
|
+
nodes[nodeSize++] = await parseAsync(ctx, item);
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
// Parse deferred items
|
|
183
183
|
for (let i = 0; i < deferredSize; i++) {
|
|
184
|
-
nodes[nodeSize + i] = await
|
|
184
|
+
nodes[nodeSize + i] = await parseAsync(ctx, deferred[i]);
|
|
185
185
|
}
|
|
186
186
|
return {
|
|
187
187
|
t: SerovalNodeType.Set,
|
|
@@ -202,15 +202,15 @@ async function generateProperties(
|
|
|
202
202
|
properties: Record<string, unknown>,
|
|
203
203
|
): Promise<SerovalObjectRecordNode> {
|
|
204
204
|
const keys = Object.keys(properties);
|
|
205
|
-
|
|
206
|
-
const keyNodes = new Array<
|
|
205
|
+
let size = keys.length;
|
|
206
|
+
const keyNodes = new Array<SerovalObjectRecordKey>(size);
|
|
207
207
|
const valueNodes = new Array<SerovalNode>(size);
|
|
208
|
-
const deferredKeys = new Array<
|
|
208
|
+
const deferredKeys = new Array<SerovalObjectRecordKey>(size);
|
|
209
209
|
const deferredValues = new Array<unknown>(size);
|
|
210
210
|
let deferredSize = 0;
|
|
211
211
|
let nodesSize = 0;
|
|
212
212
|
let item: unknown;
|
|
213
|
-
let escaped:
|
|
213
|
+
let escaped: SerovalObjectRecordKey;
|
|
214
214
|
for (const key of keys) {
|
|
215
215
|
item = properties[key];
|
|
216
216
|
escaped = serializeString(key);
|
|
@@ -220,13 +220,25 @@ async function generateProperties(
|
|
|
220
220
|
deferredSize++;
|
|
221
221
|
} else {
|
|
222
222
|
keyNodes[nodesSize] = escaped;
|
|
223
|
-
valueNodes[nodesSize] = await
|
|
223
|
+
valueNodes[nodesSize] = await parseAsync(ctx, item);
|
|
224
224
|
nodesSize++;
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
for (let i = 0; i < deferredSize; i++) {
|
|
228
228
|
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
229
|
-
valueNodes[nodesSize + i] = await
|
|
229
|
+
valueNodes[nodesSize + i] = await parseAsync(ctx, deferredValues[i]);
|
|
230
|
+
}
|
|
231
|
+
if (ctx.features & Feature.Symbol) {
|
|
232
|
+
if (Symbol.iterator in properties) {
|
|
233
|
+
keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
|
|
234
|
+
const items = Array.from(properties as Iterable<unknown>);
|
|
235
|
+
valueNodes[size] = await generateArrayNode(
|
|
236
|
+
ctx,
|
|
237
|
+
createIndexedValue(ctx, items),
|
|
238
|
+
items,
|
|
239
|
+
);
|
|
240
|
+
size++;
|
|
241
|
+
}
|
|
230
242
|
}
|
|
231
243
|
return {
|
|
232
244
|
k: keyNodes,
|
|
@@ -235,38 +247,51 @@ async function generateProperties(
|
|
|
235
247
|
};
|
|
236
248
|
}
|
|
237
249
|
|
|
238
|
-
async function
|
|
250
|
+
async function generatePlainProperties(
|
|
239
251
|
ctx: ParserContext,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
const
|
|
252
|
+
properties: Record<string, unknown>,
|
|
253
|
+
): Promise<SerovalPlainRecordNode> {
|
|
254
|
+
const keys = Object.keys(properties);
|
|
255
|
+
const size = keys.length;
|
|
256
|
+
const keyNodes = new Array<string>(size);
|
|
257
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
258
|
+
const deferredKeys = new Array<string>(size);
|
|
259
|
+
const deferredValues = new Array<unknown>(size);
|
|
260
|
+
let deferredSize = 0;
|
|
261
|
+
let nodesSize = 0;
|
|
262
|
+
let item: unknown;
|
|
263
|
+
let escaped: string;
|
|
264
|
+
for (const key of keys) {
|
|
265
|
+
item = properties[key];
|
|
266
|
+
escaped = serializeString(key);
|
|
267
|
+
if (isIterable(item)) {
|
|
268
|
+
deferredKeys[deferredSize] = escaped;
|
|
269
|
+
deferredValues[deferredSize] = item;
|
|
270
|
+
deferredSize++;
|
|
271
|
+
} else {
|
|
272
|
+
keyNodes[nodesSize] = escaped;
|
|
273
|
+
valueNodes[nodesSize] = await parseAsync(ctx, item);
|
|
274
|
+
nodesSize++;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
278
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
279
|
+
valueNodes[nodesSize + i] = await parseAsync(ctx, deferredValues[i]);
|
|
280
|
+
}
|
|
246
281
|
return {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
s:
|
|
250
|
-
l: array.length,
|
|
251
|
-
c: undefined,
|
|
252
|
-
m: undefined,
|
|
253
|
-
// Parse options first before the items
|
|
254
|
-
d: options
|
|
255
|
-
? await generateProperties(ctx, options)
|
|
256
|
-
: undefined,
|
|
257
|
-
a: await generateNodeList(ctx, array),
|
|
258
|
-
f: undefined,
|
|
259
|
-
b: undefined,
|
|
282
|
+
k: keyNodes,
|
|
283
|
+
v: valueNodes,
|
|
284
|
+
s: size,
|
|
260
285
|
};
|
|
261
286
|
}
|
|
262
287
|
|
|
263
288
|
async function generatePromiseNode(
|
|
264
289
|
ctx: ParserContext,
|
|
265
290
|
id: number,
|
|
266
|
-
current:
|
|
291
|
+
current: Promise<unknown>,
|
|
267
292
|
): Promise<SerovalPromiseNode> {
|
|
268
|
-
assert(ctx.features & Feature.Promise,
|
|
269
|
-
return
|
|
293
|
+
assert(ctx.features & Feature.Promise, new UnsupportedTypeError(current));
|
|
294
|
+
return {
|
|
270
295
|
t: SerovalNodeType.Promise,
|
|
271
296
|
i: id,
|
|
272
297
|
s: undefined,
|
|
@@ -276,23 +301,17 @@ async function generatePromiseNode(
|
|
|
276
301
|
// Parse options first before the items
|
|
277
302
|
d: undefined,
|
|
278
303
|
a: undefined,
|
|
279
|
-
f: await
|
|
304
|
+
f: await parseAsync(ctx, await current),
|
|
280
305
|
b: undefined,
|
|
281
|
-
}
|
|
306
|
+
};
|
|
282
307
|
}
|
|
283
308
|
|
|
284
309
|
async function generateObjectNode(
|
|
285
310
|
ctx: ParserContext,
|
|
286
311
|
id: number,
|
|
287
|
-
current:
|
|
312
|
+
current: Record<string, unknown>,
|
|
288
313
|
empty: boolean,
|
|
289
314
|
): Promise<ObjectLikeNode> {
|
|
290
|
-
if (Symbol.iterator in current) {
|
|
291
|
-
return generateIterableNode(ctx, id, current);
|
|
292
|
-
}
|
|
293
|
-
if ('then' in current && typeof current.then === 'function') {
|
|
294
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
295
|
-
}
|
|
296
315
|
return {
|
|
297
316
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
298
317
|
i: id,
|
|
@@ -300,7 +319,7 @@ async function generateObjectNode(
|
|
|
300
319
|
l: undefined,
|
|
301
320
|
c: undefined,
|
|
302
321
|
m: undefined,
|
|
303
|
-
d: await generateProperties(ctx, current
|
|
322
|
+
d: await generateProperties(ctx, current),
|
|
304
323
|
a: undefined,
|
|
305
324
|
f: undefined,
|
|
306
325
|
b: undefined,
|
|
@@ -358,7 +377,7 @@ async function generateHeadersNode(
|
|
|
358
377
|
id: number,
|
|
359
378
|
current: Headers,
|
|
360
379
|
): Promise<SerovalHeadersNode> {
|
|
361
|
-
assert(ctx.features & Feature.WebAPI,
|
|
380
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
362
381
|
const items: Record<string, string> = {};
|
|
363
382
|
current.forEach((value, key) => {
|
|
364
383
|
items[key] = value;
|
|
@@ -370,7 +389,7 @@ async function generateHeadersNode(
|
|
|
370
389
|
l: undefined,
|
|
371
390
|
c: undefined,
|
|
372
391
|
m: undefined,
|
|
373
|
-
d: await
|
|
392
|
+
d: await generatePlainProperties(ctx, items),
|
|
374
393
|
a: undefined,
|
|
375
394
|
f: undefined,
|
|
376
395
|
b: undefined,
|
|
@@ -382,7 +401,7 @@ async function generateFormDataNode(
|
|
|
382
401
|
id: number,
|
|
383
402
|
current: FormData,
|
|
384
403
|
): Promise<SerovalFormDataNode> {
|
|
385
|
-
assert(ctx.features & Feature.WebAPI,
|
|
404
|
+
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
386
405
|
const items: Record<string, FormDataEntryValue> = {};
|
|
387
406
|
current.forEach((value, key) => {
|
|
388
407
|
items[key] = value;
|
|
@@ -394,14 +413,156 @@ async function generateFormDataNode(
|
|
|
394
413
|
l: undefined,
|
|
395
414
|
c: undefined,
|
|
396
415
|
m: undefined,
|
|
397
|
-
d: await
|
|
416
|
+
d: await generatePlainProperties(ctx, items),
|
|
398
417
|
a: undefined,
|
|
399
418
|
f: undefined,
|
|
400
419
|
b: undefined,
|
|
401
420
|
};
|
|
402
421
|
}
|
|
403
422
|
|
|
404
|
-
async function
|
|
423
|
+
async function generateBoxedNode(
|
|
424
|
+
ctx: ParserContext,
|
|
425
|
+
id: number,
|
|
426
|
+
current: object,
|
|
427
|
+
): Promise<SerovalBoxedNode> {
|
|
428
|
+
return {
|
|
429
|
+
t: SerovalNodeType.Boxed,
|
|
430
|
+
i: id,
|
|
431
|
+
s: undefined,
|
|
432
|
+
l: undefined,
|
|
433
|
+
c: undefined,
|
|
434
|
+
m: undefined,
|
|
435
|
+
d: undefined,
|
|
436
|
+
a: undefined,
|
|
437
|
+
f: await parseAsync(ctx, current.valueOf()),
|
|
438
|
+
b: undefined,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async function parseObject(
|
|
443
|
+
ctx: ParserContext,
|
|
444
|
+
current: object | null,
|
|
445
|
+
): Promise<SerovalNode> {
|
|
446
|
+
if (!current) {
|
|
447
|
+
return NULL_NODE;
|
|
448
|
+
}
|
|
449
|
+
// Non-primitive values needs a reference ID
|
|
450
|
+
// mostly because the values themselves are stateful
|
|
451
|
+
const id = createIndexedValue(ctx, current);
|
|
452
|
+
if (ctx.markedRefs.has(id)) {
|
|
453
|
+
return createIndexedValueNode(id);
|
|
454
|
+
}
|
|
455
|
+
if (hasReferenceID(current)) {
|
|
456
|
+
return createReferenceNode(id, current);
|
|
457
|
+
}
|
|
458
|
+
if (Array.isArray(current)) {
|
|
459
|
+
return generateArrayNode(ctx, id, current);
|
|
460
|
+
}
|
|
461
|
+
switch (current.constructor) {
|
|
462
|
+
case Number:
|
|
463
|
+
case Boolean:
|
|
464
|
+
case String:
|
|
465
|
+
case BigInt:
|
|
466
|
+
case Function:
|
|
467
|
+
case Symbol:
|
|
468
|
+
return generateBoxedNode(ctx, id, current);
|
|
469
|
+
case Date:
|
|
470
|
+
return createDateNode(id, current as unknown as Date);
|
|
471
|
+
case RegExp:
|
|
472
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
473
|
+
case Promise:
|
|
474
|
+
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
475
|
+
case ArrayBuffer:
|
|
476
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
477
|
+
case Int8Array:
|
|
478
|
+
case Int16Array:
|
|
479
|
+
case Int32Array:
|
|
480
|
+
case Uint8Array:
|
|
481
|
+
case Uint16Array:
|
|
482
|
+
case Uint32Array:
|
|
483
|
+
case Uint8ClampedArray:
|
|
484
|
+
case Float32Array:
|
|
485
|
+
case Float64Array:
|
|
486
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
487
|
+
case BigInt64Array:
|
|
488
|
+
case BigUint64Array:
|
|
489
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
490
|
+
case DataView:
|
|
491
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
492
|
+
case Map:
|
|
493
|
+
return generateMapNode(
|
|
494
|
+
ctx,
|
|
495
|
+
id,
|
|
496
|
+
current as unknown as Map<unknown, unknown>,
|
|
497
|
+
);
|
|
498
|
+
case Set:
|
|
499
|
+
return generateSetNode(
|
|
500
|
+
ctx,
|
|
501
|
+
id,
|
|
502
|
+
current as unknown as Set<unknown>,
|
|
503
|
+
);
|
|
504
|
+
case Object:
|
|
505
|
+
return generateObjectNode(
|
|
506
|
+
ctx,
|
|
507
|
+
id,
|
|
508
|
+
current as Record<string, unknown>,
|
|
509
|
+
false,
|
|
510
|
+
);
|
|
511
|
+
case undefined:
|
|
512
|
+
return generateObjectNode(
|
|
513
|
+
ctx,
|
|
514
|
+
id,
|
|
515
|
+
current as Record<string, unknown>,
|
|
516
|
+
true,
|
|
517
|
+
);
|
|
518
|
+
case AggregateError:
|
|
519
|
+
if (ctx.features & Feature.AggregateError) {
|
|
520
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
521
|
+
}
|
|
522
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
523
|
+
case Error:
|
|
524
|
+
case EvalError:
|
|
525
|
+
case RangeError:
|
|
526
|
+
case ReferenceError:
|
|
527
|
+
case SyntaxError:
|
|
528
|
+
case TypeError:
|
|
529
|
+
case URIError:
|
|
530
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
531
|
+
case URL:
|
|
532
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
533
|
+
case URLSearchParams:
|
|
534
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
535
|
+
case Blob:
|
|
536
|
+
return createBlobNode(ctx, id, current as unknown as Blob);
|
|
537
|
+
case File:
|
|
538
|
+
return createFileNode(ctx, id, current as unknown as File);
|
|
539
|
+
case Headers:
|
|
540
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
541
|
+
case FormData:
|
|
542
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
543
|
+
default:
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
if (current instanceof AggregateError) {
|
|
547
|
+
if (ctx.features & Feature.AggregateError) {
|
|
548
|
+
return generateAggregateErrorNode(ctx, id, current);
|
|
549
|
+
}
|
|
550
|
+
return generateErrorNode(ctx, id, current);
|
|
551
|
+
}
|
|
552
|
+
if (current instanceof Error) {
|
|
553
|
+
return generateErrorNode(ctx, id, current);
|
|
554
|
+
}
|
|
555
|
+
if (current instanceof Promise) {
|
|
556
|
+
return generatePromiseNode(ctx, id, current);
|
|
557
|
+
}
|
|
558
|
+
// Generator functions don't have a global constructor
|
|
559
|
+
if (Symbol.iterator in current) {
|
|
560
|
+
return generateObjectNode(ctx, id, current, !!current.constructor);
|
|
561
|
+
}
|
|
562
|
+
throw new UnsupportedTypeError(current);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
export default async function parseAsync<T>(
|
|
405
566
|
ctx: ParserContext,
|
|
406
567
|
current: T,
|
|
407
568
|
): Promise<SerovalNode> {
|
|
@@ -413,165 +574,16 @@ async function parse<T>(
|
|
|
413
574
|
case 'string':
|
|
414
575
|
return createStringNode(current);
|
|
415
576
|
case 'number':
|
|
416
|
-
|
|
417
|
-
case Infinity: return INFINITY_NODE;
|
|
418
|
-
case -Infinity: return NEG_INFINITY_NODE;
|
|
419
|
-
default:
|
|
420
|
-
// eslint-disable-next-line no-self-compare
|
|
421
|
-
if (current !== current) {
|
|
422
|
-
return NAN_NODE;
|
|
423
|
-
}
|
|
424
|
-
if (Object.is(current, -0)) {
|
|
425
|
-
return NEG_ZERO_NODE;
|
|
426
|
-
}
|
|
427
|
-
return createNumberNode(current);
|
|
428
|
-
}
|
|
577
|
+
return createNumberNode(current);
|
|
429
578
|
case 'bigint':
|
|
430
579
|
return createBigIntNode(ctx, current);
|
|
431
|
-
case 'object':
|
|
432
|
-
|
|
433
|
-
return NULL_NODE;
|
|
434
|
-
}
|
|
435
|
-
// Non-primitive values needs a reference ID
|
|
436
|
-
// mostly because the values themselves are stateful
|
|
437
|
-
const id = createIndexedValue(ctx, current);
|
|
438
|
-
if (ctx.markedRefs.has(id)) {
|
|
439
|
-
return createIndexedValueNode(id);
|
|
440
|
-
}
|
|
441
|
-
if (hasReferenceID(current)) {
|
|
442
|
-
return createReferenceNode(id, current);
|
|
443
|
-
}
|
|
444
|
-
if (Array.isArray(current)) {
|
|
445
|
-
return generateArrayNode(ctx, id, current);
|
|
446
|
-
}
|
|
447
|
-
switch (current.constructor) {
|
|
448
|
-
case Date:
|
|
449
|
-
return createDateNode(id, current as unknown as Date);
|
|
450
|
-
case RegExp:
|
|
451
|
-
return createRegExpNode(id, current as unknown as RegExp);
|
|
452
|
-
case Promise:
|
|
453
|
-
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
454
|
-
case ArrayBuffer:
|
|
455
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
456
|
-
case Int8Array:
|
|
457
|
-
case Int16Array:
|
|
458
|
-
case Int32Array:
|
|
459
|
-
case Uint8Array:
|
|
460
|
-
case Uint16Array:
|
|
461
|
-
case Uint32Array:
|
|
462
|
-
case Uint8ClampedArray:
|
|
463
|
-
case Float32Array:
|
|
464
|
-
case Float64Array:
|
|
465
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
466
|
-
case BigInt64Array:
|
|
467
|
-
case BigUint64Array:
|
|
468
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
469
|
-
case DataView:
|
|
470
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
471
|
-
case Map:
|
|
472
|
-
return generateMapNode(
|
|
473
|
-
ctx,
|
|
474
|
-
id,
|
|
475
|
-
current as unknown as Map<unknown, unknown>,
|
|
476
|
-
);
|
|
477
|
-
case Set:
|
|
478
|
-
return generateSetNode(
|
|
479
|
-
ctx,
|
|
480
|
-
id,
|
|
481
|
-
current as unknown as Set<unknown>,
|
|
482
|
-
);
|
|
483
|
-
case Object:
|
|
484
|
-
return generateObjectNode(
|
|
485
|
-
ctx,
|
|
486
|
-
id,
|
|
487
|
-
current as Record<string, unknown>,
|
|
488
|
-
false,
|
|
489
|
-
);
|
|
490
|
-
case undefined:
|
|
491
|
-
return generateObjectNode(
|
|
492
|
-
ctx,
|
|
493
|
-
id,
|
|
494
|
-
current as Record<string, unknown>,
|
|
495
|
-
true,
|
|
496
|
-
);
|
|
497
|
-
case AggregateError:
|
|
498
|
-
if (ctx.features & Feature.AggregateError) {
|
|
499
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
500
|
-
}
|
|
501
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
502
|
-
case Error:
|
|
503
|
-
case EvalError:
|
|
504
|
-
case RangeError:
|
|
505
|
-
case ReferenceError:
|
|
506
|
-
case SyntaxError:
|
|
507
|
-
case TypeError:
|
|
508
|
-
case URIError:
|
|
509
|
-
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
510
|
-
case URL:
|
|
511
|
-
return createURLNode(ctx, id, current as unknown as URL);
|
|
512
|
-
case URLSearchParams:
|
|
513
|
-
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
514
|
-
case Blob:
|
|
515
|
-
return createBlobNode(ctx, id, current as unknown as Blob);
|
|
516
|
-
case File:
|
|
517
|
-
return createFileNode(ctx, id, current as unknown as File);
|
|
518
|
-
case Headers:
|
|
519
|
-
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
520
|
-
case FormData:
|
|
521
|
-
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
522
|
-
default:
|
|
523
|
-
break;
|
|
524
|
-
}
|
|
525
|
-
if (current instanceof AggregateError) {
|
|
526
|
-
if (ctx.features & Feature.AggregateError) {
|
|
527
|
-
return generateAggregateErrorNode(ctx, id, current);
|
|
528
|
-
}
|
|
529
|
-
return generateErrorNode(ctx, id, current);
|
|
530
|
-
}
|
|
531
|
-
if (current instanceof Error) {
|
|
532
|
-
return generateErrorNode(ctx, id, current);
|
|
533
|
-
}
|
|
534
|
-
if (current instanceof Promise) {
|
|
535
|
-
return generatePromiseNode(ctx, id, current);
|
|
536
|
-
}
|
|
537
|
-
// Generator functions don't have a global constructor
|
|
538
|
-
if (Symbol.iterator in current) {
|
|
539
|
-
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
540
|
-
}
|
|
541
|
-
// For Promise-like objects
|
|
542
|
-
if ('then' in current && typeof current.then === 'function') {
|
|
543
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
544
|
-
}
|
|
545
|
-
throw new Error('Unsupported type');
|
|
546
|
-
}
|
|
580
|
+
case 'object':
|
|
581
|
+
return parseObject(ctx, current);
|
|
547
582
|
case 'symbol':
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
return createIndexedValueNode(id);
|
|
552
|
-
}
|
|
553
|
-
return createReferenceNode(id, current);
|
|
554
|
-
}
|
|
555
|
-
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
556
|
-
case 'function': {
|
|
557
|
-
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
558
|
-
const id = createIndexedValue(ctx, current);
|
|
559
|
-
if (ctx.markedRefs.has(id)) {
|
|
560
|
-
return createIndexedValueNode(id);
|
|
561
|
-
}
|
|
562
|
-
return createReferenceNode(id, current);
|
|
563
|
-
}
|
|
583
|
+
return createSymbolNode(ctx, current);
|
|
584
|
+
case 'function':
|
|
585
|
+
return createFunctionNode(ctx, current);
|
|
564
586
|
default:
|
|
565
|
-
throw new
|
|
587
|
+
throw new UnsupportedTypeError(current);
|
|
566
588
|
}
|
|
567
589
|
}
|
|
568
|
-
|
|
569
|
-
export default async function parseAsync<T>(
|
|
570
|
-
ctx: ParserContext,
|
|
571
|
-
current: T,
|
|
572
|
-
) {
|
|
573
|
-
const result = await parse(ctx, current);
|
|
574
|
-
const isObject = result.t === SerovalNodeType.Object
|
|
575
|
-
|| result.t === SerovalNodeType.Iterable;
|
|
576
|
-
return [result, getRootID(ctx, current), isObject] as const;
|
|
577
|
-
}
|