seroval 0.4.0-alpha.2 → 0.4.0-alpha.3
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 +82 -64
- package/dist/cjs/development/index.cjs.map +2 -2
- package/dist/cjs/production/index.cjs +2 -2
- package/dist/esm/development/index.mjs +82 -64
- package/dist/esm/development/index.mjs.map +2 -2
- package/dist/esm/production/index.mjs +2 -2
- package/package.json +2 -2
- package/src/tree.ts +87 -72
package/src/tree.ts
CHANGED
|
@@ -540,27 +540,30 @@ function serializePropertiesSync(
|
|
|
540
540
|
ctx: SerializationContext,
|
|
541
541
|
properties: Record<string, unknown>,
|
|
542
542
|
): SerovalDictionaryNode {
|
|
543
|
-
const keyNodes: string[] = [];
|
|
544
|
-
const valueNodes: SerovalNode[] = [];
|
|
545
|
-
const deferredKeys: string[] = [];
|
|
546
|
-
const deferredValues: ServerValue[] = [];
|
|
547
543
|
const keys = Object.keys(properties);
|
|
544
|
+
const size = keys.length;
|
|
545
|
+
const keyNodes = new Array<string>(size);
|
|
546
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
547
|
+
const deferredKeys = new Array<string>(size);
|
|
548
|
+
const deferredValues = new Array<ServerValue>(size);
|
|
548
549
|
let deferredSize = 0;
|
|
550
|
+
let nodesSize = 0;
|
|
549
551
|
for (const key of keys) {
|
|
550
552
|
if (isIterable(properties[key])) {
|
|
551
|
-
deferredKeys
|
|
552
|
-
deferredValues
|
|
553
|
+
deferredKeys[deferredSize] = key;
|
|
554
|
+
deferredValues[deferredSize] = properties[key] as ServerValue;
|
|
553
555
|
deferredSize++;
|
|
554
556
|
} else {
|
|
555
|
-
keyNodes
|
|
556
|
-
valueNodes
|
|
557
|
+
keyNodes[nodesSize] = key;
|
|
558
|
+
valueNodes[nodesSize] = generateTreeSync(ctx, properties[key] as ServerValue);
|
|
559
|
+
nodesSize++;
|
|
557
560
|
}
|
|
558
561
|
}
|
|
559
562
|
for (let i = 0; i < deferredSize; i++) {
|
|
560
|
-
keyNodes
|
|
561
|
-
valueNodes
|
|
563
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
564
|
+
valueNodes[nodesSize + i] = generateTreeSync(ctx, deferredValues[i]);
|
|
562
565
|
}
|
|
563
|
-
return [keyNodes, valueNodes,
|
|
566
|
+
return [keyNodes, valueNodes, size];
|
|
564
567
|
}
|
|
565
568
|
|
|
566
569
|
export function generateTreeSync(
|
|
@@ -582,45 +585,51 @@ export function generateTreeSync(
|
|
|
582
585
|
}
|
|
583
586
|
if (constructorCheck<Set<ServerValue>>(current, Set)) {
|
|
584
587
|
assert(ctx.features.has(Feature.Set), 'Unsupported type "Set"');
|
|
585
|
-
const
|
|
586
|
-
const
|
|
588
|
+
const len = current.size;
|
|
589
|
+
const nodes = new Array<SerovalNode>(len);
|
|
590
|
+
const deferred = new Array<ServerValue>(len);
|
|
591
|
+
let deferredSize = 0;
|
|
592
|
+
let nodeSize = 0;
|
|
587
593
|
for (const item of current.keys()) {
|
|
588
594
|
// Iterables are lazy, so the evaluation must be deferred
|
|
589
595
|
if (isIterable(item)) {
|
|
590
|
-
deferred
|
|
596
|
+
deferred[deferredSize++] = item;
|
|
591
597
|
} else {
|
|
592
|
-
nodes
|
|
598
|
+
nodes[nodeSize++] = generateTreeSync(ctx, item);
|
|
593
599
|
}
|
|
594
600
|
}
|
|
595
601
|
// Parse deferred items
|
|
596
|
-
for (let i = 0
|
|
597
|
-
nodes
|
|
602
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
603
|
+
nodes[nodeSize + i] = generateTreeSync(ctx, deferred[i]);
|
|
598
604
|
}
|
|
599
605
|
return [SerovalNodeType.Set, nodes, id];
|
|
600
606
|
}
|
|
601
607
|
if (constructorCheck<Map<ServerValue, ServerValue>>(current, Map)) {
|
|
602
608
|
assert(ctx.features.has(Feature.Map), 'Unsupported type "Map"');
|
|
603
|
-
const
|
|
604
|
-
const
|
|
605
|
-
const
|
|
606
|
-
const
|
|
609
|
+
const len = current.size;
|
|
610
|
+
const keyNodes = new Array<SerovalNode>(len);
|
|
611
|
+
const valueNodes = new Array<SerovalNode>(len);
|
|
612
|
+
const deferredKey = new Array<ServerValue>(len);
|
|
613
|
+
const deferredValue = new Array<ServerValue>(len);
|
|
607
614
|
let deferredSize = 0;
|
|
615
|
+
let nodeSize = 0;
|
|
608
616
|
for (const [key, value] of current.entries()) {
|
|
609
617
|
// Either key or value might be an iterable
|
|
610
618
|
if (isIterable(key) || isIterable(value)) {
|
|
611
|
-
deferredKey
|
|
612
|
-
deferredValue
|
|
619
|
+
deferredKey[deferredSize] = key;
|
|
620
|
+
deferredValue[deferredSize] = value;
|
|
613
621
|
deferredSize++;
|
|
614
622
|
} else {
|
|
615
|
-
keyNodes
|
|
616
|
-
valueNodes
|
|
623
|
+
keyNodes[nodeSize] = generateTreeSync(ctx, key);
|
|
624
|
+
valueNodes[nodeSize] = generateTreeSync(ctx, value);
|
|
625
|
+
nodeSize++;
|
|
617
626
|
}
|
|
618
627
|
}
|
|
619
628
|
for (let i = 0; i < deferredSize; i++) {
|
|
620
|
-
keyNodes
|
|
621
|
-
valueNodes
|
|
629
|
+
keyNodes[nodeSize + i] = generateTreeSync(ctx, deferredKey[i]);
|
|
630
|
+
valueNodes[nodeSize + i] = generateTreeSync(ctx, deferredValue[i]);
|
|
622
631
|
}
|
|
623
|
-
return [SerovalNodeType.Map, [keyNodes, valueNodes,
|
|
632
|
+
return [SerovalNodeType.Map, [keyNodes, valueNodes, len], id];
|
|
624
633
|
}
|
|
625
634
|
if (Array.isArray(current)) {
|
|
626
635
|
const size = current.length;
|
|
@@ -685,27 +694,30 @@ async function serializePropertiesAsync(
|
|
|
685
694
|
ctx: SerializationContext,
|
|
686
695
|
properties: Record<string, unknown>,
|
|
687
696
|
): Promise<SerovalDictionaryNode> {
|
|
688
|
-
const keyNodes: string[] = [];
|
|
689
|
-
const valueNodes: SerovalNode[] = [];
|
|
690
|
-
const deferredKeys: string[] = [];
|
|
691
|
-
const deferredValues: ServerValue[] = [];
|
|
692
697
|
const keys = Object.keys(properties);
|
|
698
|
+
const size = keys.length;
|
|
699
|
+
const keyNodes = new Array<string>(size);
|
|
700
|
+
const valueNodes = new Array<SerovalNode>(size);
|
|
701
|
+
const deferredKeys = new Array<string>(size);
|
|
702
|
+
const deferredValues = new Array<ServerValue>(size);
|
|
693
703
|
let deferredSize = 0;
|
|
704
|
+
let nodesSize = 0;
|
|
694
705
|
for (const key of keys) {
|
|
695
706
|
if (isIterable(properties[key])) {
|
|
696
|
-
deferredKeys
|
|
697
|
-
deferredValues
|
|
707
|
+
deferredKeys[deferredSize] = key;
|
|
708
|
+
deferredValues[deferredSize] = properties[key] as ServerValue;
|
|
698
709
|
deferredSize++;
|
|
699
710
|
} else {
|
|
700
|
-
keyNodes
|
|
701
|
-
valueNodes
|
|
711
|
+
keyNodes[nodesSize] = key;
|
|
712
|
+
valueNodes[nodesSize] = await generateTreeAsync(ctx, properties[key] as ServerValue);
|
|
713
|
+
nodesSize++;
|
|
702
714
|
}
|
|
703
715
|
}
|
|
704
716
|
for (let i = 0; i < deferredSize; i++) {
|
|
705
|
-
keyNodes
|
|
706
|
-
valueNodes
|
|
717
|
+
keyNodes[nodesSize + i] = deferredKeys[i];
|
|
718
|
+
valueNodes[nodesSize + i] = await generateTreeAsync(ctx, deferredValues[i]);
|
|
707
719
|
}
|
|
708
|
-
return [keyNodes, valueNodes,
|
|
720
|
+
return [keyNodes, valueNodes, size];
|
|
709
721
|
}
|
|
710
722
|
|
|
711
723
|
export async function generateTreeAsync(
|
|
@@ -733,42 +745,51 @@ export async function generateTreeAsync(
|
|
|
733
745
|
}
|
|
734
746
|
if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
|
|
735
747
|
assert(ctx.features.has(Feature.Set), 'Unsupported type "Set"');
|
|
736
|
-
const
|
|
737
|
-
const
|
|
748
|
+
const len = current.size;
|
|
749
|
+
const nodes = new Array<SerovalNode>(len);
|
|
750
|
+
const deferred = new Array<AsyncServerValue>(len);
|
|
751
|
+
let deferredSize = 0;
|
|
752
|
+
let nodeSize = 0;
|
|
738
753
|
for (const item of current.keys()) {
|
|
754
|
+
// Iterables are lazy, so the evaluation must be deferred
|
|
739
755
|
if (isIterable(item)) {
|
|
740
|
-
deferred
|
|
756
|
+
deferred[deferredSize++] = item;
|
|
741
757
|
} else {
|
|
742
|
-
nodes
|
|
758
|
+
nodes[nodeSize++] = await generateTreeAsync(ctx, item);
|
|
743
759
|
}
|
|
744
760
|
}
|
|
745
|
-
|
|
746
|
-
|
|
761
|
+
// Parse deferred items
|
|
762
|
+
for (let i = 0; i < deferredSize; i++) {
|
|
763
|
+
nodes[nodeSize + i] = await generateTreeAsync(ctx, deferred[i]);
|
|
747
764
|
}
|
|
748
765
|
return [SerovalNodeType.Set, nodes, id];
|
|
749
766
|
}
|
|
750
767
|
if (constructorCheck<Map<AsyncServerValue, AsyncServerValue>>(current, Map)) {
|
|
751
768
|
assert(ctx.features.has(Feature.Map), 'Unsupported type "Map"');
|
|
752
|
-
const
|
|
753
|
-
const
|
|
754
|
-
const
|
|
755
|
-
const
|
|
769
|
+
const len = current.size;
|
|
770
|
+
const keyNodes = new Array<SerovalNode>(len);
|
|
771
|
+
const valueNodes = new Array<SerovalNode>(len);
|
|
772
|
+
const deferredKey = new Array<AsyncServerValue>(len);
|
|
773
|
+
const deferredValue = new Array<AsyncServerValue>(len);
|
|
756
774
|
let deferredSize = 0;
|
|
775
|
+
let nodeSize = 0;
|
|
757
776
|
for (const [key, value] of current.entries()) {
|
|
777
|
+
// Either key or value might be an iterable
|
|
758
778
|
if (isIterable(key) || isIterable(value)) {
|
|
759
|
-
deferredKey
|
|
760
|
-
deferredValue
|
|
779
|
+
deferredKey[deferredSize] = key;
|
|
780
|
+
deferredValue[deferredSize] = value;
|
|
761
781
|
deferredSize++;
|
|
762
782
|
} else {
|
|
763
|
-
keyNodes
|
|
764
|
-
valueNodes
|
|
783
|
+
keyNodes[nodeSize] = await generateTreeAsync(ctx, key);
|
|
784
|
+
valueNodes[nodeSize] = await generateTreeAsync(ctx, value);
|
|
785
|
+
nodeSize++;
|
|
765
786
|
}
|
|
766
787
|
}
|
|
767
788
|
for (let i = 0; i < deferredSize; i++) {
|
|
768
|
-
keyNodes
|
|
769
|
-
valueNodes
|
|
789
|
+
keyNodes[nodeSize + i] = await generateTreeAsync(ctx, deferredKey[i]);
|
|
790
|
+
valueNodes[nodeSize + i] = await generateTreeAsync(ctx, deferredValue[i]);
|
|
770
791
|
}
|
|
771
|
-
return [SerovalNodeType.Map, [keyNodes, valueNodes,
|
|
792
|
+
return [SerovalNodeType.Map, [keyNodes, valueNodes, len], id];
|
|
772
793
|
}
|
|
773
794
|
if (Array.isArray(current)) {
|
|
774
795
|
const size = current.length;
|
|
@@ -884,14 +905,11 @@ function serializeAssignments(
|
|
|
884
905
|
ctx.stack = parentStack;
|
|
885
906
|
const key = keys[i];
|
|
886
907
|
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
908
|
const parentAssignment = ctx.assignments;
|
|
890
909
|
ctx.assignments = mainAssignments;
|
|
891
|
-
if
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
) {
|
|
910
|
+
// Test if key is a valid number or JS identifier
|
|
911
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
912
|
+
if (IDENTIFIER_CHECK.test(key) || check >= 0) {
|
|
895
913
|
if (!Number.isNaN(check)) {
|
|
896
914
|
createObjectComputedAssign(ctx, targetRef, key, refParam);
|
|
897
915
|
} else {
|
|
@@ -919,23 +937,20 @@ function serializeObject(
|
|
|
919
937
|
const check = Number(key);
|
|
920
938
|
// Test if key is a valid number or JS identifier
|
|
921
939
|
// so that we don't have to serialize the key and wrap with brackets
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
if (isReferenceInStack(ctx, val)) {
|
|
927
|
-
const refParam = getRefParam(ctx, val[1]);
|
|
940
|
+
const isIdentifier = IDENTIFIER_CHECK.test(key) || check >= 0;
|
|
941
|
+
if (isReferenceInStack(ctx, val)) {
|
|
942
|
+
const refParam = getRefParam(ctx, val[1]);
|
|
943
|
+
if (isIdentifier) {
|
|
928
944
|
if (!Number.isNaN(check)) {
|
|
929
945
|
createObjectComputedAssign(ctx, sourceID, key, refParam);
|
|
930
946
|
} else {
|
|
931
947
|
createObjectIdentifierAssign(ctx, sourceID, key, refParam);
|
|
932
948
|
}
|
|
933
949
|
} else {
|
|
934
|
-
|
|
950
|
+
createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
|
|
935
951
|
}
|
|
936
|
-
} else if (
|
|
937
|
-
|
|
938
|
-
createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
|
|
952
|
+
} else if (isIdentifier) {
|
|
953
|
+
result += `${key}:${serializeTree(ctx, val)},`;
|
|
939
954
|
} else {
|
|
940
955
|
result += `${quote(key)}:${serializeTree(ctx, val)},`;
|
|
941
956
|
}
|