seroval 0.2.0 → 0.3.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/src/sync.ts DELETED
@@ -1,199 +0,0 @@
1
- import { forEach, join } from './array';
2
- import {
3
- SerializationContext,
4
- insertRef,
5
- constructorCheck,
6
- getRefParam,
7
- createRef,
8
- assignRef,
9
- createSetAdd,
10
- EMPTY_SET,
11
- createMapSet,
12
- EMPTY_MAP,
13
- createArrayAssign,
14
- EMPTY_ARRAY,
15
- createObjectIdentifierAssign,
16
- createObjectComputedAssign,
17
- } from './context';
18
- import isPrimitive from './is-primitive';
19
- import quote from './quote';
20
- import serializePrimitive from './serialize-primitive';
21
- import { AsyncServerValue, ServerValue } from './types';
22
-
23
- export function lookupRefs(ctx: SerializationContext, current: ServerValue) {
24
- if (isPrimitive(current)) {
25
- return;
26
- }
27
- if (Array.isArray(current)) {
28
- if (insertRef(ctx, current)) {
29
- forEach(current, (value) => {
30
- lookupRefs(ctx, value);
31
- });
32
- }
33
- } else if (constructorCheck<Set<AsyncServerValue>>(current, Set)) {
34
- if (insertRef(ctx, current)) {
35
- for (const item of current.keys()) {
36
- lookupRefs(ctx, item);
37
- }
38
- }
39
- } else if (constructorCheck<Map<AsyncServerValue, AsyncServerValue>>(current, Map)) {
40
- if (insertRef(ctx, current)) {
41
- for (const [key, value] of current.entries()) {
42
- lookupRefs(ctx, key);
43
- lookupRefs(ctx, value);
44
- }
45
- }
46
- } else if (
47
- (current.constructor === Object || current.constructor == null)
48
- && insertRef(ctx, current)
49
- ) {
50
- forEach(Object.values(current), (value) => {
51
- lookupRefs(ctx, value);
52
- });
53
- }
54
- }
55
-
56
- export function traverseSync(
57
- ctx: SerializationContext,
58
- current: ServerValue,
59
- ): string {
60
- // Skip primitives
61
- if (isPrimitive(current)) {
62
- return serializePrimitive(current);
63
- }
64
- // Get reference of the current object
65
- let refResult = ctx.refs.get(current);
66
- if (refResult != null) {
67
- // Return the reference if already assigned a value
68
- if (ctx.assignedRefs.has(refResult)) {
69
- return getRefParam(ctx, refResult);
70
- }
71
- // Early sign (to prevent recursion)
72
- ctx.assignedRefs.add(refResult);
73
- }
74
- function getCurrentRef() {
75
- // This object received a ref, we must generate a setter ref
76
- if (refResult == null) {
77
- refResult = createRef(ctx, current);
78
- }
79
- return refResult;
80
- }
81
- function processRef(value: string) {
82
- if (refResult != null) {
83
- return assignRef(ctx, refResult, value);
84
- }
85
- return value;
86
- }
87
- // Transform Set
88
- if (constructorCheck<Set<ServerValue>>(current, Set)) {
89
- if (current.size) {
90
- const values: string[] = [];
91
-
92
- ctx.stack.add(current);
93
- for (const value of current.keys()) {
94
- if (ctx.stack.has(value)) {
95
- // Received a ref, this might be a recursive ref, defer an assignment
96
- createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
97
- } else {
98
- values.push(traverseSync(ctx, value));
99
- }
100
- }
101
- ctx.stack.delete(current);
102
-
103
- return processRef(values.length ? `new Set([${join(values, ',')}])` : EMPTY_SET);
104
- }
105
- return EMPTY_SET;
106
- }
107
- if (constructorCheck<Map<ServerValue, ServerValue>>(current, Map)) {
108
- if (current.size) {
109
- const values: string[] = [];
110
-
111
- ctx.stack.add(current);
112
- for (const [key, value] of current.entries()) {
113
- if (ctx.stack.has(key)) {
114
- const ref = getCurrentRef();
115
- const keyRef = getRefParam(ctx, createRef(ctx, key));
116
- if (ctx.stack.has(value)) {
117
- const valueRef = getRefParam(ctx, createRef(ctx, value));
118
- createMapSet(ctx, ref, keyRef, valueRef);
119
- } else {
120
- createMapSet(ctx, ref, keyRef, traverseSync(ctx, value));
121
- }
122
- } else if (ctx.stack.has(value)) {
123
- const valueRef = getRefParam(ctx, createRef(ctx, value));
124
- createMapSet(ctx, getCurrentRef(), traverseSync(ctx, key), valueRef);
125
- } else {
126
- values.push(`[${traverseSync(ctx, key)},${traverseSync(ctx, value)}]`);
127
- }
128
- }
129
- ctx.stack.delete(current);
130
- return processRef(values.length ? `new Map([${join(values, ',')}])` : EMPTY_MAP);
131
- }
132
- return EMPTY_MAP;
133
- }
134
- if (Array.isArray(current)) {
135
- if (current.length) {
136
- let values = '';
137
-
138
- ctx.stack.add(current);
139
- forEach(current, (item, i) => {
140
- if (i in current) {
141
- if (ctx.stack.has(item)) {
142
- const refParam = getRefParam(ctx, createRef(ctx, item));
143
- createArrayAssign(ctx, getCurrentRef(), i, refParam);
144
- values += ',';
145
- } else {
146
- values += traverseSync(ctx, item);
147
- if (i < current.length - 1) {
148
- values += ',';
149
- }
150
- }
151
- } else {
152
- values += ',';
153
- }
154
- });
155
- ctx.stack.delete(current);
156
- return processRef(`[${values}]`);
157
- }
158
- return EMPTY_ARRAY;
159
- }
160
- const empty = current.constructor == null;
161
- if (current.constructor === Object || empty) {
162
- const values: string[] = [];
163
-
164
- ctx.stack.add(current);
165
- forEach(Object.entries(current), ([key, value]) => {
166
- const check = Number(key);
167
- // Test if key is a valid number or JS identifier
168
- // so that we don't have to serialize the key and wrap with brackets
169
- if (
170
- check >= 0
171
- || (Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key))
172
- ) {
173
- if (ctx.stack.has(value)) {
174
- const ref = getCurrentRef();
175
- const refParam = getRefParam(ctx, createRef(ctx, value));
176
- if (!Number.isNaN(check)) {
177
- createObjectComputedAssign(ctx, ref, key, refParam);
178
- } else {
179
- createObjectIdentifierAssign(ctx, ref, key, refParam);
180
- }
181
- } else {
182
- values.push(`${key}:${traverseSync(ctx, value)}`);
183
- }
184
- } else if (ctx.stack.has(value)) {
185
- const refParam = getRefParam(ctx, createRef(ctx, value));
186
- createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
187
- } else {
188
- values.push(`${quote(key)}:${traverseSync(ctx, value)}`);
189
- }
190
- });
191
- ctx.stack.delete(current);
192
- const value = `{${join(values, ',')}}`;
193
- if (empty) {
194
- return processRef(`Object.assign(Object.create(null),${value})`);
195
- }
196
- return processRef(value);
197
- }
198
- throw new Error('Unserializable value');
199
- }