seroval 0.10.4 → 0.11.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 +842 -318
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +842 -318
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/core/compat.d.ts +2 -1
- package/dist/types/core/constants.d.ts +6 -1
- package/dist/types/core/constructors.d.ts +4 -0
- package/dist/types/core/types.d.ts +31 -2
- package/dist/types/core/web-api.d.ts +4 -4
- package/package.json +8 -9
- package/src/core/compat.ts +3 -1
- package/src/core/constants.ts +5 -0
- package/src/core/constructors.ts +49 -0
- package/src/core/cross/async.ts +208 -76
- package/src/core/cross/serialize.ts +61 -0
- package/src/core/cross/stream.ts +203 -79
- package/src/core/cross/sync.ts +126 -61
- package/src/core/tree/async.ts +209 -76
- package/src/core/tree/deserialize.ts +82 -0
- package/src/core/tree/primitives.ts +0 -9
- package/src/core/tree/serialize.ts +62 -0
- package/src/core/tree/sync.ts +126 -61
- package/src/core/types.ts +49 -2
- package/src/core/web-api.ts +21 -9
package/src/core/tree/sync.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
|
-
import
|
|
3
|
-
import { Feature } from '../compat';
|
|
2
|
+
import { BIGINT_FLAG, Feature } from '../compat';
|
|
4
3
|
import type { ParserContext } from './context';
|
|
5
4
|
import { createIndexedValue } from './context';
|
|
6
5
|
import { serializeString } from '../string';
|
|
@@ -32,7 +31,9 @@ import type {
|
|
|
32
31
|
SerovalAggregateErrorNode,
|
|
33
32
|
SerovalArrayNode,
|
|
34
33
|
SerovalBoxedNode,
|
|
34
|
+
SerovalCustomEventNode,
|
|
35
35
|
SerovalErrorNode,
|
|
36
|
+
SerovalEventNode,
|
|
36
37
|
SerovalFormDataNode,
|
|
37
38
|
SerovalHeadersNode,
|
|
38
39
|
SerovalMapNode,
|
|
@@ -58,7 +59,8 @@ import {
|
|
|
58
59
|
createRegExpNode,
|
|
59
60
|
createStringNode,
|
|
60
61
|
} from '../base-primitives';
|
|
61
|
-
import { createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
62
|
+
import { createDOMExceptionNode, createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
63
|
+
import { createCustomEventOptions, createEventOptions } from '../constructors';
|
|
62
64
|
|
|
63
65
|
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
|
|
64
66
|
|
|
@@ -111,7 +113,6 @@ function generateMapNode(
|
|
|
111
113
|
id: number,
|
|
112
114
|
current: Map<unknown, unknown>,
|
|
113
115
|
): SerovalMapNode {
|
|
114
|
-
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
115
116
|
const len = current.size;
|
|
116
117
|
const keyNodes = new Array<SerovalSyncNode>(len);
|
|
117
118
|
const valueNodes = new Array<SerovalSyncNode>(len);
|
|
@@ -156,7 +157,6 @@ function generateSetNode(
|
|
|
156
157
|
id: number,
|
|
157
158
|
current: Set<unknown>,
|
|
158
159
|
): SerovalSetNode {
|
|
159
|
-
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
160
160
|
const len = current.size;
|
|
161
161
|
const nodes = new Array<SerovalSyncNode>(len);
|
|
162
162
|
const deferred = new Array<unknown>(len);
|
|
@@ -352,7 +352,6 @@ function generateHeadersNode(
|
|
|
352
352
|
id: number,
|
|
353
353
|
current: Headers,
|
|
354
354
|
): SerovalHeadersNode {
|
|
355
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
356
355
|
const items: Record<string, string> = {};
|
|
357
356
|
// TS Headers not an Iterable
|
|
358
357
|
current.forEach((value, key) => {
|
|
@@ -379,7 +378,6 @@ function generateFormDataNode(
|
|
|
379
378
|
id: number,
|
|
380
379
|
current: FormData,
|
|
381
380
|
): SerovalFormDataNode {
|
|
382
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
383
381
|
const items: Record<string, FormDataEntryValue> = {};
|
|
384
382
|
// TS FormData isn't an Iterable sadly
|
|
385
383
|
current.forEach((value, key) => {
|
|
@@ -422,6 +420,44 @@ function generateBoxedNode(
|
|
|
422
420
|
};
|
|
423
421
|
}
|
|
424
422
|
|
|
423
|
+
function generateEventNode(ctx: ParserContext, id: number, current: Event): SerovalEventNode {
|
|
424
|
+
return {
|
|
425
|
+
t: SerovalNodeType.Event,
|
|
426
|
+
i: id,
|
|
427
|
+
s: serializeString(current.type),
|
|
428
|
+
l: undefined,
|
|
429
|
+
c: undefined,
|
|
430
|
+
m: undefined,
|
|
431
|
+
p: undefined,
|
|
432
|
+
e: undefined,
|
|
433
|
+
a: undefined,
|
|
434
|
+
f: parseObject(ctx, createEventOptions(current)),
|
|
435
|
+
b: undefined,
|
|
436
|
+
o: undefined,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function generateCustomEventNode(
|
|
441
|
+
ctx: ParserContext,
|
|
442
|
+
id: number,
|
|
443
|
+
current: CustomEvent,
|
|
444
|
+
): SerovalCustomEventNode {
|
|
445
|
+
return {
|
|
446
|
+
t: SerovalNodeType.CustomEvent,
|
|
447
|
+
i: id,
|
|
448
|
+
s: serializeString(current.type),
|
|
449
|
+
l: undefined,
|
|
450
|
+
c: undefined,
|
|
451
|
+
m: undefined,
|
|
452
|
+
p: undefined,
|
|
453
|
+
e: undefined,
|
|
454
|
+
a: undefined,
|
|
455
|
+
f: parseObject(ctx, createCustomEventOptions(current)),
|
|
456
|
+
b: undefined,
|
|
457
|
+
o: undefined,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
425
461
|
function parseObject(
|
|
426
462
|
ctx: ParserContext,
|
|
427
463
|
current: object | null,
|
|
@@ -442,40 +478,18 @@ function parseObject(
|
|
|
442
478
|
if (Array.isArray(current)) {
|
|
443
479
|
return generateArrayNode(ctx, id, current);
|
|
444
480
|
}
|
|
481
|
+
const currentClass = current.constructor;
|
|
445
482
|
// Fast path
|
|
446
|
-
switch (
|
|
483
|
+
switch (currentClass) {
|
|
447
484
|
case Number:
|
|
448
485
|
case Boolean:
|
|
449
486
|
case String:
|
|
450
487
|
case BigInt:
|
|
451
|
-
case Function:
|
|
452
|
-
case Symbol:
|
|
453
488
|
return generateBoxedNode(ctx, id, current);
|
|
454
489
|
case Date:
|
|
455
490
|
return createDateNode(id, current as unknown as Date);
|
|
456
491
|
case RegExp:
|
|
457
492
|
return createRegExpNode(id, current as unknown as RegExp);
|
|
458
|
-
case ArrayBuffer:
|
|
459
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
460
|
-
case Int8Array:
|
|
461
|
-
case Int16Array:
|
|
462
|
-
case Int32Array:
|
|
463
|
-
case Uint8Array:
|
|
464
|
-
case Uint16Array:
|
|
465
|
-
case Uint32Array:
|
|
466
|
-
case Uint8ClampedArray:
|
|
467
|
-
case Float32Array:
|
|
468
|
-
case Float64Array:
|
|
469
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
470
|
-
case BigInt64Array:
|
|
471
|
-
case BigUint64Array:
|
|
472
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
473
|
-
case DataView:
|
|
474
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
475
|
-
case Map:
|
|
476
|
-
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
477
|
-
case Set:
|
|
478
|
-
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
479
493
|
case Object:
|
|
480
494
|
return generateObjectNode(
|
|
481
495
|
ctx,
|
|
@@ -490,12 +504,6 @@ function parseObject(
|
|
|
490
504
|
current as unknown as Record<string, unknown>,
|
|
491
505
|
true,
|
|
492
506
|
);
|
|
493
|
-
case AggregateError:
|
|
494
|
-
// Compile-down AggregateError to Error if disabled
|
|
495
|
-
if (ctx.features & Feature.AggregateError) {
|
|
496
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
497
|
-
}
|
|
498
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
499
507
|
case Error:
|
|
500
508
|
case EvalError:
|
|
501
509
|
case RangeError:
|
|
@@ -504,32 +512,86 @@ function parseObject(
|
|
|
504
512
|
case TypeError:
|
|
505
513
|
case URIError:
|
|
506
514
|
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
507
|
-
case URL:
|
|
508
|
-
return createURLNode(ctx, id, current as unknown as URL);
|
|
509
|
-
case URLSearchParams:
|
|
510
|
-
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
511
|
-
case Headers:
|
|
512
|
-
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
513
|
-
case FormData:
|
|
514
|
-
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
515
515
|
default:
|
|
516
516
|
break;
|
|
517
517
|
}
|
|
518
|
-
//
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
518
|
+
// Typed Arrays
|
|
519
|
+
if (ctx.features & Feature.TypedArray) {
|
|
520
|
+
switch (currentClass) {
|
|
521
|
+
case ArrayBuffer:
|
|
522
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
523
|
+
case Int8Array:
|
|
524
|
+
case Int16Array:
|
|
525
|
+
case Int32Array:
|
|
526
|
+
case Uint8Array:
|
|
527
|
+
case Uint16Array:
|
|
528
|
+
case Uint32Array:
|
|
529
|
+
case Uint8ClampedArray:
|
|
530
|
+
case Float32Array:
|
|
531
|
+
case Float64Array:
|
|
532
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
533
|
+
case DataView:
|
|
534
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
535
|
+
default:
|
|
536
|
+
break;
|
|
523
537
|
}
|
|
524
|
-
return generateErrorNode(ctx, id, current);
|
|
525
538
|
}
|
|
539
|
+
// BigInt Typed Arrays
|
|
540
|
+
if ((ctx.features & BIGINT_FLAG) === BIGINT_FLAG) {
|
|
541
|
+
switch (currentClass) {
|
|
542
|
+
case BigInt64Array:
|
|
543
|
+
case BigUint64Array:
|
|
544
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
545
|
+
default:
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
// ES Collection
|
|
550
|
+
if (ctx.features & Feature.Map && currentClass === Map) {
|
|
551
|
+
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
552
|
+
}
|
|
553
|
+
if (ctx.features & Feature.Set && currentClass === Set) {
|
|
554
|
+
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
555
|
+
}
|
|
556
|
+
// Web APIs
|
|
557
|
+
if (ctx.features & Feature.WebAPI) {
|
|
558
|
+
switch (currentClass) {
|
|
559
|
+
case URL:
|
|
560
|
+
return createURLNode(id, current as unknown as URL);
|
|
561
|
+
case URLSearchParams:
|
|
562
|
+
return createURLSearchParamsNode(id, current as unknown as URLSearchParams);
|
|
563
|
+
case Headers:
|
|
564
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
565
|
+
case FormData:
|
|
566
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
567
|
+
case Event:
|
|
568
|
+
return generateEventNode(ctx, id, current as unknown as Event);
|
|
569
|
+
case CustomEvent:
|
|
570
|
+
return generateCustomEventNode(ctx, id, current as unknown as CustomEvent);
|
|
571
|
+
case DOMException:
|
|
572
|
+
return createDOMExceptionNode(id, current as unknown as DOMException);
|
|
573
|
+
default:
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (
|
|
578
|
+
(ctx.features & Feature.AggregateError)
|
|
579
|
+
&& (
|
|
580
|
+
currentClass === AggregateError
|
|
581
|
+
|| current instanceof AggregateError
|
|
582
|
+
)
|
|
583
|
+
) {
|
|
584
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
585
|
+
}
|
|
586
|
+
// Slow path. We only need to handle Errors and Iterators
|
|
587
|
+
// since they have very broad implementations.
|
|
526
588
|
if (current instanceof Error) {
|
|
527
589
|
return generateErrorNode(ctx, id, current);
|
|
528
590
|
}
|
|
529
591
|
// Generator functions don't have a global constructor
|
|
530
592
|
// despite existing
|
|
531
|
-
if (Symbol.iterator in current) {
|
|
532
|
-
return generateObjectNode(ctx, id, current, !!
|
|
593
|
+
if ((ctx.features & Feature.Symbol) && Symbol.iterator in current) {
|
|
594
|
+
return generateObjectNode(ctx, id, current, !!currentClass);
|
|
533
595
|
}
|
|
534
596
|
throw new UnsupportedTypeError(current);
|
|
535
597
|
}
|
|
@@ -538,23 +600,26 @@ export default function parseSync<T>(
|
|
|
538
600
|
ctx: ParserContext,
|
|
539
601
|
current: T,
|
|
540
602
|
): SerovalSyncNode {
|
|
541
|
-
|
|
603
|
+
const t = typeof current;
|
|
604
|
+
if (ctx.features & Feature.BigInt && t === 'bigint') {
|
|
605
|
+
return createBigIntNode(ctx, current as bigint);
|
|
606
|
+
}
|
|
607
|
+
switch (t) {
|
|
542
608
|
case 'boolean':
|
|
543
609
|
return current ? TRUE_NODE : FALSE_NODE;
|
|
544
610
|
case 'undefined':
|
|
545
611
|
return UNDEFINED_NODE;
|
|
546
612
|
case 'string':
|
|
547
|
-
return createStringNode(current);
|
|
613
|
+
return createStringNode(current as string);
|
|
548
614
|
case 'number':
|
|
549
|
-
return createNumberNode(current);
|
|
550
|
-
case 'bigint':
|
|
551
|
-
return createBigIntNode(ctx, current);
|
|
615
|
+
return createNumberNode(current as number);
|
|
552
616
|
case 'object':
|
|
553
|
-
return parseObject(ctx, current);
|
|
617
|
+
return parseObject(ctx, current as object);
|
|
554
618
|
case 'symbol':
|
|
555
|
-
return createSymbolNode(ctx, current);
|
|
619
|
+
return createSymbolNode(ctx, current as symbol);
|
|
556
620
|
case 'function':
|
|
557
|
-
|
|
621
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
622
|
+
return createFunctionNode(ctx, current as Function);
|
|
558
623
|
default:
|
|
559
624
|
throw new UnsupportedTypeError(current);
|
|
560
625
|
}
|
package/src/core/types.ts
CHANGED
|
@@ -340,6 +340,48 @@ export interface SerovalReadableStreamErrorNode extends SerovalBaseNode {
|
|
|
340
340
|
f: SerovalNode;
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
export interface SerovalRequestNode extends SerovalBaseNode {
|
|
344
|
+
t: SerovalNodeType.Request;
|
|
345
|
+
i: number;
|
|
346
|
+
// Request URL
|
|
347
|
+
s: string;
|
|
348
|
+
// This is just a shortcut for serializing the option fields
|
|
349
|
+
f: SerovalNode;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export interface SerovalResponseNode extends SerovalBaseNode {
|
|
353
|
+
t: SerovalNodeType.Response;
|
|
354
|
+
i: number;
|
|
355
|
+
// This is just a shortcut for serializing the option fields
|
|
356
|
+
a: [body: SerovalNode, options: SerovalNode];
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export interface SerovalEventNode extends SerovalBaseNode {
|
|
360
|
+
t: SerovalNodeType.Event;
|
|
361
|
+
i: number;
|
|
362
|
+
// Event type
|
|
363
|
+
s: string;
|
|
364
|
+
// Event options
|
|
365
|
+
f: SerovalNode;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface SerovalCustomEventNode extends SerovalBaseNode {
|
|
369
|
+
t: SerovalNodeType.CustomEvent;
|
|
370
|
+
i: number;
|
|
371
|
+
// Event type
|
|
372
|
+
s: string;
|
|
373
|
+
f: SerovalNode;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export interface SerovalDOMExceptionNode extends SerovalBaseNode {
|
|
377
|
+
t: SerovalNodeType.DOMException;
|
|
378
|
+
i: number;
|
|
379
|
+
// Message
|
|
380
|
+
s: string;
|
|
381
|
+
// name
|
|
382
|
+
c: string;
|
|
383
|
+
}
|
|
384
|
+
|
|
343
385
|
export type SerovalSyncNode =
|
|
344
386
|
| SerovalPrimitiveNode
|
|
345
387
|
| SerovalIndexedValueNode
|
|
@@ -362,7 +404,10 @@ export type SerovalSyncNode =
|
|
|
362
404
|
| SerovalFileNode
|
|
363
405
|
| SerovalHeadersNode
|
|
364
406
|
| SerovalFormDataNode
|
|
365
|
-
| SerovalBoxedNode
|
|
407
|
+
| SerovalBoxedNode
|
|
408
|
+
| SerovalEventNode
|
|
409
|
+
| SerovalCustomEventNode
|
|
410
|
+
| SerovalDOMExceptionNode;
|
|
366
411
|
|
|
367
412
|
export type SerovalAsyncNode =
|
|
368
413
|
| SerovalPromiseNode
|
|
@@ -374,7 +419,9 @@ export type SerovalAsyncNode =
|
|
|
374
419
|
| SerovalReadableStreamConstructorNode
|
|
375
420
|
| SerovalReadableStreamEnqueueNode
|
|
376
421
|
| SerovalReadableStreamCloseNode
|
|
377
|
-
| SerovalReadableStreamErrorNode
|
|
422
|
+
| SerovalReadableStreamErrorNode
|
|
423
|
+
| SerovalRequestNode
|
|
424
|
+
| SerovalResponseNode;
|
|
378
425
|
|
|
379
426
|
export type SerovalNode =
|
|
380
427
|
| SerovalSyncNode
|
package/src/core/web-api.ts
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import UnsupportedTypeError from './UnsupportedTypeError';
|
|
2
|
-
import assert from './assert';
|
|
3
|
-
import { Feature } from './compat';
|
|
4
1
|
import { SerovalNodeType } from './constants';
|
|
5
|
-
import type { BaseParserContext } from './context';
|
|
6
2
|
import { serializeString } from './string';
|
|
7
|
-
import type { SerovalURLNode, SerovalURLSearchParamsNode } from './types';
|
|
3
|
+
import type { SerovalDOMExceptionNode, SerovalURLNode, SerovalURLSearchParamsNode } from './types';
|
|
8
4
|
|
|
9
5
|
export function createURLNode(
|
|
10
|
-
ctx: BaseParserContext,
|
|
11
6
|
id: number,
|
|
12
7
|
current: URL,
|
|
13
8
|
): SerovalURLNode {
|
|
14
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
15
9
|
return {
|
|
16
10
|
t: SerovalNodeType.URL,
|
|
17
11
|
i: id,
|
|
@@ -29,11 +23,9 @@ export function createURLNode(
|
|
|
29
23
|
}
|
|
30
24
|
|
|
31
25
|
export function createURLSearchParamsNode(
|
|
32
|
-
ctx: BaseParserContext,
|
|
33
26
|
id: number,
|
|
34
27
|
current: URLSearchParams,
|
|
35
28
|
): SerovalURLSearchParamsNode {
|
|
36
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
37
29
|
return {
|
|
38
30
|
t: SerovalNodeType.URLSearchParams,
|
|
39
31
|
i: id,
|
|
@@ -49,3 +41,23 @@ export function createURLSearchParamsNode(
|
|
|
49
41
|
o: undefined,
|
|
50
42
|
};
|
|
51
43
|
}
|
|
44
|
+
|
|
45
|
+
export function createDOMExceptionNode(
|
|
46
|
+
id: number,
|
|
47
|
+
current: DOMException,
|
|
48
|
+
): SerovalDOMExceptionNode {
|
|
49
|
+
return {
|
|
50
|
+
t: SerovalNodeType.DOMException,
|
|
51
|
+
i: id,
|
|
52
|
+
s: serializeString(current.message),
|
|
53
|
+
l: undefined,
|
|
54
|
+
c: serializeString(current.name),
|
|
55
|
+
m: undefined,
|
|
56
|
+
p: undefined,
|
|
57
|
+
e: undefined,
|
|
58
|
+
a: undefined,
|
|
59
|
+
f: undefined,
|
|
60
|
+
b: undefined,
|
|
61
|
+
o: undefined,
|
|
62
|
+
};
|
|
63
|
+
}
|