seroval 0.5.0 → 0.6.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/README.md +59 -9
- package/dist/cjs/development/index.cjs +372 -202
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +372 -202
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/compat.d.ts +3 -2
- package/dist/types/context.d.ts +3 -6
- package/dist/types/index.d.ts +9 -9
- package/dist/types/tree/async.d.ts +1 -2
- package/dist/types/tree/deserialize.d.ts +1 -2
- package/dist/types/tree/primitives.d.ts +4 -3
- package/dist/types/tree/reference.d.ts +6 -0
- package/dist/types/tree/sync.d.ts +1 -2
- package/dist/types/tree/types.d.ts +25 -7
- package/dist/types/tree/web-api.d.ts +4 -0
- package/dist/types/types.d.ts +2 -1
- package/package.json +3 -3
- package/src/compat.ts +2 -1
- package/src/context.ts +37 -48
- package/src/index.ts +10 -16
- package/src/tree/async.ts +99 -74
- package/src/tree/deserialize.ts +32 -21
- package/src/tree/primitives.ts +46 -24
- package/src/tree/reference.ts +61 -0
- package/src/tree/serialize.ts +93 -86
- package/src/tree/sync.ts +104 -66
- package/src/tree/types.ts +32 -8
- package/src/tree/web-api.ts +42 -0
- package/src/types.ts +6 -1
package/src/tree/primitives.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Feature } from '../compat';
|
|
|
3
3
|
import { ParserContext } from '../context';
|
|
4
4
|
import quote from '../quote';
|
|
5
5
|
import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
|
|
6
|
+
import { getReferenceID } from './reference';
|
|
6
7
|
import { INV_SYMBOL_REF, WellKnownSymbols } from './symbols';
|
|
7
8
|
import {
|
|
8
9
|
SerovalBigIntNode,
|
|
@@ -16,12 +17,13 @@ import {
|
|
|
16
17
|
SerovalNodeType,
|
|
17
18
|
SerovalNullNode,
|
|
18
19
|
SerovalNumberNode,
|
|
19
|
-
|
|
20
|
+
SerovalIndexedValueNode,
|
|
20
21
|
SerovalRegExpNode,
|
|
21
22
|
SerovalStringNode,
|
|
22
23
|
SerovalTypedArrayNode,
|
|
23
24
|
SerovalUndefinedNode,
|
|
24
25
|
SerovalWKSymbolNode,
|
|
26
|
+
SerovalReferenceNode,
|
|
25
27
|
} from './types';
|
|
26
28
|
|
|
27
29
|
export const TRUE_NODE: SerovalBooleanNode = {
|
|
@@ -33,7 +35,7 @@ export const TRUE_NODE: SerovalBooleanNode = {
|
|
|
33
35
|
m: undefined,
|
|
34
36
|
d: undefined,
|
|
35
37
|
a: undefined,
|
|
36
|
-
|
|
38
|
+
f: undefined,
|
|
37
39
|
};
|
|
38
40
|
export const FALSE_NODE: SerovalBooleanNode = {
|
|
39
41
|
t: SerovalNodeType.Boolean,
|
|
@@ -44,7 +46,7 @@ export const FALSE_NODE: SerovalBooleanNode = {
|
|
|
44
46
|
m: undefined,
|
|
45
47
|
d: undefined,
|
|
46
48
|
a: undefined,
|
|
47
|
-
|
|
49
|
+
f: undefined,
|
|
48
50
|
};
|
|
49
51
|
export const UNDEFINED_NODE: SerovalUndefinedNode = {
|
|
50
52
|
t: SerovalNodeType.Undefined,
|
|
@@ -55,7 +57,7 @@ export const UNDEFINED_NODE: SerovalUndefinedNode = {
|
|
|
55
57
|
m: undefined,
|
|
56
58
|
d: undefined,
|
|
57
59
|
a: undefined,
|
|
58
|
-
|
|
60
|
+
f: undefined,
|
|
59
61
|
};
|
|
60
62
|
export const NULL_NODE: SerovalNullNode = {
|
|
61
63
|
t: SerovalNodeType.Null,
|
|
@@ -66,7 +68,7 @@ export const NULL_NODE: SerovalNullNode = {
|
|
|
66
68
|
m: undefined,
|
|
67
69
|
d: undefined,
|
|
68
70
|
a: undefined,
|
|
69
|
-
|
|
71
|
+
f: undefined,
|
|
70
72
|
};
|
|
71
73
|
export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
|
|
72
74
|
t: SerovalNodeType.NegativeZero,
|
|
@@ -77,7 +79,7 @@ export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
|
|
|
77
79
|
m: undefined,
|
|
78
80
|
d: undefined,
|
|
79
81
|
a: undefined,
|
|
80
|
-
|
|
82
|
+
f: undefined,
|
|
81
83
|
};
|
|
82
84
|
export const INFINITY_NODE: SerovalInfinityNode = {
|
|
83
85
|
t: SerovalNodeType.Infinity,
|
|
@@ -88,7 +90,7 @@ export const INFINITY_NODE: SerovalInfinityNode = {
|
|
|
88
90
|
m: undefined,
|
|
89
91
|
d: undefined,
|
|
90
92
|
a: undefined,
|
|
91
|
-
|
|
93
|
+
f: undefined,
|
|
92
94
|
};
|
|
93
95
|
export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
|
|
94
96
|
t: SerovalNodeType.NegativeInfinity,
|
|
@@ -99,7 +101,7 @@ export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
|
|
|
99
101
|
m: undefined,
|
|
100
102
|
d: undefined,
|
|
101
103
|
a: undefined,
|
|
102
|
-
|
|
104
|
+
f: undefined,
|
|
103
105
|
};
|
|
104
106
|
export const NAN_NODE: SerovalNaNNode = {
|
|
105
107
|
t: SerovalNodeType.NaN,
|
|
@@ -110,7 +112,7 @@ export const NAN_NODE: SerovalNaNNode = {
|
|
|
110
112
|
m: undefined,
|
|
111
113
|
d: undefined,
|
|
112
114
|
a: undefined,
|
|
113
|
-
|
|
115
|
+
f: undefined,
|
|
114
116
|
};
|
|
115
117
|
|
|
116
118
|
export function createNumberNode(value: number): SerovalNumberNode {
|
|
@@ -123,7 +125,7 @@ export function createNumberNode(value: number): SerovalNumberNode {
|
|
|
123
125
|
m: undefined,
|
|
124
126
|
d: undefined,
|
|
125
127
|
a: undefined,
|
|
126
|
-
|
|
128
|
+
f: undefined,
|
|
127
129
|
};
|
|
128
130
|
}
|
|
129
131
|
|
|
@@ -137,7 +139,7 @@ export function createStringNode(value: string): SerovalStringNode {
|
|
|
137
139
|
m: undefined,
|
|
138
140
|
d: undefined,
|
|
139
141
|
a: undefined,
|
|
140
|
-
|
|
142
|
+
f: undefined,
|
|
141
143
|
};
|
|
142
144
|
}
|
|
143
145
|
|
|
@@ -149,19 +151,19 @@ export function createBigIntNode(
|
|
|
149
151
|
return {
|
|
150
152
|
t: SerovalNodeType.BigInt,
|
|
151
153
|
i: undefined,
|
|
152
|
-
s: current
|
|
154
|
+
s: '' + current,
|
|
153
155
|
l: undefined,
|
|
154
156
|
c: undefined,
|
|
155
157
|
m: undefined,
|
|
156
158
|
d: undefined,
|
|
157
159
|
a: undefined,
|
|
158
|
-
|
|
160
|
+
f: undefined,
|
|
159
161
|
};
|
|
160
162
|
}
|
|
161
163
|
|
|
162
|
-
export function
|
|
164
|
+
export function createIndexedValueNode(id: number): SerovalIndexedValueNode {
|
|
163
165
|
return {
|
|
164
|
-
t: SerovalNodeType.
|
|
166
|
+
t: SerovalNodeType.IndexedValue,
|
|
165
167
|
i: id,
|
|
166
168
|
s: undefined,
|
|
167
169
|
l: undefined,
|
|
@@ -169,7 +171,7 @@ export function createReferenceNode(id: number): SerovalReferenceNode {
|
|
|
169
171
|
m: undefined,
|
|
170
172
|
d: undefined,
|
|
171
173
|
a: undefined,
|
|
172
|
-
|
|
174
|
+
f: undefined,
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
|
|
@@ -182,7 +184,7 @@ export function createDateNode(id: number, current: Date): SerovalDateNode {
|
|
|
182
184
|
c: undefined,
|
|
183
185
|
m: undefined,
|
|
184
186
|
d: undefined,
|
|
185
|
-
|
|
187
|
+
f: undefined,
|
|
186
188
|
a: undefined,
|
|
187
189
|
};
|
|
188
190
|
}
|
|
@@ -197,7 +199,7 @@ export function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode
|
|
|
197
199
|
m: current.flags,
|
|
198
200
|
d: undefined,
|
|
199
201
|
a: undefined,
|
|
200
|
-
|
|
202
|
+
f: undefined,
|
|
201
203
|
};
|
|
202
204
|
}
|
|
203
205
|
|
|
@@ -211,7 +213,7 @@ export function createTypedArrayNode(
|
|
|
211
213
|
const len = current.length;
|
|
212
214
|
const values = new Array<string>(len);
|
|
213
215
|
for (let i = 0; i < len; i++) {
|
|
214
|
-
values[i] = current[i]
|
|
216
|
+
values[i] = '' + current[i];
|
|
215
217
|
}
|
|
216
218
|
return {
|
|
217
219
|
t: SerovalNodeType.TypedArray,
|
|
@@ -222,7 +224,7 @@ export function createTypedArrayNode(
|
|
|
222
224
|
m: undefined,
|
|
223
225
|
d: undefined,
|
|
224
226
|
a: undefined,
|
|
225
|
-
|
|
227
|
+
f: undefined,
|
|
226
228
|
};
|
|
227
229
|
}
|
|
228
230
|
|
|
@@ -241,24 +243,27 @@ export function createBigIntTypedArrayNode(
|
|
|
241
243
|
const len = current.length;
|
|
242
244
|
const values = new Array<string>(len);
|
|
243
245
|
for (let i = 0; i < len; i++) {
|
|
244
|
-
values[i] = current[i]
|
|
246
|
+
values[i] = '' + current[i];
|
|
245
247
|
}
|
|
246
248
|
return {
|
|
247
249
|
t: SerovalNodeType.BigIntTypedArray,
|
|
248
250
|
i: id,
|
|
249
251
|
s: values,
|
|
250
|
-
l:
|
|
252
|
+
l: current.byteOffset,
|
|
251
253
|
c: constructor,
|
|
252
254
|
m: undefined,
|
|
253
255
|
d: undefined,
|
|
254
256
|
a: undefined,
|
|
255
|
-
|
|
257
|
+
f: undefined,
|
|
256
258
|
};
|
|
257
259
|
}
|
|
258
260
|
|
|
259
261
|
export function createWKSymbolNode(
|
|
262
|
+
ctx: ParserContext,
|
|
260
263
|
current: WellKnownSymbols,
|
|
261
264
|
): SerovalWKSymbolNode {
|
|
265
|
+
assert(ctx.features & Feature.Symbol, 'Unsupported type "symbol"');
|
|
266
|
+
assert(current in INV_SYMBOL_REF, 'seroval only supports well-known symbols');
|
|
262
267
|
return {
|
|
263
268
|
t: SerovalNodeType.WKSymbol,
|
|
264
269
|
i: undefined,
|
|
@@ -268,6 +273,23 @@ export function createWKSymbolNode(
|
|
|
268
273
|
m: undefined,
|
|
269
274
|
d: undefined,
|
|
270
275
|
a: undefined,
|
|
271
|
-
|
|
276
|
+
f: undefined,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function createReferenceNode<T>(
|
|
281
|
+
id: number,
|
|
282
|
+
ref: T,
|
|
283
|
+
): SerovalReferenceNode {
|
|
284
|
+
return {
|
|
285
|
+
t: SerovalNodeType.Reference,
|
|
286
|
+
i: id,
|
|
287
|
+
s: quote(getReferenceID(ref)),
|
|
288
|
+
l: undefined,
|
|
289
|
+
c: undefined,
|
|
290
|
+
m: undefined,
|
|
291
|
+
d: undefined,
|
|
292
|
+
a: undefined,
|
|
293
|
+
f: undefined,
|
|
272
294
|
};
|
|
273
295
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals */
|
|
2
|
+
import assert from '../assert';
|
|
3
|
+
|
|
4
|
+
const REFERENCE = new Map<unknown, string>();
|
|
5
|
+
const INV_REFERENCE = new Map<string, unknown>();
|
|
6
|
+
|
|
7
|
+
export function createReference<T>(id: string, value: T): T {
|
|
8
|
+
REFERENCE.set(value, id);
|
|
9
|
+
INV_REFERENCE.set(id, value);
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function hasReferenceID<T>(value: T): boolean {
|
|
14
|
+
return REFERENCE.has(value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function hasReference(id: string): boolean {
|
|
18
|
+
return INV_REFERENCE.has(id);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getReferenceID<T>(value: T): string {
|
|
22
|
+
assert(hasReferenceID(value), 'Missing reference id');
|
|
23
|
+
return REFERENCE.get(value) as string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getReference<T>(id: string): T {
|
|
27
|
+
assert(hasReference(id), 'Missing reference for id:' + id);
|
|
28
|
+
return INV_REFERENCE.get(id) as T;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const GLOBAL_KEY = '__SEROVAL__';
|
|
32
|
+
|
|
33
|
+
if (typeof globalThis !== undefined) {
|
|
34
|
+
Object.defineProperty(globalThis, GLOBAL_KEY, {
|
|
35
|
+
value: INV_REFERENCE,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: false,
|
|
38
|
+
enumerable: false,
|
|
39
|
+
});
|
|
40
|
+
} else if (typeof window !== undefined) {
|
|
41
|
+
Object.defineProperty(window, GLOBAL_KEY, {
|
|
42
|
+
value: INV_REFERENCE,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: false,
|
|
45
|
+
enumerable: false,
|
|
46
|
+
});
|
|
47
|
+
} else if (typeof self !== undefined) {
|
|
48
|
+
Object.defineProperty(self, GLOBAL_KEY, {
|
|
49
|
+
value: INV_REFERENCE,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: false,
|
|
52
|
+
enumerable: false,
|
|
53
|
+
});
|
|
54
|
+
} else if (typeof global !== undefined) {
|
|
55
|
+
Object.defineProperty(global, GLOBAL_KEY, {
|
|
56
|
+
value: INV_REFERENCE,
|
|
57
|
+
configurable: true,
|
|
58
|
+
writable: false,
|
|
59
|
+
enumerable: false,
|
|
60
|
+
});
|
|
61
|
+
}
|
package/src/tree/serialize.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
markRef,
|
|
8
8
|
} from '../context';
|
|
9
9
|
import quote from '../quote';
|
|
10
|
+
import { GLOBAL_KEY } from './reference';
|
|
10
11
|
import { isValidIdentifier } from './shared';
|
|
11
12
|
import { SYMBOL_STRING } from './symbols';
|
|
12
13
|
import {
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
SerovalObjectNode,
|
|
23
24
|
SerovalObjectRecordNode,
|
|
24
25
|
SerovalPromiseNode,
|
|
25
|
-
|
|
26
|
+
SerovalIndexedValueNode,
|
|
26
27
|
SerovalSetNode,
|
|
27
28
|
SerovalTypedArrayNode,
|
|
28
29
|
} from './types';
|
|
@@ -48,35 +49,55 @@ function mergeAssignments(assignments: Assignment[]) {
|
|
|
48
49
|
for (let i = 1, len = assignments.length; i < len; i++) {
|
|
49
50
|
item = assignments[i];
|
|
50
51
|
if (item.t === prev.t) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
52
|
+
switch (item.t) {
|
|
53
|
+
case 'index':
|
|
54
|
+
if (item.v === prev.v) {
|
|
55
|
+
// Merge if the right-hand value is the same
|
|
56
|
+
// saves at least 2 chars
|
|
57
|
+
current = {
|
|
58
|
+
t: 'index',
|
|
59
|
+
s: item.s,
|
|
60
|
+
k: undefined,
|
|
61
|
+
v: getAssignmentExpression(current),
|
|
62
|
+
};
|
|
63
|
+
} else {
|
|
64
|
+
// Different assignment, push current
|
|
65
|
+
newAssignments.push(current);
|
|
66
|
+
current = item;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case 'map':
|
|
70
|
+
if (item.s === prev.s) {
|
|
71
|
+
// Maps has chaining methods, merge if source is the same
|
|
72
|
+
current = {
|
|
73
|
+
t: 'map',
|
|
74
|
+
s: getAssignmentExpression(current),
|
|
75
|
+
k: item.k,
|
|
76
|
+
v: item.v,
|
|
77
|
+
};
|
|
78
|
+
} else {
|
|
79
|
+
// Different assignment, push current
|
|
80
|
+
newAssignments.push(current);
|
|
81
|
+
current = item;
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
case 'set':
|
|
85
|
+
if (item.s === prev.s) {
|
|
86
|
+
// Sets has chaining methods too
|
|
87
|
+
current = {
|
|
88
|
+
t: 'set',
|
|
89
|
+
s: getAssignmentExpression(current),
|
|
90
|
+
k: undefined,
|
|
91
|
+
v: item.v,
|
|
92
|
+
};
|
|
93
|
+
} else {
|
|
94
|
+
// Different assignment, push current
|
|
95
|
+
newAssignments.push(current);
|
|
96
|
+
current = item;
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
default:
|
|
100
|
+
break;
|
|
80
101
|
}
|
|
81
102
|
} else {
|
|
82
103
|
newAssignments.push(current);
|
|
@@ -161,7 +182,7 @@ function createArrayAssign(
|
|
|
161
182
|
value: string,
|
|
162
183
|
) {
|
|
163
184
|
markRef(ctx, ref);
|
|
164
|
-
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index
|
|
185
|
+
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
|
|
165
186
|
}
|
|
166
187
|
|
|
167
188
|
function createObjectAssign(
|
|
@@ -174,7 +195,7 @@ function createObjectAssign(
|
|
|
174
195
|
createAssignment(ctx, getRefParam(ctx, ref) + '.' + key, value);
|
|
175
196
|
}
|
|
176
197
|
|
|
177
|
-
function
|
|
198
|
+
function assignIndexedValue(
|
|
178
199
|
ctx: SerializationContext,
|
|
179
200
|
index: number,
|
|
180
201
|
value: string,
|
|
@@ -185,11 +206,11 @@ function assignRef(
|
|
|
185
206
|
return value;
|
|
186
207
|
}
|
|
187
208
|
|
|
188
|
-
function
|
|
209
|
+
function isIndexedValueInStack(
|
|
189
210
|
ctx: SerializationContext,
|
|
190
211
|
node: SerovalNode,
|
|
191
|
-
): node is
|
|
192
|
-
return node.t === SerovalNodeType.
|
|
212
|
+
): node is SerovalIndexedValueNode {
|
|
213
|
+
return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
|
|
193
214
|
}
|
|
194
215
|
|
|
195
216
|
function serializeNodeList(
|
|
@@ -212,7 +233,7 @@ function serializeNodeList(
|
|
|
212
233
|
// Check if index is a hole
|
|
213
234
|
if (item) {
|
|
214
235
|
// Check if item is a parent
|
|
215
|
-
if (
|
|
236
|
+
if (isIndexedValueInStack(ctx, item)) {
|
|
216
237
|
createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
|
|
217
238
|
isHoley = true;
|
|
218
239
|
} else {
|
|
@@ -223,10 +244,7 @@ function serializeNodeList(
|
|
|
223
244
|
isHoley = true;
|
|
224
245
|
}
|
|
225
246
|
}
|
|
226
|
-
|
|
227
|
-
values += ',';
|
|
228
|
-
}
|
|
229
|
-
return '[' + values + ']';
|
|
247
|
+
return '[' + values + (isHoley ? ',]' : ']');
|
|
230
248
|
}
|
|
231
249
|
|
|
232
250
|
function serializeArray(
|
|
@@ -236,7 +254,7 @@ function serializeArray(
|
|
|
236
254
|
ctx.stack.push(node.i);
|
|
237
255
|
const result = serializeNodeList(ctx, node);
|
|
238
256
|
ctx.stack.pop();
|
|
239
|
-
return
|
|
257
|
+
return assignIndexedValue(ctx, node.i, result);
|
|
240
258
|
}
|
|
241
259
|
|
|
242
260
|
function serializeProperties(
|
|
@@ -262,7 +280,7 @@ function serializeProperties(
|
|
|
262
280
|
// Test if key is a valid number or JS identifier
|
|
263
281
|
// so that we don't have to serialize the key and wrap with brackets
|
|
264
282
|
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
265
|
-
if (
|
|
283
|
+
if (isIndexedValueInStack(ctx, val)) {
|
|
266
284
|
refParam = getRefParam(ctx, val.i);
|
|
267
285
|
if (isIdentifier && Number.isNaN(check)) {
|
|
268
286
|
createObjectAssign(ctx, sourceID, key, refParam);
|
|
@@ -270,11 +288,9 @@ function serializeProperties(
|
|
|
270
288
|
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
|
|
271
289
|
}
|
|
272
290
|
} else {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
result += isIdentifier ? key : ('"' + quote(key) + '"');
|
|
277
|
-
result += ':' + serializeTree(ctx, val);
|
|
291
|
+
result += (hasPrev ? ',' : '')
|
|
292
|
+
+ (isIdentifier ? key : ('"' + quote(key) + '"'))
|
|
293
|
+
+ ':' + serializeTree(ctx, val);
|
|
278
294
|
hasPrev = true;
|
|
279
295
|
}
|
|
280
296
|
}
|
|
@@ -344,12 +360,11 @@ function serializeDictionary(
|
|
|
344
360
|
markRef(ctx, i);
|
|
345
361
|
const assignments = serializeAssignments(ctx, i, d);
|
|
346
362
|
if (assignments) {
|
|
347
|
-
|
|
348
|
-
return '(' + assignRef(ctx, i, init) + ',' + assignments + ref + ')';
|
|
363
|
+
return '(' + assignIndexedValue(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
|
|
349
364
|
}
|
|
350
365
|
}
|
|
351
366
|
}
|
|
352
|
-
return
|
|
367
|
+
return assignIndexedValue(ctx, i, init);
|
|
353
368
|
}
|
|
354
369
|
|
|
355
370
|
function serializeNullConstructor(
|
|
@@ -363,7 +378,7 @@ function serializeObject(
|
|
|
363
378
|
ctx: SerializationContext,
|
|
364
379
|
node: SerovalObjectNode,
|
|
365
380
|
) {
|
|
366
|
-
return
|
|
381
|
+
return assignIndexedValue(ctx, node.i, serializeProperties(ctx, node.i, node.d));
|
|
367
382
|
}
|
|
368
383
|
|
|
369
384
|
function serializeSet(
|
|
@@ -379,14 +394,11 @@ function serializeSet(
|
|
|
379
394
|
let hasPrev = false;
|
|
380
395
|
for (let i = 0; i < size; i++) {
|
|
381
396
|
item = node.a[i];
|
|
382
|
-
if (
|
|
397
|
+
if (isIndexedValueInStack(ctx, item)) {
|
|
383
398
|
createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
|
|
384
399
|
} else {
|
|
385
400
|
// Push directly
|
|
386
|
-
|
|
387
|
-
result += ',';
|
|
388
|
-
}
|
|
389
|
-
result += serializeTree(ctx, item);
|
|
401
|
+
result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
|
|
390
402
|
hasPrev = true;
|
|
391
403
|
}
|
|
392
404
|
}
|
|
@@ -395,7 +407,7 @@ function serializeSet(
|
|
|
395
407
|
serialized += '([' + result + '])';
|
|
396
408
|
}
|
|
397
409
|
}
|
|
398
|
-
return
|
|
410
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
399
411
|
}
|
|
400
412
|
|
|
401
413
|
function serializeMap(
|
|
@@ -416,11 +428,11 @@ function serializeMap(
|
|
|
416
428
|
// Check if key is a parent
|
|
417
429
|
key = node.d.k[i];
|
|
418
430
|
val = node.d.v[i];
|
|
419
|
-
if (
|
|
431
|
+
if (isIndexedValueInStack(ctx, key)) {
|
|
420
432
|
// Create reference for the map instance
|
|
421
433
|
keyRef = getRefParam(ctx, key.i);
|
|
422
434
|
// Check if value is a parent
|
|
423
|
-
if (
|
|
435
|
+
if (isIndexedValueInStack(ctx, val)) {
|
|
424
436
|
valueRef = getRefParam(ctx, val.i);
|
|
425
437
|
// Register an assignment since
|
|
426
438
|
// both key and value are a parent of this
|
|
@@ -437,7 +449,7 @@ function serializeMap(
|
|
|
437
449
|
createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
|
|
438
450
|
ctx.stack = parent;
|
|
439
451
|
}
|
|
440
|
-
} else if (
|
|
452
|
+
} else if (isIndexedValueInStack(ctx, val)) {
|
|
441
453
|
// Create ref for the Map instance
|
|
442
454
|
valueRef = getRefParam(ctx, val.i);
|
|
443
455
|
// Reset stack for the key serialization
|
|
@@ -446,10 +458,7 @@ function serializeMap(
|
|
|
446
458
|
createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
|
|
447
459
|
ctx.stack = parent;
|
|
448
460
|
} else {
|
|
449
|
-
|
|
450
|
-
result += ',';
|
|
451
|
-
}
|
|
452
|
-
result += '[' + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
|
|
461
|
+
result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
|
|
453
462
|
hasPrev = true;
|
|
454
463
|
}
|
|
455
464
|
}
|
|
@@ -461,7 +470,7 @@ function serializeMap(
|
|
|
461
470
|
serialized += '([' + result + '])';
|
|
462
471
|
}
|
|
463
472
|
}
|
|
464
|
-
return
|
|
473
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
465
474
|
}
|
|
466
475
|
|
|
467
476
|
function serializeAggregateError(
|
|
@@ -492,12 +501,12 @@ function serializePromise(
|
|
|
492
501
|
) {
|
|
493
502
|
let serialized: string;
|
|
494
503
|
// Check if resolved value is a parent expression
|
|
495
|
-
if (
|
|
504
|
+
if (isIndexedValueInStack(ctx, node.f)) {
|
|
496
505
|
// A Promise trick, reference the value
|
|
497
506
|
// inside the `then` expression so that
|
|
498
507
|
// the Promise evaluates after the parent
|
|
499
508
|
// has initialized
|
|
500
|
-
const ref = getRefParam(ctx, node.
|
|
509
|
+
const ref = getRefParam(ctx, node.f.i);
|
|
501
510
|
if (ctx.features & Feature.ArrowFunction) {
|
|
502
511
|
serialized = 'Promise.resolve().then(()=>' + ref + ')';
|
|
503
512
|
} else {
|
|
@@ -505,12 +514,12 @@ function serializePromise(
|
|
|
505
514
|
}
|
|
506
515
|
} else {
|
|
507
516
|
ctx.stack.push(node.i);
|
|
508
|
-
const result = serializeTree(ctx, node.
|
|
517
|
+
const result = serializeTree(ctx, node.f);
|
|
509
518
|
ctx.stack.pop();
|
|
510
519
|
// just inline the value/reference here
|
|
511
520
|
serialized = 'Promise.resolve(' + result + ')';
|
|
512
521
|
}
|
|
513
|
-
return
|
|
522
|
+
return assignIndexedValue(ctx, node.i, serialized);
|
|
514
523
|
}
|
|
515
524
|
|
|
516
525
|
function serializeTypedArray(
|
|
@@ -518,20 +527,12 @@ function serializeTypedArray(
|
|
|
518
527
|
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
519
528
|
) {
|
|
520
529
|
let result = '';
|
|
530
|
+
const isBigInt = node.t === SerovalNodeType.BigIntTypedArray;
|
|
521
531
|
for (let i = 0, len = node.s.length; i < len; i++) {
|
|
522
|
-
|
|
523
|
-
result += ',';
|
|
524
|
-
}
|
|
525
|
-
result += node.s[i];
|
|
526
|
-
if (node.t === SerovalNodeType.BigIntTypedArray) {
|
|
527
|
-
result += 'n';
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
let args = '[' + result + ']';
|
|
531
|
-
if (node.l !== 0) {
|
|
532
|
-
args += ',' + node.l.toString();
|
|
532
|
+
result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
|
|
533
533
|
}
|
|
534
|
-
|
|
534
|
+
const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
|
|
535
|
+
return assignIndexedValue(ctx, node.i, 'new ' + node.c + '(' + args + ')');
|
|
535
536
|
}
|
|
536
537
|
|
|
537
538
|
function serializeIterable(
|
|
@@ -564,13 +565,13 @@ export default function serializeTree(
|
|
|
564
565
|
): string {
|
|
565
566
|
switch (node.t) {
|
|
566
567
|
case SerovalNodeType.Number:
|
|
567
|
-
return
|
|
568
|
+
return '' + node.s;
|
|
568
569
|
case SerovalNodeType.String:
|
|
569
570
|
return '"' + node.s + '"';
|
|
570
571
|
case SerovalNodeType.Boolean:
|
|
571
572
|
return node.s ? '!0' : '!1';
|
|
572
573
|
case SerovalNodeType.Undefined:
|
|
573
|
-
return '
|
|
574
|
+
return 'void 0';
|
|
574
575
|
case SerovalNodeType.Null:
|
|
575
576
|
return 'null';
|
|
576
577
|
case SerovalNodeType.NegativeZero:
|
|
@@ -583,7 +584,7 @@ export default function serializeTree(
|
|
|
583
584
|
return 'NaN';
|
|
584
585
|
case SerovalNodeType.BigInt:
|
|
585
586
|
return node.s + 'n';
|
|
586
|
-
case SerovalNodeType.
|
|
587
|
+
case SerovalNodeType.IndexedValue:
|
|
587
588
|
return getRefParam(ctx, node.i);
|
|
588
589
|
case SerovalNodeType.Array:
|
|
589
590
|
return serializeArray(ctx, node);
|
|
@@ -592,9 +593,9 @@ export default function serializeTree(
|
|
|
592
593
|
case SerovalNodeType.NullConstructor:
|
|
593
594
|
return serializeNullConstructor(ctx, node);
|
|
594
595
|
case SerovalNodeType.Date:
|
|
595
|
-
return
|
|
596
|
+
return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
|
|
596
597
|
case SerovalNodeType.RegExp:
|
|
597
|
-
return
|
|
598
|
+
return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
|
|
598
599
|
case SerovalNodeType.Set:
|
|
599
600
|
return serializeSet(ctx, node);
|
|
600
601
|
case SerovalNodeType.Map:
|
|
@@ -612,6 +613,12 @@ export default function serializeTree(
|
|
|
612
613
|
return serializePromise(ctx, node);
|
|
613
614
|
case SerovalNodeType.WKSymbol:
|
|
614
615
|
return SYMBOL_STRING[node.s];
|
|
616
|
+
case SerovalNodeType.URL:
|
|
617
|
+
return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
|
|
618
|
+
case SerovalNodeType.URLSearchParams:
|
|
619
|
+
return assignIndexedValue(ctx, node.i, node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams');
|
|
620
|
+
case SerovalNodeType.Reference:
|
|
621
|
+
return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
|
|
615
622
|
default:
|
|
616
623
|
throw new Error('Unsupported type');
|
|
617
624
|
}
|