seroval 0.4.0-alpha.0 → 0.4.0-alpha.2
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 +213 -215
- package/dist/cjs/development/index.cjs.map +3 -3
- package/dist/cjs/production/index.cjs +2 -2
- package/dist/esm/development/index.mjs +213 -215
- package/dist/esm/development/index.mjs.map +3 -3
- package/dist/esm/production/index.mjs +2 -2
- package/dist/types/compat.d.ts +12 -14
- package/package.json +2 -2
- package/src/compat.ts +35 -36
- package/src/index.ts +2 -1
- package/src/tree.ts +170 -159
package/src/tree.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
1
2
|
/* eslint-disable guard-for-in */
|
|
2
3
|
/* eslint-disable @typescript-eslint/no-for-in-array */
|
|
3
4
|
/* eslint-disable no-await-in-loop */
|
|
@@ -481,53 +482,53 @@ function generateSemiPrimitiveValue(
|
|
|
481
482
|
return [SerovalNodeType.RegExp, current, id];
|
|
482
483
|
}
|
|
483
484
|
if (constructorCheck<Int8Array>(current, Int8Array)) {
|
|
484
|
-
assert(ctx.features.has(
|
|
485
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Int8Array"');
|
|
485
486
|
return [SerovalNodeType.TypedArray, ['Int8Array', current], id];
|
|
486
487
|
}
|
|
487
488
|
if (constructorCheck<Int16Array>(current, Int16Array)) {
|
|
488
|
-
assert(ctx.features.has(
|
|
489
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Int16Array"');
|
|
489
490
|
return [SerovalNodeType.TypedArray, ['Int16Array', current], id];
|
|
490
491
|
}
|
|
491
492
|
if (constructorCheck<Int32Array>(current, Int32Array)) {
|
|
492
|
-
assert(ctx.features.has(
|
|
493
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Int32Array"');
|
|
493
494
|
return [SerovalNodeType.TypedArray, ['Int32Array', current], id];
|
|
494
495
|
}
|
|
495
496
|
if (constructorCheck<Uint8Array>(current, Uint8Array)) {
|
|
496
|
-
assert(ctx.features.has(
|
|
497
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Uint8Array"');
|
|
497
498
|
return [SerovalNodeType.TypedArray, ['Uint8Array', current], id];
|
|
498
499
|
}
|
|
499
500
|
if (constructorCheck<Uint16Array>(current, Uint16Array)) {
|
|
500
|
-
assert(ctx.features.has(
|
|
501
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Uint16Array"');
|
|
501
502
|
return [SerovalNodeType.TypedArray, ['Uint16Array', current], id];
|
|
502
503
|
}
|
|
503
504
|
if (constructorCheck<Uint32Array>(current, Uint32Array)) {
|
|
504
|
-
assert(ctx.features.has(
|
|
505
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Uint32Array"');
|
|
505
506
|
return [SerovalNodeType.TypedArray, ['Uint32Array', current], id];
|
|
506
507
|
}
|
|
507
508
|
if (constructorCheck<Uint8ClampedArray>(current, Uint8ClampedArray)) {
|
|
508
|
-
assert(ctx.features.has(
|
|
509
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Uint8ClampedArray"');
|
|
509
510
|
return [SerovalNodeType.TypedArray, ['Uint8ClampedArray', current], id];
|
|
510
511
|
}
|
|
511
512
|
if (constructorCheck<Float32Array>(current, Float32Array)) {
|
|
512
|
-
assert(ctx.features.has(
|
|
513
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Float32Array"');
|
|
513
514
|
return [SerovalNodeType.TypedArray, ['Float32Array', current], id];
|
|
514
515
|
}
|
|
515
516
|
if (constructorCheck<Float64Array>(current, Float64Array)) {
|
|
516
|
-
assert(ctx.features.has(
|
|
517
|
+
assert(ctx.features.has(Feature.TypedArray), 'Unsupported value type "Float64Array"');
|
|
517
518
|
return [SerovalNodeType.TypedArray, ['Float64Array', current], id];
|
|
518
519
|
}
|
|
519
520
|
if (constructorCheck<BigInt64Array>(current, BigInt64Array)) {
|
|
520
521
|
assert(
|
|
521
|
-
ctx.features.has(
|
|
522
|
-
&& ctx.features.has(
|
|
522
|
+
ctx.features.has(Feature.TypedArray)
|
|
523
|
+
&& ctx.features.has(Feature.BigInt),
|
|
523
524
|
'Unsupported value type "BigInt64Array"',
|
|
524
525
|
);
|
|
525
526
|
return [SerovalNodeType.TypedArray, ['BigInt64Array', current], id];
|
|
526
527
|
}
|
|
527
528
|
if (constructorCheck<BigUint64Array>(current, BigUint64Array)) {
|
|
528
529
|
assert(
|
|
529
|
-
ctx.features.has(
|
|
530
|
-
&& ctx.features.has(
|
|
530
|
+
ctx.features.has(Feature.TypedArray)
|
|
531
|
+
&& ctx.features.has(Feature.BigInt),
|
|
531
532
|
'Unsupported value type "BigUint64Array"',
|
|
532
533
|
);
|
|
533
534
|
return [SerovalNodeType.TypedArray, ['BigUint64Array', current], id];
|
|
@@ -535,35 +536,37 @@ function generateSemiPrimitiveValue(
|
|
|
535
536
|
return undefined;
|
|
536
537
|
}
|
|
537
538
|
|
|
539
|
+
function serializePropertiesSync(
|
|
540
|
+
ctx: SerializationContext,
|
|
541
|
+
properties: Record<string, unknown>,
|
|
542
|
+
): SerovalDictionaryNode {
|
|
543
|
+
const keyNodes: string[] = [];
|
|
544
|
+
const valueNodes: SerovalNode[] = [];
|
|
545
|
+
const deferredKeys: string[] = [];
|
|
546
|
+
const deferredValues: ServerValue[] = [];
|
|
547
|
+
const keys = Object.keys(properties);
|
|
548
|
+
let deferredSize = 0;
|
|
549
|
+
for (const key of keys) {
|
|
550
|
+
if (isIterable(properties[key])) {
|
|
551
|
+
deferredKeys.push(key);
|
|
552
|
+
deferredValues.push(properties[key] as ServerValue);
|
|
553
|
+
deferredSize++;
|
|
554
|
+
} else {
|
|
555
|
+
keyNodes.push(key);
|
|
556
|
+
valueNodes.push(generateTreeSync(ctx, properties[key] as ServerValue));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
560
|
+
keyNodes.push(deferredKeys[i]);
|
|
561
|
+
valueNodes.push(generateTreeSync(ctx, deferredValues[i]));
|
|
562
|
+
}
|
|
563
|
+
return [keyNodes, valueNodes, keys.length];
|
|
564
|
+
}
|
|
565
|
+
|
|
538
566
|
export function generateTreeSync(
|
|
539
567
|
ctx: SerializationContext,
|
|
540
568
|
current: ServerValue,
|
|
541
569
|
): SerovalNode {
|
|
542
|
-
function serializeProperties(
|
|
543
|
-
properties: Record<string, unknown>,
|
|
544
|
-
): SerovalDictionaryNode {
|
|
545
|
-
const keyNodes: string[] = [];
|
|
546
|
-
const valueNodes: SerovalNode[] = [];
|
|
547
|
-
const deferredKeys: string[] = [];
|
|
548
|
-
const deferredValues: ServerValue[] = [];
|
|
549
|
-
const keys = Object.keys(properties);
|
|
550
|
-
let deferredSize = 0;
|
|
551
|
-
for (const key of keys) {
|
|
552
|
-
if (isIterable(properties[key])) {
|
|
553
|
-
deferredKeys.push(key);
|
|
554
|
-
deferredValues.push(properties[key] as ServerValue);
|
|
555
|
-
deferredSize++;
|
|
556
|
-
} else {
|
|
557
|
-
keyNodes.push(key);
|
|
558
|
-
valueNodes.push(generateTreeSync(ctx, properties[key] as ServerValue));
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
562
|
-
keyNodes.push(deferredKeys[i]);
|
|
563
|
-
valueNodes.push(generateTreeSync(ctx, deferredValues[i]));
|
|
564
|
-
}
|
|
565
|
-
return [keyNodes, valueNodes, keys.length];
|
|
566
|
-
}
|
|
567
570
|
if (isPrimitive(current)) {
|
|
568
571
|
return [SerovalNodeType.Primitive, current];
|
|
569
572
|
}
|
|
@@ -578,7 +581,7 @@ export function generateTreeSync(
|
|
|
578
581
|
return semiPrimitive;
|
|
579
582
|
}
|
|
580
583
|
if (constructorCheck<Set<ServerValue>>(current, Set)) {
|
|
581
|
-
assert(ctx.features.has(
|
|
584
|
+
assert(ctx.features.has(Feature.Set), 'Unsupported type "Set"');
|
|
582
585
|
const nodes: SerovalNode[] = [];
|
|
583
586
|
const deferred: ServerValue[] = [];
|
|
584
587
|
for (const item of current.keys()) {
|
|
@@ -596,7 +599,7 @@ export function generateTreeSync(
|
|
|
596
599
|
return [SerovalNodeType.Set, nodes, id];
|
|
597
600
|
}
|
|
598
601
|
if (constructorCheck<Map<ServerValue, ServerValue>>(current, Map)) {
|
|
599
|
-
assert(ctx.features.has(
|
|
602
|
+
assert(ctx.features.has(Feature.Map), 'Unsupported type "Map"');
|
|
600
603
|
const keyNodes: SerovalNode[] = [];
|
|
601
604
|
const valueNodes: SerovalNode[] = [];
|
|
602
605
|
const deferredKey: ServerValue[] = [];
|
|
@@ -639,10 +642,10 @@ export function generateTreeSync(
|
|
|
639
642
|
}
|
|
640
643
|
return [SerovalNodeType.Array, nodes, id];
|
|
641
644
|
}
|
|
642
|
-
if (current instanceof AggregateError && ctx.features.has(
|
|
645
|
+
if (current instanceof AggregateError && ctx.features.has(Feature.AggregateError)) {
|
|
643
646
|
const options = getErrorOptions(current);
|
|
644
647
|
const optionsNode = options
|
|
645
|
-
?
|
|
648
|
+
? serializePropertiesSync(ctx, options)
|
|
646
649
|
: undefined;
|
|
647
650
|
const errorsNode = generateTreeSync(ctx, current.errors as ServerValue);
|
|
648
651
|
return [SerovalNodeType.AggregateError, [current.message, optionsNode, errorsNode], id];
|
|
@@ -650,7 +653,7 @@ export function generateTreeSync(
|
|
|
650
653
|
if (current instanceof Error) {
|
|
651
654
|
const options = getErrorOptions(current);
|
|
652
655
|
const optionsNode = options
|
|
653
|
-
?
|
|
656
|
+
? serializePropertiesSync(ctx, options)
|
|
654
657
|
: undefined;
|
|
655
658
|
return [
|
|
656
659
|
SerovalNodeType.Error,
|
|
@@ -659,11 +662,11 @@ export function generateTreeSync(
|
|
|
659
662
|
];
|
|
660
663
|
}
|
|
661
664
|
if (isIterable(current)) {
|
|
662
|
-
assert(ctx.features.has(
|
|
665
|
+
assert(ctx.features.has(Feature.SymbolIterator), 'Unsupported type "Iterable"');
|
|
663
666
|
const options = getIterableOptions(current);
|
|
664
667
|
return [SerovalNodeType.Iterable, [
|
|
665
668
|
// Parse options first before the items
|
|
666
|
-
options ?
|
|
669
|
+
options ? serializePropertiesSync(ctx, options) : undefined,
|
|
667
670
|
generateTreeSync(ctx, Array.from(current)),
|
|
668
671
|
], id];
|
|
669
672
|
}
|
|
@@ -671,42 +674,44 @@ export function generateTreeSync(
|
|
|
671
674
|
if (current.constructor === Object || empty) {
|
|
672
675
|
return [
|
|
673
676
|
empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
674
|
-
|
|
677
|
+
serializePropertiesSync(ctx, current as Record<string, unknown>),
|
|
675
678
|
id,
|
|
676
679
|
];
|
|
677
680
|
}
|
|
678
681
|
throw new Error('Unsupported value');
|
|
679
682
|
}
|
|
680
683
|
|
|
684
|
+
async function serializePropertiesAsync(
|
|
685
|
+
ctx: SerializationContext,
|
|
686
|
+
properties: Record<string, unknown>,
|
|
687
|
+
): Promise<SerovalDictionaryNode> {
|
|
688
|
+
const keyNodes: string[] = [];
|
|
689
|
+
const valueNodes: SerovalNode[] = [];
|
|
690
|
+
const deferredKeys: string[] = [];
|
|
691
|
+
const deferredValues: ServerValue[] = [];
|
|
692
|
+
const keys = Object.keys(properties);
|
|
693
|
+
let deferredSize = 0;
|
|
694
|
+
for (const key of keys) {
|
|
695
|
+
if (isIterable(properties[key])) {
|
|
696
|
+
deferredKeys.push(key);
|
|
697
|
+
deferredValues.push(properties[key] as ServerValue);
|
|
698
|
+
deferredSize++;
|
|
699
|
+
} else {
|
|
700
|
+
keyNodes.push(key);
|
|
701
|
+
valueNodes.push(await generateTreeAsync(ctx, properties[key] as ServerValue));
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
705
|
+
keyNodes.push(deferredKeys[i]);
|
|
706
|
+
valueNodes.push(await generateTreeAsync(ctx, deferredValues[i]));
|
|
707
|
+
}
|
|
708
|
+
return [keyNodes, valueNodes, keys.length];
|
|
709
|
+
}
|
|
710
|
+
|
|
681
711
|
export async function generateTreeAsync(
|
|
682
712
|
ctx: SerializationContext,
|
|
683
713
|
current: AsyncServerValue,
|
|
684
714
|
): Promise<SerovalNode> {
|
|
685
|
-
async function serializeProperties(
|
|
686
|
-
properties: Record<string, unknown>,
|
|
687
|
-
): Promise<SerovalDictionaryNode> {
|
|
688
|
-
const keyNodes: string[] = [];
|
|
689
|
-
const valueNodes: SerovalNode[] = [];
|
|
690
|
-
const deferredKeys: string[] = [];
|
|
691
|
-
const deferredValues: ServerValue[] = [];
|
|
692
|
-
const keys = Object.keys(properties);
|
|
693
|
-
let deferredSize = 0;
|
|
694
|
-
for (const key of keys) {
|
|
695
|
-
if (isIterable(properties[key])) {
|
|
696
|
-
deferredKeys.push(key);
|
|
697
|
-
deferredValues.push(properties[key] as ServerValue);
|
|
698
|
-
deferredSize++;
|
|
699
|
-
} else {
|
|
700
|
-
keyNodes.push(key);
|
|
701
|
-
valueNodes.push(await generateTreeAsync(ctx, properties[key] as ServerValue));
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
for (let i = 0; i < deferredSize; i++) {
|
|
705
|
-
keyNodes.push(deferredKeys[i]);
|
|
706
|
-
valueNodes.push(await generateTreeAsync(ctx, deferredValues[i]));
|
|
707
|
-
}
|
|
708
|
-
return [keyNodes, valueNodes, keys.length];
|
|
709
|
-
}
|
|
710
715
|
if (isPrimitive(current)) {
|
|
711
716
|
return [SerovalNodeType.Primitive, current];
|
|
712
717
|
}
|
|
@@ -719,7 +724,7 @@ export async function generateTreeAsync(
|
|
|
719
724
|
return semiPrimitive;
|
|
720
725
|
}
|
|
721
726
|
if (isPromise(current)) {
|
|
722
|
-
assert(ctx.features.has(
|
|
727
|
+
assert(ctx.features.has(Feature.Promise), 'Unsupported type "Promise"');
|
|
723
728
|
return current.then(async (value) => [
|
|
724
729
|
SerovalNodeType.Promise,
|
|
725
730
|
await generateTreeAsync(ctx, value),
|
|
@@ -727,7 +732,7 @@ export async function generateTreeAsync(
|
|
|
727
732
|
]);
|
|
728
733
|
}
|
|
729
734
|
if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
|
|
730
|
-
assert(ctx.features.has(
|
|
735
|
+
assert(ctx.features.has(Feature.Set), 'Unsupported type "Set"');
|
|
731
736
|
const nodes: SerovalNode[] = [];
|
|
732
737
|
const deferred: AsyncServerValue[] = [];
|
|
733
738
|
for (const item of current.keys()) {
|
|
@@ -743,7 +748,7 @@ export async function generateTreeAsync(
|
|
|
743
748
|
return [SerovalNodeType.Set, nodes, id];
|
|
744
749
|
}
|
|
745
750
|
if (constructorCheck<Map<AsyncServerValue, AsyncServerValue>>(current, Map)) {
|
|
746
|
-
assert(ctx.features.has(
|
|
751
|
+
assert(ctx.features.has(Feature.Map), 'Unsupported type "Map"');
|
|
747
752
|
const keyNodes: SerovalNode[] = [];
|
|
748
753
|
const valueNodes: SerovalNode[] = [];
|
|
749
754
|
const deferredKey: AsyncServerValue[] = [];
|
|
@@ -789,7 +794,7 @@ export async function generateTreeAsync(
|
|
|
789
794
|
if (current instanceof AggregateError) {
|
|
790
795
|
const options = getErrorOptions(current);
|
|
791
796
|
const optionsNode = options
|
|
792
|
-
? await
|
|
797
|
+
? await serializePropertiesAsync(ctx, options)
|
|
793
798
|
: undefined;
|
|
794
799
|
const errorsNode = await generateTreeAsync(ctx, current.errors as ServerValue);
|
|
795
800
|
return [SerovalNodeType.AggregateError, [current.message, optionsNode, errorsNode], id];
|
|
@@ -797,7 +802,7 @@ export async function generateTreeAsync(
|
|
|
797
802
|
if (current instanceof Error) {
|
|
798
803
|
const options = getErrorOptions(current);
|
|
799
804
|
const optionsNode = options
|
|
800
|
-
? await
|
|
805
|
+
? await serializePropertiesAsync(ctx, options)
|
|
801
806
|
: undefined;
|
|
802
807
|
return [
|
|
803
808
|
SerovalNodeType.Error,
|
|
@@ -806,11 +811,11 @@ export async function generateTreeAsync(
|
|
|
806
811
|
];
|
|
807
812
|
}
|
|
808
813
|
if (isIterable(current)) {
|
|
809
|
-
assert(ctx.features.has(
|
|
814
|
+
assert(ctx.features.has(Feature.SymbolIterator), 'Unsupported type "Iterable"');
|
|
810
815
|
const options = getIterableOptions(current);
|
|
811
816
|
return [SerovalNodeType.Iterable, [
|
|
812
817
|
options
|
|
813
|
-
? await
|
|
818
|
+
? await serializePropertiesAsync(ctx, options)
|
|
814
819
|
: undefined,
|
|
815
820
|
await generateTreeAsync(ctx, Array.from(current)),
|
|
816
821
|
], id];
|
|
@@ -819,7 +824,7 @@ export async function generateTreeAsync(
|
|
|
819
824
|
if (current.constructor === Object || empty) {
|
|
820
825
|
return [
|
|
821
826
|
empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
|
|
822
|
-
await
|
|
827
|
+
await serializePropertiesAsync(ctx, current as Record<string, unknown>),
|
|
823
828
|
id,
|
|
824
829
|
];
|
|
825
830
|
}
|
|
@@ -844,7 +849,7 @@ export function serializePrimitive(
|
|
|
844
849
|
return 'null';
|
|
845
850
|
}
|
|
846
851
|
if (typeof value === 'bigint') {
|
|
847
|
-
assert(ctx.features.has(
|
|
852
|
+
assert(ctx.features.has(Feature.BigInt), 'Unsupported type "BigInt"');
|
|
848
853
|
return `${value}n`;
|
|
849
854
|
}
|
|
850
855
|
if (typeof value === 'string') {
|
|
@@ -863,80 +868,86 @@ export function serializePrimitive(
|
|
|
863
868
|
return String(value);
|
|
864
869
|
}
|
|
865
870
|
|
|
866
|
-
|
|
871
|
+
const IDENTIFIER_CHECK = /^([$A-Z_][0-9A-Z_$]*)$/i;
|
|
872
|
+
|
|
873
|
+
function serializeAssignments(
|
|
867
874
|
ctx: SerializationContext,
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
) {
|
|
874
|
-
ctx.stack
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
) {
|
|
891
|
-
if (!Number.isNaN(check)) {
|
|
892
|
-
createObjectComputedAssign(ctx, targetRef, key, refParam);
|
|
893
|
-
} else {
|
|
894
|
-
createObjectIdentifierAssign(ctx, targetRef, key, refParam);
|
|
895
|
-
}
|
|
875
|
+
targetRef: number,
|
|
876
|
+
[keys, values, size]: SerovalDictionaryNode,
|
|
877
|
+
) {
|
|
878
|
+
ctx.stack.push(targetRef);
|
|
879
|
+
const mainAssignments: Assignment[] = [];
|
|
880
|
+
for (let i = 0; i < size; i++) {
|
|
881
|
+
const parentStack = ctx.stack;
|
|
882
|
+
ctx.stack = [];
|
|
883
|
+
const refParam = serializeTree(ctx, values[i]);
|
|
884
|
+
ctx.stack = parentStack;
|
|
885
|
+
const key = keys[i];
|
|
886
|
+
const check = Number(key);
|
|
887
|
+
// Test if key is a valid number or JS identifier
|
|
888
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
889
|
+
const parentAssignment = ctx.assignments;
|
|
890
|
+
ctx.assignments = mainAssignments;
|
|
891
|
+
if (
|
|
892
|
+
check >= 0
|
|
893
|
+
|| (Number.isNaN(check) && IDENTIFIER_CHECK.test(key))
|
|
894
|
+
) {
|
|
895
|
+
if (!Number.isNaN(check)) {
|
|
896
|
+
createObjectComputedAssign(ctx, targetRef, key, refParam);
|
|
896
897
|
} else {
|
|
897
|
-
|
|
898
|
+
createObjectIdentifierAssign(ctx, targetRef, key, refParam);
|
|
898
899
|
}
|
|
899
|
-
|
|
900
|
+
} else {
|
|
901
|
+
createObjectComputedAssign(ctx, targetRef, quote(key), refParam);
|
|
900
902
|
}
|
|
901
|
-
ctx.
|
|
902
|
-
return resolveAssignments(mainAssignments);
|
|
903
|
+
ctx.assignments = parentAssignment;
|
|
903
904
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
905
|
+
ctx.stack.pop();
|
|
906
|
+
return resolveAssignments(mainAssignments);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
function serializeObject(
|
|
910
|
+
ctx: SerializationContext,
|
|
911
|
+
sourceID: number,
|
|
912
|
+
[keys, values, size]: SerovalDictionaryNode,
|
|
913
|
+
) {
|
|
914
|
+
let result = '';
|
|
915
|
+
ctx.stack.push(sourceID);
|
|
916
|
+
for (let i = 0; i < size; i++) {
|
|
917
|
+
const key = keys[i];
|
|
918
|
+
const val = values[i];
|
|
919
|
+
const check = Number(key);
|
|
920
|
+
// Test if key is a valid number or JS identifier
|
|
921
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
922
|
+
if (
|
|
923
|
+
check >= 0
|
|
924
|
+
|| (Number.isNaN(check) && IDENTIFIER_CHECK.test(key))
|
|
925
|
+
) {
|
|
926
|
+
if (isReferenceInStack(ctx, val)) {
|
|
927
|
+
const refParam = getRefParam(ctx, val[1]);
|
|
928
|
+
if (!Number.isNaN(check)) {
|
|
929
|
+
createObjectComputedAssign(ctx, sourceID, key, refParam);
|
|
927
930
|
} else {
|
|
928
|
-
|
|
931
|
+
createObjectIdentifierAssign(ctx, sourceID, key, refParam);
|
|
929
932
|
}
|
|
930
|
-
} else if (isReferenceInStack(ctx, val)) {
|
|
931
|
-
const refParam = getRefParam(ctx, val[1]);
|
|
932
|
-
createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
|
|
933
933
|
} else {
|
|
934
|
-
result += `${
|
|
934
|
+
result += `${key}:${serializeTree(ctx, val)},`;
|
|
935
935
|
}
|
|
936
|
+
} else if (isReferenceInStack(ctx, val)) {
|
|
937
|
+
const refParam = getRefParam(ctx, val[1]);
|
|
938
|
+
createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
|
|
939
|
+
} else {
|
|
940
|
+
result += `${quote(key)}:${serializeTree(ctx, val)},`;
|
|
936
941
|
}
|
|
937
|
-
ctx.stack.pop();
|
|
938
|
-
return `{${result.substring(0, result.length - 1)}}`;
|
|
939
942
|
}
|
|
943
|
+
ctx.stack.pop();
|
|
944
|
+
return `{${result.substring(0, result.length - 1)}}`;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
export function serializeTree(
|
|
948
|
+
ctx: SerializationContext,
|
|
949
|
+
[type, value, id]: SerovalNode,
|
|
950
|
+
): string {
|
|
940
951
|
switch (type) {
|
|
941
952
|
case SerovalNodeType.Primitive:
|
|
942
953
|
return serializePrimitive(ctx, value);
|
|
@@ -1089,12 +1100,12 @@ export function serializeTree(
|
|
|
1089
1100
|
// either through class or custom properties
|
|
1090
1101
|
// Make sure to assign extra properties
|
|
1091
1102
|
if (value[1]) {
|
|
1092
|
-
if (ctx.features.has(
|
|
1093
|
-
const options = serializeObject(id, value[1]);
|
|
1103
|
+
if (ctx.features.has(Feature.ObjectAssign)) {
|
|
1104
|
+
const options = serializeObject(ctx, id, value[1]);
|
|
1094
1105
|
serialized = `Object.assign(${serialized},${options})`;
|
|
1095
1106
|
} else {
|
|
1096
1107
|
markRef(ctx, id);
|
|
1097
|
-
const assignments = serializeAssignments(id, value[1]);
|
|
1108
|
+
const assignments = serializeAssignments(ctx, id, value[1]);
|
|
1098
1109
|
if (assignments) {
|
|
1099
1110
|
const ref = getRefParam(ctx, id);
|
|
1100
1111
|
return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
|
|
@@ -1106,12 +1117,12 @@ export function serializeTree(
|
|
|
1106
1117
|
case SerovalNodeType.Error: {
|
|
1107
1118
|
let serialized = `new ${value[0]}(${quote(value[1])})`;
|
|
1108
1119
|
if (value[2]) {
|
|
1109
|
-
if (ctx.features.has(
|
|
1110
|
-
const options = serializeObject(id, value[2]);
|
|
1120
|
+
if (ctx.features.has(Feature.ObjectAssign)) {
|
|
1121
|
+
const options = serializeObject(ctx, id, value[2]);
|
|
1111
1122
|
serialized = `Object.assign(${serialized},${options})`;
|
|
1112
1123
|
} else {
|
|
1113
1124
|
markRef(ctx, id);
|
|
1114
|
-
const assignments = serializeAssignments(id, value[2]);
|
|
1125
|
+
const assignments = serializeAssignments(ctx, id, value[2]);
|
|
1115
1126
|
if (assignments) {
|
|
1116
1127
|
const ref = getRefParam(ctx, id);
|
|
1117
1128
|
return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
|
|
@@ -1126,25 +1137,25 @@ export function serializeTree(
|
|
|
1126
1137
|
const values = serializeTree(ctx, value[1]);
|
|
1127
1138
|
ctx.stack = parent;
|
|
1128
1139
|
let serialized: string;
|
|
1129
|
-
if (ctx.features.has(
|
|
1140
|
+
if (ctx.features.has(Feature.ArrayPrototypeValues)) {
|
|
1130
1141
|
serialized = `${values}.values()`;
|
|
1131
1142
|
} else {
|
|
1132
1143
|
serialized = `${values}[Symbol.iterator]()`;
|
|
1133
1144
|
}
|
|
1134
|
-
if (ctx.features.has(
|
|
1145
|
+
if (ctx.features.has(Feature.ArrowFunction)) {
|
|
1135
1146
|
serialized = `{[Symbol.iterator]:()=>${serialized}}`;
|
|
1136
|
-
} else if (ctx.features.has(
|
|
1147
|
+
} else if (ctx.features.has(Feature.MethodShorthand)) {
|
|
1137
1148
|
serialized = `{[Symbol.iterator](){return ${serialized}}}`;
|
|
1138
1149
|
} else {
|
|
1139
1150
|
serialized = `{[Symbol.iterator]:function(){return ${serialized}}}`;
|
|
1140
1151
|
}
|
|
1141
1152
|
if (value[0]) {
|
|
1142
|
-
if (ctx.features.has(
|
|
1143
|
-
const options = serializeObject(id, value[0]);
|
|
1153
|
+
if (ctx.features.has(Feature.ObjectAssign)) {
|
|
1154
|
+
const options = serializeObject(ctx, id, value[0]);
|
|
1144
1155
|
serialized = `Object.assign(${serialized},${options})`;
|
|
1145
1156
|
} else {
|
|
1146
1157
|
markRef(ctx, id);
|
|
1147
|
-
const assignments = serializeAssignments(id, value[0]);
|
|
1158
|
+
const assignments = serializeAssignments(ctx, id, value[0]);
|
|
1148
1159
|
if (assignments) {
|
|
1149
1160
|
const ref = getRefParam(ctx, id);
|
|
1150
1161
|
return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
|
|
@@ -1155,14 +1166,14 @@ export function serializeTree(
|
|
|
1155
1166
|
}
|
|
1156
1167
|
case SerovalNodeType.NullConstructor: {
|
|
1157
1168
|
let serialized = 'Object.create(null)';
|
|
1158
|
-
if (ctx.features.has(
|
|
1159
|
-
const fields = serializeObject(id, value);
|
|
1169
|
+
if (ctx.features.has(Feature.ObjectAssign)) {
|
|
1170
|
+
const fields = serializeObject(ctx, id, value);
|
|
1160
1171
|
if (fields !== '{}') {
|
|
1161
1172
|
serialized = `Object.assign(${serialized},${fields})`;
|
|
1162
1173
|
}
|
|
1163
1174
|
} else {
|
|
1164
1175
|
markRef(ctx, id);
|
|
1165
|
-
const assignments = serializeAssignments(id, value);
|
|
1176
|
+
const assignments = serializeAssignments(ctx, id, value);
|
|
1166
1177
|
if (assignments) {
|
|
1167
1178
|
const ref = getRefParam(ctx, id);
|
|
1168
1179
|
return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
|
|
@@ -1171,7 +1182,7 @@ export function serializeTree(
|
|
|
1171
1182
|
return assignRef(ctx, id, serialized);
|
|
1172
1183
|
}
|
|
1173
1184
|
case SerovalNodeType.Object:
|
|
1174
|
-
return assignRef(ctx, id, serializeObject(id, value));
|
|
1185
|
+
return assignRef(ctx, id, serializeObject(ctx, id, value));
|
|
1175
1186
|
default:
|
|
1176
1187
|
throw new Error('Unsupported type');
|
|
1177
1188
|
}
|