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/cross/stream.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-await-in-loop */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
3
|
-
import
|
|
4
|
-
import { Feature } from '../compat';
|
|
3
|
+
import { BIGINT_FLAG, Feature } from '../compat';
|
|
5
4
|
import type { StreamingCrossParserContext } from './context';
|
|
6
5
|
import {
|
|
7
6
|
createCrossIndexedValue, popPendingState, pushPendingState,
|
|
@@ -50,6 +49,10 @@ import type {
|
|
|
50
49
|
SerovalPromiseConstructorNode,
|
|
51
50
|
SerovalSetNode,
|
|
52
51
|
SerovalReadableStreamConstructorNode,
|
|
52
|
+
SerovalRequestNode,
|
|
53
|
+
SerovalResponseNode,
|
|
54
|
+
SerovalEventNode,
|
|
55
|
+
SerovalCustomEventNode,
|
|
53
56
|
} from '../types';
|
|
54
57
|
import {
|
|
55
58
|
SerovalObjectRecordSpecialKey,
|
|
@@ -69,7 +72,13 @@ import {
|
|
|
69
72
|
createRegExpNode,
|
|
70
73
|
createStringNode,
|
|
71
74
|
} from '../base-primitives';
|
|
72
|
-
import { createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
75
|
+
import { createDOMExceptionNode, createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
76
|
+
import {
|
|
77
|
+
createCustomEventOptions,
|
|
78
|
+
createEventOptions,
|
|
79
|
+
createRequestOptions,
|
|
80
|
+
createResponseOptions,
|
|
81
|
+
} from '../constructors';
|
|
73
82
|
|
|
74
83
|
type ObjectLikeNode =
|
|
75
84
|
| SerovalObjectNode
|
|
@@ -128,7 +137,6 @@ function generateMapNode(
|
|
|
128
137
|
id: number,
|
|
129
138
|
current: Map<unknown, unknown>,
|
|
130
139
|
): SerovalMapNode {
|
|
131
|
-
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
132
140
|
const len = current.size;
|
|
133
141
|
const keyNodes = new Array<SerovalNode>(len);
|
|
134
142
|
const valueNodes = new Array<SerovalNode>(len);
|
|
@@ -173,7 +181,6 @@ function generateSetNode(
|
|
|
173
181
|
id: number,
|
|
174
182
|
current: Set<unknown>,
|
|
175
183
|
): SerovalSetNode {
|
|
176
|
-
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
177
184
|
const len = current.size;
|
|
178
185
|
const nodes = new Array<SerovalNode>(len);
|
|
179
186
|
const deferred = new Array<unknown>(len);
|
|
@@ -300,7 +307,6 @@ function generatePromiseNode(
|
|
|
300
307
|
id: number,
|
|
301
308
|
current: Promise<unknown>,
|
|
302
309
|
): SerovalPromiseConstructorNode {
|
|
303
|
-
assert(ctx.features & Feature.Promise, new UnsupportedTypeError(current));
|
|
304
310
|
current.then(
|
|
305
311
|
(data) => {
|
|
306
312
|
if (ctx.alive) {
|
|
@@ -435,7 +441,6 @@ function generateHeadersNode(
|
|
|
435
441
|
id: number,
|
|
436
442
|
current: Headers,
|
|
437
443
|
): SerovalHeadersNode {
|
|
438
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
439
444
|
const items: Record<string, string> = {};
|
|
440
445
|
current.forEach((value, key) => {
|
|
441
446
|
items[key] = value;
|
|
@@ -461,7 +466,6 @@ function generateFormDataNode(
|
|
|
461
466
|
id: number,
|
|
462
467
|
current: FormData,
|
|
463
468
|
): SerovalFormDataNode {
|
|
464
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
465
469
|
const items: Record<string, FormDataEntryValue> = {};
|
|
466
470
|
current.forEach((value, key) => {
|
|
467
471
|
items[key] = value;
|
|
@@ -508,7 +512,6 @@ function generateReadableStreamNode(
|
|
|
508
512
|
id: number,
|
|
509
513
|
current: ReadableStream<unknown>,
|
|
510
514
|
): SerovalReadableStreamConstructorNode {
|
|
511
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
512
515
|
const reader = current.getReader();
|
|
513
516
|
pushPendingState(ctx);
|
|
514
517
|
|
|
@@ -591,6 +594,98 @@ function generateReadableStreamNode(
|
|
|
591
594
|
};
|
|
592
595
|
}
|
|
593
596
|
|
|
597
|
+
function generateRequestNode(
|
|
598
|
+
ctx: StreamingCrossParserContext,
|
|
599
|
+
id: number,
|
|
600
|
+
current: Request,
|
|
601
|
+
): SerovalRequestNode {
|
|
602
|
+
return {
|
|
603
|
+
t: SerovalNodeType.Request,
|
|
604
|
+
i: id,
|
|
605
|
+
s: serializeString(current.url),
|
|
606
|
+
l: undefined,
|
|
607
|
+
c: undefined,
|
|
608
|
+
m: undefined,
|
|
609
|
+
p: undefined,
|
|
610
|
+
e: undefined,
|
|
611
|
+
f: parseObject(
|
|
612
|
+
ctx,
|
|
613
|
+
createRequestOptions(current, current.clone().body),
|
|
614
|
+
),
|
|
615
|
+
a: undefined,
|
|
616
|
+
b: undefined,
|
|
617
|
+
o: undefined,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function generateResponseNode(
|
|
622
|
+
ctx: StreamingCrossParserContext,
|
|
623
|
+
id: number,
|
|
624
|
+
current: Response,
|
|
625
|
+
): SerovalResponseNode {
|
|
626
|
+
return {
|
|
627
|
+
t: SerovalNodeType.Response,
|
|
628
|
+
i: id,
|
|
629
|
+
s: undefined,
|
|
630
|
+
l: undefined,
|
|
631
|
+
c: undefined,
|
|
632
|
+
m: undefined,
|
|
633
|
+
p: undefined,
|
|
634
|
+
e: undefined,
|
|
635
|
+
f: undefined,
|
|
636
|
+
a: [
|
|
637
|
+
current.body
|
|
638
|
+
? parseObject(ctx, current.clone().body)
|
|
639
|
+
: NULL_NODE,
|
|
640
|
+
parseObject(ctx, createResponseOptions(current)),
|
|
641
|
+
],
|
|
642
|
+
b: undefined,
|
|
643
|
+
o: undefined,
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function generateEventNode(
|
|
648
|
+
ctx: StreamingCrossParserContext,
|
|
649
|
+
id: number,
|
|
650
|
+
current: Event,
|
|
651
|
+
): SerovalEventNode {
|
|
652
|
+
return {
|
|
653
|
+
t: SerovalNodeType.Event,
|
|
654
|
+
i: id,
|
|
655
|
+
s: serializeString(current.type),
|
|
656
|
+
l: undefined,
|
|
657
|
+
c: undefined,
|
|
658
|
+
m: undefined,
|
|
659
|
+
p: undefined,
|
|
660
|
+
e: undefined,
|
|
661
|
+
a: undefined,
|
|
662
|
+
f: parseObject(ctx, createEventOptions(current)),
|
|
663
|
+
b: undefined,
|
|
664
|
+
o: undefined,
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
function generateCustomEventNode(
|
|
669
|
+
ctx: StreamingCrossParserContext,
|
|
670
|
+
id: number,
|
|
671
|
+
current: CustomEvent,
|
|
672
|
+
): SerovalCustomEventNode {
|
|
673
|
+
return {
|
|
674
|
+
t: SerovalNodeType.CustomEvent,
|
|
675
|
+
i: id,
|
|
676
|
+
s: serializeString(current.type),
|
|
677
|
+
l: undefined,
|
|
678
|
+
c: undefined,
|
|
679
|
+
m: undefined,
|
|
680
|
+
p: undefined,
|
|
681
|
+
e: undefined,
|
|
682
|
+
a: undefined,
|
|
683
|
+
f: parseObject(ctx, createCustomEventOptions(current)),
|
|
684
|
+
b: undefined,
|
|
685
|
+
o: undefined,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
594
689
|
function parseObject(
|
|
595
690
|
ctx: StreamingCrossParserContext,
|
|
596
691
|
current: object | null,
|
|
@@ -612,7 +707,9 @@ function parseObject(
|
|
|
612
707
|
if (Array.isArray(current)) {
|
|
613
708
|
return generateArrayNode(ctx, id, current);
|
|
614
709
|
}
|
|
615
|
-
|
|
710
|
+
const currentClass = current.constructor;
|
|
711
|
+
// Fast path
|
|
712
|
+
switch (currentClass) {
|
|
616
713
|
case Number:
|
|
617
714
|
case Boolean:
|
|
618
715
|
case String:
|
|
@@ -624,56 +721,20 @@ function parseObject(
|
|
|
624
721
|
return createDateNode(id, current as unknown as Date);
|
|
625
722
|
case RegExp:
|
|
626
723
|
return createRegExpNode(id, current as unknown as RegExp);
|
|
627
|
-
case Promise:
|
|
628
|
-
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
629
|
-
case ArrayBuffer:
|
|
630
|
-
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
631
|
-
case Int8Array:
|
|
632
|
-
case Int16Array:
|
|
633
|
-
case Int32Array:
|
|
634
|
-
case Uint8Array:
|
|
635
|
-
case Uint16Array:
|
|
636
|
-
case Uint32Array:
|
|
637
|
-
case Uint8ClampedArray:
|
|
638
|
-
case Float32Array:
|
|
639
|
-
case Float64Array:
|
|
640
|
-
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
641
|
-
case BigInt64Array:
|
|
642
|
-
case BigUint64Array:
|
|
643
|
-
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
644
|
-
case DataView:
|
|
645
|
-
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
646
|
-
case Map:
|
|
647
|
-
return generateMapNode(
|
|
648
|
-
ctx,
|
|
649
|
-
id,
|
|
650
|
-
current as unknown as Map<unknown, unknown>,
|
|
651
|
-
);
|
|
652
|
-
case Set:
|
|
653
|
-
return generateSetNode(
|
|
654
|
-
ctx,
|
|
655
|
-
id,
|
|
656
|
-
current as unknown as Set<unknown>,
|
|
657
|
-
);
|
|
658
724
|
case Object:
|
|
659
725
|
return generateObjectNode(
|
|
660
726
|
ctx,
|
|
661
727
|
id,
|
|
662
|
-
current as Record<string, unknown>,
|
|
728
|
+
current as unknown as Record<string, unknown>,
|
|
663
729
|
false,
|
|
664
730
|
);
|
|
665
731
|
case undefined:
|
|
666
732
|
return generateObjectNode(
|
|
667
733
|
ctx,
|
|
668
734
|
id,
|
|
669
|
-
current as Record<string, unknown>,
|
|
735
|
+
current as unknown as Record<string, unknown>,
|
|
670
736
|
true,
|
|
671
737
|
);
|
|
672
|
-
case AggregateError:
|
|
673
|
-
if (ctx.features & Feature.AggregateError) {
|
|
674
|
-
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
675
|
-
}
|
|
676
|
-
return generateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
677
738
|
case Error:
|
|
678
739
|
case EvalError:
|
|
679
740
|
case RangeError:
|
|
@@ -682,38 +743,98 @@ function parseObject(
|
|
|
682
743
|
case TypeError:
|
|
683
744
|
case URIError:
|
|
684
745
|
return generateErrorNode(ctx, id, current as unknown as Error);
|
|
685
|
-
case URL:
|
|
686
|
-
return createURLNode(ctx, id, current as unknown as URL);
|
|
687
|
-
case URLSearchParams:
|
|
688
|
-
return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
|
|
689
|
-
// case Blob:
|
|
690
|
-
// return createBlobNode(ctx, id, current as unknown as Blob);
|
|
691
|
-
// case File:
|
|
692
|
-
// return createFileNode(ctx, id, current as unknown as File);
|
|
693
|
-
case Headers:
|
|
694
|
-
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
695
|
-
case FormData:
|
|
696
|
-
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
697
|
-
case ReadableStream:
|
|
698
|
-
return generateReadableStreamNode(ctx, id, current as unknown as ReadableStream);
|
|
699
746
|
default:
|
|
700
747
|
break;
|
|
701
748
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
749
|
+
// Typed Arrays
|
|
750
|
+
if (ctx.features & Feature.TypedArray) {
|
|
751
|
+
switch (currentClass) {
|
|
752
|
+
case ArrayBuffer:
|
|
753
|
+
return createArrayBufferNode(id, current as unknown as ArrayBuffer);
|
|
754
|
+
case Int8Array:
|
|
755
|
+
case Int16Array:
|
|
756
|
+
case Int32Array:
|
|
757
|
+
case Uint8Array:
|
|
758
|
+
case Uint16Array:
|
|
759
|
+
case Uint32Array:
|
|
760
|
+
case Uint8ClampedArray:
|
|
761
|
+
case Float32Array:
|
|
762
|
+
case Float64Array:
|
|
763
|
+
return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
|
|
764
|
+
case DataView:
|
|
765
|
+
return createDataViewNode(ctx, id, current as unknown as DataView);
|
|
766
|
+
default:
|
|
767
|
+
break;
|
|
705
768
|
}
|
|
706
|
-
return generateErrorNode(ctx, id, current);
|
|
707
769
|
}
|
|
770
|
+
// BigInt Typed Arrays
|
|
771
|
+
if ((ctx.features & BIGINT_FLAG) === BIGINT_FLAG) {
|
|
772
|
+
switch (currentClass) {
|
|
773
|
+
case BigInt64Array:
|
|
774
|
+
case BigUint64Array:
|
|
775
|
+
return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
|
|
776
|
+
default:
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
// ES Collection
|
|
781
|
+
if (ctx.features & Feature.Map && currentClass === Map) {
|
|
782
|
+
return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
|
|
783
|
+
}
|
|
784
|
+
if (ctx.features & Feature.Set && currentClass === Set) {
|
|
785
|
+
return generateSetNode(ctx, id, current as unknown as Set<unknown>);
|
|
786
|
+
}
|
|
787
|
+
// Web APIs
|
|
788
|
+
if (ctx.features & Feature.WebAPI) {
|
|
789
|
+
switch (currentClass) {
|
|
790
|
+
case URL:
|
|
791
|
+
return createURLNode(id, current as unknown as URL);
|
|
792
|
+
case URLSearchParams:
|
|
793
|
+
return createURLSearchParamsNode(id, current as unknown as URLSearchParams);
|
|
794
|
+
case Headers:
|
|
795
|
+
return generateHeadersNode(ctx, id, current as unknown as Headers);
|
|
796
|
+
case FormData:
|
|
797
|
+
return generateFormDataNode(ctx, id, current as unknown as FormData);
|
|
798
|
+
case ReadableStream:
|
|
799
|
+
return generateReadableStreamNode(ctx, id, current as unknown as ReadableStream);
|
|
800
|
+
case Request:
|
|
801
|
+
return generateRequestNode(ctx, id, current as unknown as Request);
|
|
802
|
+
case Response:
|
|
803
|
+
return generateResponseNode(ctx, id, current as unknown as Response);
|
|
804
|
+
case Event:
|
|
805
|
+
return generateEventNode(ctx, id, current as unknown as Event);
|
|
806
|
+
case CustomEvent:
|
|
807
|
+
return generateCustomEventNode(ctx, id, current as unknown as CustomEvent);
|
|
808
|
+
case DOMException:
|
|
809
|
+
return createDOMExceptionNode(id, current as unknown as DOMException);
|
|
810
|
+
default:
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
if (
|
|
815
|
+
(ctx.features & Feature.AggregateError)
|
|
816
|
+
&& (
|
|
817
|
+
currentClass === AggregateError
|
|
818
|
+
|| current instanceof AggregateError
|
|
819
|
+
)
|
|
820
|
+
) {
|
|
821
|
+
return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
|
|
822
|
+
}
|
|
823
|
+
if (
|
|
824
|
+
(ctx.features & Feature.Promise)
|
|
825
|
+
&& (currentClass === Promise || current instanceof Promise)
|
|
826
|
+
) {
|
|
827
|
+
return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
|
|
828
|
+
}
|
|
829
|
+
// Slow path. We only need to handle Errors and Iterators
|
|
830
|
+
// since they have very broad implementations.
|
|
708
831
|
if (current instanceof Error) {
|
|
709
832
|
return generateErrorNode(ctx, id, current);
|
|
710
833
|
}
|
|
711
|
-
if (current instanceof Promise) {
|
|
712
|
-
return generatePromiseNode(ctx, id, current);
|
|
713
|
-
}
|
|
714
834
|
// Generator functions don't have a global constructor
|
|
715
|
-
|
|
716
|
-
|
|
835
|
+
// despite existing
|
|
836
|
+
if (ctx.features & Feature.Symbol && Symbol.iterator in current) {
|
|
837
|
+
return generateObjectNode(ctx, id, current, !!currentClass);
|
|
717
838
|
}
|
|
718
839
|
throw new UnsupportedTypeError(current);
|
|
719
840
|
}
|
|
@@ -722,23 +843,26 @@ export default function crossParseStream<T>(
|
|
|
722
843
|
ctx: StreamingCrossParserContext,
|
|
723
844
|
current: T,
|
|
724
845
|
): SerovalNode {
|
|
725
|
-
|
|
846
|
+
const t = typeof current;
|
|
847
|
+
if (ctx.features & Feature.BigInt && t === 'bigint') {
|
|
848
|
+
return createBigIntNode(ctx, current as bigint);
|
|
849
|
+
}
|
|
850
|
+
switch (t) {
|
|
726
851
|
case 'boolean':
|
|
727
852
|
return current ? TRUE_NODE : FALSE_NODE;
|
|
728
853
|
case 'undefined':
|
|
729
854
|
return UNDEFINED_NODE;
|
|
730
855
|
case 'string':
|
|
731
|
-
return createStringNode(current);
|
|
856
|
+
return createStringNode(current as string);
|
|
732
857
|
case 'number':
|
|
733
|
-
return createNumberNode(current);
|
|
734
|
-
case 'bigint':
|
|
735
|
-
return createBigIntNode(ctx, current);
|
|
858
|
+
return createNumberNode(current as number);
|
|
736
859
|
case 'object':
|
|
737
|
-
return parseObject(ctx, current);
|
|
860
|
+
return parseObject(ctx, current as object);
|
|
738
861
|
case 'symbol':
|
|
739
|
-
return createSymbolNode(ctx, current);
|
|
862
|
+
return createSymbolNode(ctx, current as symbol);
|
|
740
863
|
case 'function':
|
|
741
|
-
|
|
864
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
865
|
+
return createFunctionNode(ctx, current as Function);
|
|
742
866
|
default:
|
|
743
867
|
throw new UnsupportedTypeError(current);
|
|
744
868
|
}
|
package/src/core/cross/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 { createCrossIndexedValue, type CrossParserContext } from './context';
|
|
5
4
|
import { serializeString } from '../string';
|
|
6
5
|
import type { BigIntTypedArrayValue, TypedArrayValue } from '../../types';
|
|
@@ -31,7 +30,9 @@ import type {
|
|
|
31
30
|
SerovalAggregateErrorNode,
|
|
32
31
|
SerovalArrayNode,
|
|
33
32
|
SerovalBoxedNode,
|
|
33
|
+
SerovalCustomEventNode,
|
|
34
34
|
SerovalErrorNode,
|
|
35
|
+
SerovalEventNode,
|
|
35
36
|
SerovalFormDataNode,
|
|
36
37
|
SerovalHeadersNode,
|
|
37
38
|
SerovalMapNode,
|
|
@@ -57,7 +58,8 @@ import {
|
|
|
57
58
|
createRegExpNode,
|
|
58
59
|
createStringNode,
|
|
59
60
|
} from '../base-primitives';
|
|
60
|
-
import { createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
61
|
+
import { createDOMExceptionNode, createURLNode, createURLSearchParamsNode } from '../web-api';
|
|
62
|
+
import { createCustomEventOptions, createEventOptions } from '../constructors';
|
|
61
63
|
|
|
62
64
|
type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
|
|
63
65
|
|
|
@@ -110,7 +112,6 @@ function generateMapNode(
|
|
|
110
112
|
id: number,
|
|
111
113
|
current: Map<unknown, unknown>,
|
|
112
114
|
): SerovalMapNode {
|
|
113
|
-
assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
|
|
114
115
|
const len = current.size;
|
|
115
116
|
const keyNodes = new Array<SerovalSyncNode>(len);
|
|
116
117
|
const valueNodes = new Array<SerovalSyncNode>(len);
|
|
@@ -155,7 +156,6 @@ function generateSetNode(
|
|
|
155
156
|
id: number,
|
|
156
157
|
current: Set<unknown>,
|
|
157
158
|
): SerovalSetNode {
|
|
158
|
-
assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
|
|
159
159
|
const len = current.size;
|
|
160
160
|
const nodes = new Array<SerovalSyncNode>(len);
|
|
161
161
|
const deferred = new Array<unknown>(len);
|
|
@@ -350,7 +350,6 @@ function generateHeadersNode(
|
|
|
350
350
|
id: number,
|
|
351
351
|
current: Headers,
|
|
352
352
|
): SerovalHeadersNode {
|
|
353
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
354
353
|
const items: Record<string, string> = {};
|
|
355
354
|
// TS Headers not an Iterable
|
|
356
355
|
current.forEach((value, key) => {
|
|
@@ -377,7 +376,6 @@ function generateFormDataNode(
|
|
|
377
376
|
id: number,
|
|
378
377
|
current: FormData,
|
|
379
378
|
): SerovalFormDataNode {
|
|
380
|
-
assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
|
|
381
379
|
const items: Record<string, FormDataEntryValue> = {};
|
|
382
380
|
// TS FormData isn't an Iterable sadly
|
|
383
381
|
current.forEach((value, key) => {
|
|
@@ -420,6 +418,44 @@ function generateBoxedNode(
|
|
|
420
418
|
};
|
|
421
419
|
}
|
|
422
420
|
|
|
421
|
+
function generateEventNode(ctx: CrossParserContext, id: number, current: Event): SerovalEventNode {
|
|
422
|
+
return {
|
|
423
|
+
t: SerovalNodeType.Event,
|
|
424
|
+
i: id,
|
|
425
|
+
s: serializeString(current.type),
|
|
426
|
+
l: undefined,
|
|
427
|
+
c: undefined,
|
|
428
|
+
m: undefined,
|
|
429
|
+
p: undefined,
|
|
430
|
+
e: undefined,
|
|
431
|
+
a: undefined,
|
|
432
|
+
f: parseObject(ctx, createEventOptions(current)),
|
|
433
|
+
b: undefined,
|
|
434
|
+
o: undefined,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
function generateCustomEventNode(
|
|
439
|
+
ctx: CrossParserContext,
|
|
440
|
+
id: number,
|
|
441
|
+
current: CustomEvent,
|
|
442
|
+
): SerovalCustomEventNode {
|
|
443
|
+
return {
|
|
444
|
+
t: SerovalNodeType.CustomEvent,
|
|
445
|
+
i: id,
|
|
446
|
+
s: serializeString(current.type),
|
|
447
|
+
l: undefined,
|
|
448
|
+
c: undefined,
|
|
449
|
+
m: undefined,
|
|
450
|
+
p: undefined,
|
|
451
|
+
e: undefined,
|
|
452
|
+
a: undefined,
|
|
453
|
+
f: parseObject(ctx, createCustomEventOptions(current)),
|
|
454
|
+
b: undefined,
|
|
455
|
+
o: undefined,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
423
459
|
function parseObject(
|
|
424
460
|
ctx: CrossParserContext,
|
|
425
461
|
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 crossParseSync<T>(
|
|
|
538
600
|
ctx: CrossParserContext,
|
|
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
|
}
|