seroval 0.5.0 → 0.6.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 +59 -9
- package/dist/cjs/development/index.cjs +372 -202
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +372 -202
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/compat.d.ts +3 -2
- package/dist/types/context.d.ts +3 -6
- package/dist/types/index.d.ts +9 -9
- package/dist/types/tree/async.d.ts +1 -2
- package/dist/types/tree/deserialize.d.ts +1 -2
- package/dist/types/tree/primitives.d.ts +4 -3
- package/dist/types/tree/reference.d.ts +6 -0
- package/dist/types/tree/sync.d.ts +1 -2
- package/dist/types/tree/types.d.ts +25 -7
- package/dist/types/tree/web-api.d.ts +4 -0
- package/dist/types/types.d.ts +2 -1
- package/package.json +3 -3
- package/src/compat.ts +2 -1
- package/src/context.ts +37 -48
- package/src/index.ts +10 -16
- package/src/tree/async.ts +99 -74
- package/src/tree/deserialize.ts +32 -21
- package/src/tree/primitives.ts +46 -24
- package/src/tree/reference.ts +61 -0
- package/src/tree/serialize.ts +93 -86
- package/src/tree/sync.ts +104 -66
- package/src/tree/types.ts +32 -8
- package/src/tree/web-api.ts +42 -0
- package/src/types.ts +6 -1
package/src/tree/async.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
3
3
|
import assert from '../assert';
|
|
4
4
|
import { Feature } from '../compat';
|
|
5
|
-
import {
|
|
5
|
+
import { createIndexedValue, getRootID, ParserContext } from '../context';
|
|
6
|
+
import quote from '../quote';
|
|
6
7
|
import {
|
|
7
|
-
AsyncServerValue,
|
|
8
8
|
BigIntTypedArrayValue,
|
|
9
9
|
TypedArrayValue,
|
|
10
10
|
} from '../types';
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
createBigIntTypedArrayNode,
|
|
14
14
|
createDateNode,
|
|
15
15
|
createNumberNode,
|
|
16
|
-
|
|
16
|
+
createIndexedValueNode,
|
|
17
17
|
createRegExpNode,
|
|
18
18
|
createStringNode,
|
|
19
19
|
createTypedArrayNode,
|
|
@@ -26,14 +26,16 @@ import {
|
|
|
26
26
|
NULL_NODE,
|
|
27
27
|
TRUE_NODE,
|
|
28
28
|
UNDEFINED_NODE,
|
|
29
|
+
createReferenceNode,
|
|
29
30
|
} from './primitives';
|
|
31
|
+
import { hasReferenceID } from './reference';
|
|
30
32
|
import {
|
|
31
33
|
getErrorConstructorName,
|
|
32
34
|
getErrorOptions,
|
|
33
35
|
getIterableOptions,
|
|
34
36
|
isIterable,
|
|
35
37
|
} from './shared';
|
|
36
|
-
import {
|
|
38
|
+
import { WellKnownSymbols } from './symbols';
|
|
37
39
|
import {
|
|
38
40
|
SerovalAggregateErrorNode,
|
|
39
41
|
SerovalArrayNode,
|
|
@@ -48,6 +50,7 @@ import {
|
|
|
48
50
|
SerovalPromiseNode,
|
|
49
51
|
SerovalSetNode,
|
|
50
52
|
} from './types';
|
|
53
|
+
import { createURLNode, createURLSearchParamsNode } from './web-api';
|
|
51
54
|
|
|
52
55
|
type ObjectLikeNode =
|
|
53
56
|
| SerovalObjectNode
|
|
@@ -56,18 +59,18 @@ type ObjectLikeNode =
|
|
|
56
59
|
| SerovalPromiseNode;
|
|
57
60
|
|
|
58
61
|
type ObjectLikeValue =
|
|
59
|
-
| Record<string,
|
|
60
|
-
| Iterable<
|
|
61
|
-
| PromiseLike<
|
|
62
|
+
| Record<string, unknown>
|
|
63
|
+
| Iterable<unknown>
|
|
64
|
+
| PromiseLike<unknown>;
|
|
62
65
|
|
|
63
66
|
async function generateNodeList(
|
|
64
67
|
ctx: ParserContext,
|
|
65
|
-
current:
|
|
68
|
+
current: unknown[],
|
|
66
69
|
) {
|
|
67
70
|
const size = current.length;
|
|
68
71
|
const nodes = new Array<SerovalNode>(size);
|
|
69
|
-
const deferred = new Array<
|
|
70
|
-
let item:
|
|
72
|
+
const deferred = new Array<unknown>(size);
|
|
73
|
+
let item: unknown;
|
|
71
74
|
for (let i = 0; i < size; i++) {
|
|
72
75
|
if (i in current) {
|
|
73
76
|
item = current[i];
|
|
@@ -89,7 +92,7 @@ async function generateNodeList(
|
|
|
89
92
|
async function generateArrayNode(
|
|
90
93
|
ctx: ParserContext,
|
|
91
94
|
id: number,
|
|
92
|
-
current:
|
|
95
|
+
current: unknown[],
|
|
93
96
|
): Promise<SerovalArrayNode> {
|
|
94
97
|
return {
|
|
95
98
|
t: SerovalNodeType.Array,
|
|
@@ -100,21 +103,21 @@ async function generateArrayNode(
|
|
|
100
103
|
m: undefined,
|
|
101
104
|
d: undefined,
|
|
102
105
|
a: await generateNodeList(ctx, current),
|
|
103
|
-
|
|
106
|
+
f: undefined,
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
async function generateMapNode(
|
|
108
111
|
ctx: ParserContext,
|
|
109
112
|
id: number,
|
|
110
|
-
current: Map<
|
|
113
|
+
current: Map<unknown, unknown>,
|
|
111
114
|
): Promise<SerovalMapNode> {
|
|
112
115
|
assert(ctx.features & Feature.Map, 'Unsupported type "Map"');
|
|
113
116
|
const len = current.size;
|
|
114
117
|
const keyNodes = new Array<SerovalNode>(len);
|
|
115
118
|
const valueNodes = new Array<SerovalNode>(len);
|
|
116
|
-
const deferredKey = new Array<
|
|
117
|
-
const deferredValue = new Array<
|
|
119
|
+
const deferredKey = new Array<unknown>(len);
|
|
120
|
+
const deferredValue = new Array<unknown>(len);
|
|
118
121
|
let deferredSize = 0;
|
|
119
122
|
let nodeSize = 0;
|
|
120
123
|
for (const [key, value] of current.entries()) {
|
|
@@ -142,19 +145,19 @@ async function generateMapNode(
|
|
|
142
145
|
m: undefined,
|
|
143
146
|
d: { k: keyNodes, v: valueNodes, s: len },
|
|
144
147
|
a: undefined,
|
|
145
|
-
|
|
148
|
+
f: undefined,
|
|
146
149
|
};
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
async function generateSetNode(
|
|
150
153
|
ctx: ParserContext,
|
|
151
154
|
id: number,
|
|
152
|
-
current: Set<
|
|
155
|
+
current: Set<unknown>,
|
|
153
156
|
): Promise<SerovalSetNode> {
|
|
154
157
|
assert(ctx.features & Feature.Set, 'Unsupported type "Set"');
|
|
155
158
|
const len = current.size;
|
|
156
159
|
const nodes = new Array<SerovalNode>(len);
|
|
157
|
-
const deferred = new Array<
|
|
160
|
+
const deferred = new Array<unknown>(len);
|
|
158
161
|
let deferredSize = 0;
|
|
159
162
|
let nodeSize = 0;
|
|
160
163
|
for (const item of current.keys()) {
|
|
@@ -178,23 +181,23 @@ async function generateSetNode(
|
|
|
178
181
|
m: undefined,
|
|
179
182
|
d: undefined,
|
|
180
183
|
a: nodes,
|
|
181
|
-
|
|
184
|
+
f: undefined,
|
|
182
185
|
};
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
async function generateProperties(
|
|
186
189
|
ctx: ParserContext,
|
|
187
|
-
properties: Record<string,
|
|
190
|
+
properties: Record<string, unknown>,
|
|
188
191
|
): Promise<SerovalObjectRecordNode> {
|
|
189
192
|
const keys = Object.keys(properties);
|
|
190
193
|
const size = keys.length;
|
|
191
194
|
const keyNodes = new Array<string>(size);
|
|
192
195
|
const valueNodes = new Array<SerovalNode>(size);
|
|
193
196
|
const deferredKeys = new Array<string>(size);
|
|
194
|
-
const deferredValues = new Array<
|
|
197
|
+
const deferredValues = new Array<unknown>(size);
|
|
195
198
|
let deferredSize = 0;
|
|
196
199
|
let nodesSize = 0;
|
|
197
|
-
let item:
|
|
200
|
+
let item: unknown;
|
|
198
201
|
for (const key of keys) {
|
|
199
202
|
item = properties[key];
|
|
200
203
|
if (isIterable(item)) {
|
|
@@ -221,7 +224,7 @@ async function generateProperties(
|
|
|
221
224
|
async function generateIterableNode(
|
|
222
225
|
ctx: ParserContext,
|
|
223
226
|
id: number,
|
|
224
|
-
current: Iterable<
|
|
227
|
+
current: Iterable<unknown>,
|
|
225
228
|
): Promise<SerovalIterableNode> {
|
|
226
229
|
assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
|
|
227
230
|
const options = getIterableOptions(current);
|
|
@@ -235,17 +238,17 @@ async function generateIterableNode(
|
|
|
235
238
|
m: undefined,
|
|
236
239
|
// Parse options first before the items
|
|
237
240
|
d: options
|
|
238
|
-
? await generateProperties(ctx, options
|
|
241
|
+
? await generateProperties(ctx, options)
|
|
239
242
|
: undefined,
|
|
240
243
|
a: await generateNodeList(ctx, array),
|
|
241
|
-
|
|
244
|
+
f: undefined,
|
|
242
245
|
};
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
async function generatePromiseNode(
|
|
246
249
|
ctx: ParserContext,
|
|
247
250
|
id: number,
|
|
248
|
-
current: PromiseLike<
|
|
251
|
+
current: PromiseLike<unknown>,
|
|
249
252
|
): Promise<SerovalPromiseNode> {
|
|
250
253
|
assert(ctx.features & Feature.Promise, 'Unsupported type "Promise"');
|
|
251
254
|
return current.then(async (value) => ({
|
|
@@ -258,7 +261,7 @@ async function generatePromiseNode(
|
|
|
258
261
|
// Parse options first before the items
|
|
259
262
|
d: undefined,
|
|
260
263
|
a: undefined,
|
|
261
|
-
|
|
264
|
+
f: await parse(ctx, value),
|
|
262
265
|
}));
|
|
263
266
|
}
|
|
264
267
|
|
|
@@ -272,7 +275,7 @@ async function generateObjectNode(
|
|
|
272
275
|
return generateIterableNode(ctx, id, current);
|
|
273
276
|
}
|
|
274
277
|
if ('then' in current && typeof current.then === 'function') {
|
|
275
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<
|
|
278
|
+
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
276
279
|
}
|
|
277
280
|
return {
|
|
278
281
|
t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
@@ -281,9 +284,9 @@ async function generateObjectNode(
|
|
|
281
284
|
l: undefined,
|
|
282
285
|
c: undefined,
|
|
283
286
|
m: undefined,
|
|
284
|
-
d: await generateProperties(ctx, current as Record<string,
|
|
287
|
+
d: await generateProperties(ctx, current as Record<string, unknown>),
|
|
285
288
|
a: undefined,
|
|
286
|
-
|
|
289
|
+
f: undefined,
|
|
287
290
|
};
|
|
288
291
|
}
|
|
289
292
|
|
|
@@ -302,10 +305,10 @@ async function generateAggregateErrorNode(
|
|
|
302
305
|
s: undefined,
|
|
303
306
|
l: current.errors.length,
|
|
304
307
|
c: undefined,
|
|
305
|
-
m: current.message,
|
|
308
|
+
m: quote(current.message),
|
|
306
309
|
d: optionsNode,
|
|
307
|
-
a: await generateNodeList(ctx, current.errors as
|
|
308
|
-
|
|
310
|
+
a: await generateNodeList(ctx, current.errors as unknown[]),
|
|
311
|
+
f: undefined,
|
|
309
312
|
};
|
|
310
313
|
}
|
|
311
314
|
|
|
@@ -324,16 +327,16 @@ async function generateErrorNode(
|
|
|
324
327
|
s: undefined,
|
|
325
328
|
l: undefined,
|
|
326
329
|
c: getErrorConstructorName(current),
|
|
327
|
-
m: current.message,
|
|
330
|
+
m: quote(current.message),
|
|
328
331
|
d: optionsNode,
|
|
329
332
|
a: undefined,
|
|
330
|
-
|
|
333
|
+
f: undefined,
|
|
331
334
|
};
|
|
332
335
|
}
|
|
333
336
|
|
|
334
|
-
async function parse(
|
|
337
|
+
async function parse<T>(
|
|
335
338
|
ctx: ParserContext,
|
|
336
|
-
current:
|
|
339
|
+
current: T,
|
|
337
340
|
): Promise<SerovalNode> {
|
|
338
341
|
switch (typeof current) {
|
|
339
342
|
case 'boolean':
|
|
@@ -343,20 +346,19 @@ async function parse(
|
|
|
343
346
|
case 'string':
|
|
344
347
|
return createStringNode(current);
|
|
345
348
|
case 'number':
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
349
|
+
switch (current) {
|
|
350
|
+
case Infinity: return INFINITY_NODE;
|
|
351
|
+
case -Infinity: return NEG_INFINITY_NODE;
|
|
352
|
+
default:
|
|
353
|
+
// eslint-disable-next-line no-self-compare
|
|
354
|
+
if (current !== current) {
|
|
355
|
+
return NAN_NODE;
|
|
356
|
+
}
|
|
357
|
+
if (Object.is(current, -0)) {
|
|
358
|
+
return NEG_ZERO_NODE;
|
|
359
|
+
}
|
|
360
|
+
return createNumberNode(current);
|
|
358
361
|
}
|
|
359
|
-
return createNumberNode(current);
|
|
360
362
|
case 'bigint':
|
|
361
363
|
return createBigIntNode(ctx, current);
|
|
362
364
|
case 'object': {
|
|
@@ -365,20 +367,23 @@ async function parse(
|
|
|
365
367
|
}
|
|
366
368
|
// Non-primitive values needs a reference ID
|
|
367
369
|
// mostly because the values themselves are stateful
|
|
368
|
-
const id =
|
|
370
|
+
const id = createIndexedValue(ctx, current);
|
|
369
371
|
if (ctx.markedRefs.has(id)) {
|
|
370
|
-
return
|
|
372
|
+
return createIndexedValueNode(id);
|
|
373
|
+
}
|
|
374
|
+
if (hasReferenceID(current)) {
|
|
375
|
+
return createReferenceNode(id, current);
|
|
371
376
|
}
|
|
372
377
|
if (Array.isArray(current)) {
|
|
373
378
|
return generateArrayNode(ctx, id, current);
|
|
374
379
|
}
|
|
375
380
|
switch (current.constructor) {
|
|
376
381
|
case Date:
|
|
377
|
-
return createDateNode(id, current as Date);
|
|
382
|
+
return createDateNode(id, current as unknown as Date);
|
|
378
383
|
case RegExp:
|
|
379
|
-
return createRegExpNode(id, current as RegExp);
|
|
384
|
+
return createRegExpNode(id, current as unknown as RegExp);
|
|
380
385
|
case Promise:
|
|
381
|
-
return generatePromiseNode(ctx, id, current as Promise<
|
|
386
|
+
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
382
387
|
case Int8Array:
|
|
383
388
|
case Int16Array:
|
|
384
389
|
case Int32Array:
|
|
@@ -388,41 +393,41 @@ async function parse(
|
|
|
388
393
|
case Uint8ClampedArray:
|
|
389
394
|
case Float32Array:
|
|
390
395
|
case Float64Array:
|
|
391
|
-
return createTypedArrayNode(ctx, id, current as TypedArrayValue);
|
|
396
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
392
397
|
case BigInt64Array:
|
|
393
398
|
case BigUint64Array:
|
|
394
|
-
return createBigIntTypedArrayNode(ctx, id, current as BigIntTypedArrayValue);
|
|
399
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
395
400
|
case Map:
|
|
396
401
|
return generateMapNode(
|
|
397
402
|
ctx,
|
|
398
403
|
id,
|
|
399
|
-
current as Map<
|
|
404
|
+
current as unknown as Map<unknown, unknown>,
|
|
400
405
|
);
|
|
401
406
|
case Set:
|
|
402
407
|
return generateSetNode(
|
|
403
408
|
ctx,
|
|
404
409
|
id,
|
|
405
|
-
current as Set<
|
|
410
|
+
current as unknown as Set<unknown>,
|
|
406
411
|
);
|
|
407
412
|
case Object:
|
|
408
413
|
return generateObjectNode(
|
|
409
414
|
ctx,
|
|
410
415
|
id,
|
|
411
|
-
current as Record<string,
|
|
416
|
+
current as Record<string, unknown>,
|
|
412
417
|
false,
|
|
413
418
|
);
|
|
414
419
|
case undefined:
|
|
415
420
|
return generateObjectNode(
|
|
416
421
|
ctx,
|
|
417
422
|
id,
|
|
418
|
-
current as Record<string,
|
|
423
|
+
current as Record<string, unknown>,
|
|
419
424
|
true,
|
|
420
425
|
);
|
|
421
426
|
case AggregateError:
|
|
422
427
|
if (ctx.features & Feature.AggregateError) {
|
|
423
|
-
return generateAggregateErrorNode(ctx, id, current as AggregateError);
|
|
428
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
424
429
|
}
|
|
425
|
-
return generateErrorNode(ctx, id, current as AggregateError);
|
|
430
|
+
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
426
431
|
case Error:
|
|
427
432
|
case EvalError:
|
|
428
433
|
case RangeError:
|
|
@@ -430,12 +435,19 @@ async function parse(
|
|
|
430
435
|
case SyntaxError:
|
|
431
436
|
case TypeError:
|
|
432
437
|
case URIError:
|
|
433
|
-
return generateErrorNode(ctx, id, current as Error);
|
|
438
|
+
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
439
|
+
case URL:
|
|
440
|
+
return createURLNode(ctx, id, current as unknown as URL);
|
|
441
|
+
case URLSearchParams:
|
|
442
|
+
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
434
443
|
default:
|
|
435
444
|
break;
|
|
436
445
|
}
|
|
437
|
-
if (current instanceof AggregateError
|
|
438
|
-
|
|
446
|
+
if (current instanceof AggregateError) {
|
|
447
|
+
if (ctx.features & Feature.AggregateError) {
|
|
448
|
+
return generateAggregateErrorNode(ctx, id, current);
|
|
449
|
+
}
|
|
450
|
+
return generateErrorNode(ctx, id, current);
|
|
439
451
|
}
|
|
440
452
|
if (current instanceof Error) {
|
|
441
453
|
return generateErrorNode(ctx, id, current);
|
|
@@ -445,29 +457,42 @@ async function parse(
|
|
|
445
457
|
}
|
|
446
458
|
// Generator functions don't have a global constructor
|
|
447
459
|
if (Symbol.iterator in current) {
|
|
448
|
-
return generateIterableNode(ctx, id, current);
|
|
460
|
+
return generateIterableNode(ctx, id, current as Iterable<unknown>);
|
|
449
461
|
}
|
|
450
462
|
// For Promise-like objects
|
|
451
463
|
if ('then' in current && typeof current.then === 'function') {
|
|
452
|
-
return generatePromiseNode(ctx, id, current as PromiseLike<
|
|
464
|
+
return generatePromiseNode(ctx, id, current as PromiseLike<unknown>);
|
|
453
465
|
}
|
|
454
466
|
throw new Error('Unsupported type');
|
|
455
467
|
}
|
|
456
468
|
case 'symbol':
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
469
|
+
if (hasReferenceID(current)) {
|
|
470
|
+
const id = createIndexedValue(ctx, current);
|
|
471
|
+
if (ctx.markedRefs.has(id)) {
|
|
472
|
+
return createIndexedValueNode(id);
|
|
473
|
+
}
|
|
474
|
+
return createReferenceNode(id, current);
|
|
475
|
+
}
|
|
476
|
+
return createWKSymbolNode(ctx, current as WellKnownSymbols);
|
|
477
|
+
case 'function': {
|
|
478
|
+
assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
|
|
479
|
+
const id = createIndexedValue(ctx, current);
|
|
480
|
+
if (ctx.markedRefs.has(id)) {
|
|
481
|
+
return createIndexedValueNode(id);
|
|
482
|
+
}
|
|
483
|
+
return createReferenceNode(id, current);
|
|
484
|
+
}
|
|
460
485
|
default:
|
|
461
486
|
throw new Error('Unsupported type');
|
|
462
487
|
}
|
|
463
488
|
}
|
|
464
489
|
|
|
465
|
-
export default async function parseAsync(
|
|
490
|
+
export default async function parseAsync<T>(
|
|
466
491
|
ctx: ParserContext,
|
|
467
|
-
current:
|
|
492
|
+
current: T,
|
|
468
493
|
) {
|
|
469
494
|
const result = await parse(ctx, current);
|
|
470
495
|
const isObject = result.t === SerovalNodeType.Object
|
|
471
496
|
|| result.t === SerovalNodeType.Iterable;
|
|
472
|
-
return [result,
|
|
497
|
+
return [result, getRootID(ctx, current), isObject] as const;
|
|
473
498
|
}
|
package/src/tree/deserialize.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
} from '../context';
|
|
5
5
|
import { invQuote } from '../quote';
|
|
6
6
|
import { AsyncServerValue } from '../types';
|
|
7
|
+
import { getReference } from './reference';
|
|
7
8
|
import { getErrorConstructor, getTypedArrayConstructor } from './shared';
|
|
8
9
|
import { SYMBOL_REF } from './symbols';
|
|
9
10
|
import {
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
SerovalTypedArrayNode,
|
|
24
25
|
} from './types';
|
|
25
26
|
|
|
26
|
-
function
|
|
27
|
+
function assignIndexedValue<T>(
|
|
27
28
|
ctx: SerializationContext,
|
|
28
29
|
index: number,
|
|
29
30
|
value: T,
|
|
@@ -35,7 +36,7 @@ function assignRef<T extends AsyncServerValue>(
|
|
|
35
36
|
function deserializeNodeList(
|
|
36
37
|
ctx: SerializationContext,
|
|
37
38
|
node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
|
|
38
|
-
result:
|
|
39
|
+
result: unknown[],
|
|
39
40
|
) {
|
|
40
41
|
let item: SerovalNode;
|
|
41
42
|
for (let i = 0, len = node.a.length; i < len; i++) {
|
|
@@ -51,7 +52,7 @@ function deserializeArray(
|
|
|
51
52
|
ctx: SerializationContext,
|
|
52
53
|
node: SerovalArrayNode,
|
|
53
54
|
) {
|
|
54
|
-
const result: AsyncServerValue[] =
|
|
55
|
+
const result: AsyncServerValue[] = assignIndexedValue(
|
|
55
56
|
ctx,
|
|
56
57
|
node.i,
|
|
57
58
|
new Array<AsyncServerValue>(node.l),
|
|
@@ -65,7 +66,7 @@ function deserializeArray(
|
|
|
65
66
|
function deserializeProperties(
|
|
66
67
|
ctx: SerializationContext,
|
|
67
68
|
node: SerovalObjectRecordNode,
|
|
68
|
-
result: Record<string,
|
|
69
|
+
result: Record<string, unknown>,
|
|
69
70
|
) {
|
|
70
71
|
if (node.s === 0) {
|
|
71
72
|
return {};
|
|
@@ -80,7 +81,11 @@ function deserializeNullConstructor(
|
|
|
80
81
|
ctx: SerializationContext,
|
|
81
82
|
node: SerovalNullConstructorNode,
|
|
82
83
|
) {
|
|
83
|
-
const result =
|
|
84
|
+
const result = assignIndexedValue(
|
|
85
|
+
ctx,
|
|
86
|
+
node.i,
|
|
87
|
+
Object.create(null) as Record<string, AsyncServerValue>,
|
|
88
|
+
);
|
|
84
89
|
ctx.stack.push(node.i);
|
|
85
90
|
deserializeProperties(ctx, node.d, result);
|
|
86
91
|
ctx.stack.pop();
|
|
@@ -91,7 +96,7 @@ function deserializeObject(
|
|
|
91
96
|
ctx: SerializationContext,
|
|
92
97
|
node: SerovalObjectNode,
|
|
93
98
|
) {
|
|
94
|
-
const result =
|
|
99
|
+
const result = assignIndexedValue(ctx, node.i, {} as Record<string, AsyncServerValue>);
|
|
95
100
|
ctx.stack.push(node.i);
|
|
96
101
|
deserializeProperties(ctx, node.d, result);
|
|
97
102
|
ctx.stack.pop();
|
|
@@ -102,7 +107,7 @@ function deserializeSet(
|
|
|
102
107
|
ctx: SerializationContext,
|
|
103
108
|
node: SerovalSetNode,
|
|
104
109
|
) {
|
|
105
|
-
const result =
|
|
110
|
+
const result = assignIndexedValue(ctx, node.i, new Set<unknown>());
|
|
106
111
|
ctx.stack.push(node.i);
|
|
107
112
|
for (let i = 0, len = node.a.length; i < len; i++) {
|
|
108
113
|
result.add(deserializeTree(ctx, node.a[i]));
|
|
@@ -115,10 +120,10 @@ function deserializeMap(
|
|
|
115
120
|
ctx: SerializationContext,
|
|
116
121
|
node: SerovalMapNode,
|
|
117
122
|
) {
|
|
118
|
-
const result =
|
|
123
|
+
const result = assignIndexedValue(
|
|
119
124
|
ctx,
|
|
120
125
|
node.i,
|
|
121
|
-
new Map<
|
|
126
|
+
new Map<unknown, unknown>(),
|
|
122
127
|
);
|
|
123
128
|
ctx.stack.push(node.i);
|
|
124
129
|
for (let i = 0; i < node.d.s; i++) {
|
|
@@ -153,7 +158,7 @@ function deserializeAggregateError(
|
|
|
153
158
|
node: SerovalAggregateErrorNode,
|
|
154
159
|
) {
|
|
155
160
|
// Serialize the required arguments
|
|
156
|
-
const result =
|
|
161
|
+
const result = assignIndexedValue(ctx, node.i, new AggregateError([], invQuote(node.m)));
|
|
157
162
|
ctx.stack.push(node.i);
|
|
158
163
|
result.errors = deserializeNodeList(ctx, node, new Array<AsyncServerValue>(node.l));
|
|
159
164
|
ctx.stack.pop();
|
|
@@ -168,13 +173,13 @@ function deserializeError(
|
|
|
168
173
|
node: SerovalErrorNode,
|
|
169
174
|
) {
|
|
170
175
|
const ErrorConstructor = getErrorConstructor(node.c);
|
|
171
|
-
const result =
|
|
176
|
+
const result = assignIndexedValue(ctx, node.i, new ErrorConstructor(invQuote(node.m)));
|
|
172
177
|
return deserializeDictionary(ctx, node, result);
|
|
173
178
|
}
|
|
174
179
|
|
|
175
180
|
interface Deferred {
|
|
176
|
-
resolve(value:
|
|
177
|
-
promise: Promise<
|
|
181
|
+
resolve(value: unknown): void;
|
|
182
|
+
promise: Promise<unknown>;
|
|
178
183
|
}
|
|
179
184
|
|
|
180
185
|
function createDeferred(): Deferred {
|
|
@@ -194,8 +199,8 @@ function deserializePromise(
|
|
|
194
199
|
node: SerovalPromiseNode,
|
|
195
200
|
) {
|
|
196
201
|
const deferred = createDeferred();
|
|
197
|
-
const result =
|
|
198
|
-
deferred.resolve(deserializeTree(ctx, node.
|
|
202
|
+
const result = assignIndexedValue(ctx, node.i, deferred.promise);
|
|
203
|
+
deferred.resolve(deserializeTree(ctx, node.f));
|
|
199
204
|
return result;
|
|
200
205
|
}
|
|
201
206
|
|
|
@@ -205,7 +210,7 @@ function deserializeTypedArray(
|
|
|
205
210
|
) {
|
|
206
211
|
const TypedArray = getTypedArrayConstructor(node.c);
|
|
207
212
|
const dummy = new TypedArray();
|
|
208
|
-
const result =
|
|
213
|
+
const result = assignIndexedValue(ctx, node.i, new TypedArray(
|
|
209
214
|
dummy.buffer,
|
|
210
215
|
node.l,
|
|
211
216
|
));
|
|
@@ -223,7 +228,7 @@ function deserializeIterable(
|
|
|
223
228
|
) {
|
|
224
229
|
const values: AsyncServerValue[] = [];
|
|
225
230
|
deserializeNodeList(ctx, node, values);
|
|
226
|
-
const result =
|
|
231
|
+
const result = assignIndexedValue(ctx, node.i, {
|
|
227
232
|
[Symbol.iterator]: () => values.values(),
|
|
228
233
|
});
|
|
229
234
|
return deserializeDictionary(ctx, node, result);
|
|
@@ -232,7 +237,7 @@ function deserializeIterable(
|
|
|
232
237
|
export default function deserializeTree(
|
|
233
238
|
ctx: SerializationContext,
|
|
234
239
|
node: SerovalNode,
|
|
235
|
-
):
|
|
240
|
+
): unknown {
|
|
236
241
|
switch (node.t) {
|
|
237
242
|
case SerovalNodeType.Number:
|
|
238
243
|
case SerovalNodeType.Boolean:
|
|
@@ -253,7 +258,7 @@ export default function deserializeTree(
|
|
|
253
258
|
return NaN;
|
|
254
259
|
case SerovalNodeType.BigInt:
|
|
255
260
|
return BigInt(node.s);
|
|
256
|
-
case SerovalNodeType.
|
|
261
|
+
case SerovalNodeType.IndexedValue:
|
|
257
262
|
return ctx.valueMap.get(node.i);
|
|
258
263
|
case SerovalNodeType.Array:
|
|
259
264
|
return deserializeArray(ctx, node);
|
|
@@ -262,9 +267,9 @@ export default function deserializeTree(
|
|
|
262
267
|
case SerovalNodeType.NullConstructor:
|
|
263
268
|
return deserializeNullConstructor(ctx, node);
|
|
264
269
|
case SerovalNodeType.Date:
|
|
265
|
-
return
|
|
270
|
+
return assignIndexedValue(ctx, node.i, new Date(node.s));
|
|
266
271
|
case SerovalNodeType.RegExp:
|
|
267
|
-
return
|
|
272
|
+
return assignIndexedValue(ctx, node.i, new RegExp(node.c, node.m));
|
|
268
273
|
case SerovalNodeType.Set:
|
|
269
274
|
return deserializeSet(ctx, node);
|
|
270
275
|
case SerovalNodeType.Map:
|
|
@@ -282,6 +287,12 @@ export default function deserializeTree(
|
|
|
282
287
|
return deserializePromise(ctx, node);
|
|
283
288
|
case SerovalNodeType.WKSymbol:
|
|
284
289
|
return SYMBOL_REF[node.s];
|
|
290
|
+
case SerovalNodeType.URL:
|
|
291
|
+
return assignIndexedValue(ctx, node.i, new URL(node.s));
|
|
292
|
+
case SerovalNodeType.URLSearchParams:
|
|
293
|
+
return assignIndexedValue(ctx, node.i, new URLSearchParams(node.s));
|
|
294
|
+
case SerovalNodeType.Reference:
|
|
295
|
+
return assignIndexedValue(ctx, node.i, getReference(invQuote(node.s)));
|
|
285
296
|
default:
|
|
286
297
|
throw new Error('Unsupported type');
|
|
287
298
|
}
|