seroval 0.10.3 → 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.
@@ -1,7 +1,6 @@
1
1
  /* eslint-disable no-await-in-loop */
2
2
  /* eslint-disable @typescript-eslint/no-use-before-define */
3
- import assert from '../assert';
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
- switch (current.constructor) {
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
- if (current instanceof AggregateError) {
703
- if (ctx.features & Feature.AggregateError) {
704
- return generateAggregateErrorNode(ctx, id, current);
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
- if (Symbol.iterator in current) {
716
- return generateObjectNode(ctx, id, current, !!current.constructor);
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
- switch (typeof current) {
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
- return createFunctionNode(ctx, current);
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
  }
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-use-before-define */
2
- import assert from '../assert';
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 (current.constructor) {
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
- // Slow path. We only need to handle Errors and Iterators
519
- // since they have very broad implementations.
520
- if (current instanceof AggregateError) {
521
- if (ctx.features & Feature.AggregateError) {
522
- return generateAggregateErrorNode(ctx, id, current);
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, !!current.constructor);
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
- switch (typeof current) {
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
- return createFunctionNode(ctx, current);
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
  }