seroval 0.7.0 → 0.8.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/dist/cjs/development/index.cjs +1109 -1039
- package/dist/cjs/development/index.cjs.map +4 -4
- package/dist/cjs/production/index.cjs +3 -3
- package/dist/esm/development/index.mjs +1109 -1039
- package/dist/esm/development/index.mjs.map +4 -4
- package/dist/esm/production/index.mjs +3 -3
- package/dist/types/assert.d.ts +1 -1
- package/dist/types/context.d.ts +2 -2
- package/dist/types/index.d.ts +3 -4
- package/dist/types/string.d.ts +1 -1
- package/dist/types/tree/UnsupportedTypeError.d.ts +3 -0
- package/dist/types/tree/async.d.ts +3 -3
- package/dist/types/tree/constants.d.ts +11 -0
- package/dist/types/tree/deserialize.d.ts +2 -2
- package/dist/types/tree/primitives.d.ts +9 -15
- package/dist/types/tree/serialize.d.ts +2 -2
- package/dist/types/tree/shared.d.ts +10 -8
- package/dist/types/tree/sync.d.ts +3 -3
- package/dist/types/tree/types.d.ts +64 -71
- package/dist/types/tree/web-api.d.ts +2 -2
- package/dist/types/types.d.ts +4 -4
- package/package.json +10 -8
- package/src/assert.ts +2 -2
- package/src/compat.ts +0 -1
- package/src/context.ts +10 -7
- package/src/get-identifier.ts +1 -1
- package/src/index.ts +35 -26
- package/src/string.ts +2 -2
- package/src/tree/UnsupportedTypeError.ts +8 -0
- package/src/tree/async.ts +245 -233
- package/src/tree/constants.ts +72 -0
- package/src/tree/deserialize.ts +96 -93
- package/src/tree/primitives.ts +81 -134
- package/src/tree/reference.ts +4 -3
- package/src/tree/serialize.ts +251 -197
- package/src/tree/shared.ts +31 -22
- package/src/tree/symbols.ts +13 -13
- package/src/tree/sync.ts +226 -198
- package/src/tree/types.ts +74 -93
- package/src/tree/web-api.ts +10 -7
- package/src/types.ts +7 -3
package/src/tree/serialize.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
|
2
2
|
import { Feature } from '../compat';
|
|
3
|
-
import {
|
|
3
|
+
import type {
|
|
4
4
|
SerializationContext,
|
|
5
5
|
Assignment,
|
|
6
|
+
} from '../context';
|
|
7
|
+
import {
|
|
6
8
|
getRefParam,
|
|
7
9
|
markRef,
|
|
8
10
|
} from '../context';
|
|
11
|
+
import { serializeConstant } from './constants';
|
|
9
12
|
import { GLOBAL_KEY } from './reference';
|
|
10
13
|
import { isValidIdentifier } from './shared';
|
|
11
14
|
import { SYMBOL_STRING } from './symbols';
|
|
12
|
-
import {
|
|
15
|
+
import type {
|
|
13
16
|
SerovalAggregateErrorNode,
|
|
14
17
|
SerovalArrayNode,
|
|
15
18
|
SerovalBigIntTypedArrayNode,
|
|
16
19
|
SerovalErrorNode,
|
|
17
|
-
SerovalIterableNode,
|
|
18
20
|
SerovalMapNode,
|
|
19
21
|
SerovalNode,
|
|
20
|
-
SerovalNodeType,
|
|
21
22
|
SerovalNullConstructorNode,
|
|
22
23
|
SerovalObjectNode,
|
|
23
|
-
SerovalObjectRecordNode,
|
|
24
24
|
SerovalPromiseNode,
|
|
25
25
|
SerovalIndexedValueNode,
|
|
26
26
|
SerovalSetNode,
|
|
@@ -36,6 +36,14 @@ import {
|
|
|
36
36
|
SerovalURLSearchParamsNode,
|
|
37
37
|
SerovalReferenceNode,
|
|
38
38
|
SerovalFormDataNode,
|
|
39
|
+
SerovalObjectRecordNode,
|
|
40
|
+
SerovalObjectRecordKey,
|
|
41
|
+
SerovalBoxedNode,
|
|
42
|
+
SerovalWKSymbolNode,
|
|
43
|
+
} from './types';
|
|
44
|
+
import {
|
|
45
|
+
SerovalNodeType,
|
|
46
|
+
SerovalObjectRecordSpecialKey,
|
|
39
47
|
} from './types';
|
|
40
48
|
|
|
41
49
|
function getAssignmentExpression(assignment: Assignment): string {
|
|
@@ -53,8 +61,8 @@ function getAssignmentExpression(assignment: Assignment): string {
|
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
function mergeAssignments(assignments: Assignment[]) {
|
|
57
|
-
const newAssignments = [];
|
|
64
|
+
function mergeAssignments(assignments: Assignment[]): Assignment[] {
|
|
65
|
+
const newAssignments: Assignment[] = [];
|
|
58
66
|
let current = assignments[0];
|
|
59
67
|
let prev = current;
|
|
60
68
|
let item: Assignment;
|
|
@@ -128,7 +136,7 @@ function mergeAssignments(assignments: Assignment[]) {
|
|
|
128
136
|
return newAssignments;
|
|
129
137
|
}
|
|
130
138
|
|
|
131
|
-
function resolveAssignments(assignments: Assignment[]) {
|
|
139
|
+
function resolveAssignments(assignments: Assignment[]): string | undefined {
|
|
132
140
|
if (assignments.length) {
|
|
133
141
|
let result = '';
|
|
134
142
|
const merged = mergeAssignments(assignments);
|
|
@@ -140,7 +148,7 @@ function resolveAssignments(assignments: Assignment[]) {
|
|
|
140
148
|
return undefined;
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
export function resolvePatches(ctx: SerializationContext) {
|
|
151
|
+
export function resolvePatches(ctx: SerializationContext): string | undefined {
|
|
144
152
|
return resolveAssignments(ctx.assignments);
|
|
145
153
|
}
|
|
146
154
|
|
|
@@ -154,7 +162,7 @@ function createAssignment(
|
|
|
154
162
|
ctx: SerializationContext,
|
|
155
163
|
source: string,
|
|
156
164
|
value: string,
|
|
157
|
-
) {
|
|
165
|
+
): void {
|
|
158
166
|
ctx.assignments.push({
|
|
159
167
|
t: 'index',
|
|
160
168
|
s: source,
|
|
@@ -167,7 +175,7 @@ function createAddAssignment(
|
|
|
167
175
|
ctx: SerializationContext,
|
|
168
176
|
ref: number,
|
|
169
177
|
value: string,
|
|
170
|
-
) {
|
|
178
|
+
): void {
|
|
171
179
|
ctx.assignments.push({
|
|
172
180
|
t: 'add',
|
|
173
181
|
s: getRefParam(ctx, ref),
|
|
@@ -181,7 +189,7 @@ function createSetAssignment(
|
|
|
181
189
|
ref: number,
|
|
182
190
|
key: string,
|
|
183
191
|
value: string,
|
|
184
|
-
) {
|
|
192
|
+
): void {
|
|
185
193
|
ctx.assignments.push({
|
|
186
194
|
t: 'set',
|
|
187
195
|
s: getRefParam(ctx, ref),
|
|
@@ -195,7 +203,7 @@ function createAppendAssignment(
|
|
|
195
203
|
ref: number,
|
|
196
204
|
key: string,
|
|
197
205
|
value: string,
|
|
198
|
-
) {
|
|
206
|
+
): void {
|
|
199
207
|
ctx.assignments.push({
|
|
200
208
|
t: 'append',
|
|
201
209
|
s: getRefParam(ctx, ref),
|
|
@@ -209,7 +217,7 @@ function createArrayAssign(
|
|
|
209
217
|
ref: number,
|
|
210
218
|
index: number | string,
|
|
211
219
|
value: string,
|
|
212
|
-
) {
|
|
220
|
+
): void {
|
|
213
221
|
createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
|
|
214
222
|
}
|
|
215
223
|
|
|
@@ -218,7 +226,7 @@ function createObjectAssign(
|
|
|
218
226
|
ref: number,
|
|
219
227
|
key: string,
|
|
220
228
|
value: string,
|
|
221
|
-
) {
|
|
229
|
+
): void {
|
|
222
230
|
markRef(ctx, ref);
|
|
223
231
|
createAssignment(ctx, getRefParam(ctx, ref) + '.' + key, value);
|
|
224
232
|
}
|
|
@@ -227,7 +235,7 @@ function assignIndexedValue(
|
|
|
227
235
|
ctx: SerializationContext,
|
|
228
236
|
index: number,
|
|
229
237
|
value: string,
|
|
230
|
-
) {
|
|
238
|
+
): string {
|
|
231
239
|
if (ctx.markedRefs.has(index)) {
|
|
232
240
|
return getRefParam(ctx, index) + '=' + value;
|
|
233
241
|
}
|
|
@@ -241,33 +249,31 @@ function isIndexedValueInStack(
|
|
|
241
249
|
return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
|
|
242
250
|
}
|
|
243
251
|
|
|
244
|
-
|
|
245
|
-
| SerovalArrayNode
|
|
246
|
-
| SerovalIterableNode;
|
|
247
|
-
|
|
248
|
-
function serializeNodeList(
|
|
252
|
+
function serializeArray(
|
|
249
253
|
ctx: SerializationContext,
|
|
250
|
-
node:
|
|
251
|
-
) {
|
|
254
|
+
node: SerovalArrayNode,
|
|
255
|
+
): string {
|
|
256
|
+
const id = node.i;
|
|
257
|
+
ctx.stack.push(id);
|
|
252
258
|
// This is different than Map and Set
|
|
253
259
|
// because we also need to serialize
|
|
254
260
|
// the holes of the Array
|
|
255
|
-
const size = node.l;
|
|
256
261
|
let values = '';
|
|
257
|
-
let item: SerovalNode;
|
|
262
|
+
let item: SerovalNode | undefined;
|
|
258
263
|
let isHoley = false;
|
|
259
|
-
|
|
264
|
+
const list = node.a;
|
|
265
|
+
for (let i = 0, len = node.l; i < len; i++) {
|
|
260
266
|
if (i !== 0) {
|
|
261
267
|
// Add an empty item
|
|
262
268
|
values += ',';
|
|
263
269
|
}
|
|
264
|
-
item =
|
|
270
|
+
item = list[i];
|
|
265
271
|
// Check if index is a hole
|
|
266
272
|
if (item) {
|
|
267
273
|
// Check if item is a parent
|
|
268
274
|
if (isIndexedValueInStack(ctx, item)) {
|
|
269
|
-
markRef(ctx,
|
|
270
|
-
createArrayAssign(ctx,
|
|
275
|
+
markRef(ctx, id);
|
|
276
|
+
createArrayAssign(ctx, id, i, getRefParam(ctx, item.i));
|
|
271
277
|
isHoley = true;
|
|
272
278
|
} else {
|
|
273
279
|
values += serializeTree(ctx, item);
|
|
@@ -277,30 +283,46 @@ function serializeNodeList(
|
|
|
277
283
|
isHoley = true;
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
|
-
|
|
286
|
+
ctx.stack.pop();
|
|
287
|
+
return assignIndexedValue(ctx, id, '[' + values + (isHoley ? ',]' : ']'));
|
|
281
288
|
}
|
|
282
289
|
|
|
283
|
-
function
|
|
290
|
+
function getIterableAccess(ctx: SerializationContext): string {
|
|
291
|
+
return ctx.features & Feature.ArrayPrototypeValues
|
|
292
|
+
? '.values()'
|
|
293
|
+
: '[Symbol.iterator]()';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function serializeIterable(
|
|
284
297
|
ctx: SerializationContext,
|
|
285
|
-
node:
|
|
286
|
-
) {
|
|
287
|
-
ctx.stack
|
|
288
|
-
|
|
289
|
-
ctx
|
|
290
|
-
|
|
298
|
+
node: SerovalNode,
|
|
299
|
+
): string {
|
|
300
|
+
const parent = ctx.stack;
|
|
301
|
+
ctx.stack = [];
|
|
302
|
+
let serialized = serializeTree(ctx, node) + getIterableAccess(ctx);
|
|
303
|
+
ctx.stack = parent;
|
|
304
|
+
if (ctx.features & Feature.ArrowFunction) {
|
|
305
|
+
serialized = '[Symbol.iterator]:()=>' + serialized;
|
|
306
|
+
} else if (ctx.features & Feature.MethodShorthand) {
|
|
307
|
+
serialized = '[Symbol.iterator](){return ' + serialized + '}';
|
|
308
|
+
} else {
|
|
309
|
+
serialized = '[Symbol.iterator]:function(){return ' + serialized + '}';
|
|
310
|
+
}
|
|
311
|
+
return serialized;
|
|
291
312
|
}
|
|
292
313
|
|
|
293
314
|
function serializeProperties(
|
|
294
315
|
ctx: SerializationContext,
|
|
295
316
|
sourceID: number,
|
|
296
317
|
node: SerovalObjectRecordNode,
|
|
297
|
-
) {
|
|
298
|
-
|
|
318
|
+
): string {
|
|
319
|
+
const len = node.s;
|
|
320
|
+
if (len === 0) {
|
|
299
321
|
return '{}';
|
|
300
322
|
}
|
|
301
323
|
let result = '';
|
|
302
324
|
ctx.stack.push(sourceID);
|
|
303
|
-
let key:
|
|
325
|
+
let key: SerovalObjectRecordKey;
|
|
304
326
|
let val: SerovalNode;
|
|
305
327
|
let check: number;
|
|
306
328
|
let isIdentifier: boolean;
|
|
@@ -308,27 +330,34 @@ function serializeProperties(
|
|
|
308
330
|
let hasPrev = false;
|
|
309
331
|
const keys = node.k;
|
|
310
332
|
const values = node.v;
|
|
311
|
-
for (let i = 0
|
|
333
|
+
for (let i = 0; i < len; i++) {
|
|
312
334
|
key = keys[i];
|
|
313
335
|
val = values[i];
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
switch (key) {
|
|
337
|
+
case SerovalObjectRecordSpecialKey.SymbolIterator:
|
|
338
|
+
result += (hasPrev ? ',' : '') + serializeIterable(ctx, val);
|
|
339
|
+
hasPrev = true;
|
|
340
|
+
break;
|
|
341
|
+
default:
|
|
342
|
+
check = Number(key);
|
|
343
|
+
// Test if key is a valid number or JS identifier
|
|
344
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
345
|
+
isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
346
|
+
if (isIndexedValueInStack(ctx, val)) {
|
|
347
|
+
refParam = getRefParam(ctx, val.i);
|
|
348
|
+
markRef(ctx, sourceID);
|
|
349
|
+
if (isIdentifier && Number.isNaN(check)) {
|
|
350
|
+
createObjectAssign(ctx, sourceID, key, refParam);
|
|
351
|
+
} else {
|
|
352
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + key + '"'), refParam);
|
|
353
|
+
}
|
|
354
|
+
} else {
|
|
355
|
+
result += (hasPrev ? ',' : '')
|
|
356
|
+
+ (isIdentifier ? key : ('"' + key + '"'))
|
|
357
|
+
+ ':' + serializeTree(ctx, val);
|
|
358
|
+
hasPrev = true;
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
332
361
|
}
|
|
333
362
|
}
|
|
334
363
|
ctx.stack.pop();
|
|
@@ -340,7 +369,7 @@ function serializeWithObjectAssign(
|
|
|
340
369
|
value: SerovalObjectRecordNode,
|
|
341
370
|
id: number,
|
|
342
371
|
serialized: string,
|
|
343
|
-
) {
|
|
372
|
+
): string {
|
|
344
373
|
const fields = serializeProperties(ctx, id, value);
|
|
345
374
|
if (fields !== '{}') {
|
|
346
375
|
return 'Object.assign(' + serialized + ',' + fields + ')';
|
|
@@ -352,33 +381,47 @@ function serializeAssignments(
|
|
|
352
381
|
ctx: SerializationContext,
|
|
353
382
|
sourceID: number,
|
|
354
383
|
node: SerovalObjectRecordNode,
|
|
355
|
-
) {
|
|
384
|
+
): string | undefined {
|
|
356
385
|
ctx.stack.push(sourceID);
|
|
357
386
|
const mainAssignments: Assignment[] = [];
|
|
358
|
-
let
|
|
359
|
-
let
|
|
360
|
-
let key: string;
|
|
361
|
-
let check: number;
|
|
387
|
+
let key: SerovalObjectRecordKey;
|
|
388
|
+
let value: SerovalNode;
|
|
362
389
|
let parentAssignment: Assignment[];
|
|
363
|
-
let isIdentifier: boolean;
|
|
364
390
|
const keys = node.k;
|
|
365
391
|
const values = node.v;
|
|
366
392
|
for (let i = 0, len = node.s; i < len; i++) {
|
|
367
|
-
parentStack = ctx.stack;
|
|
368
|
-
ctx.stack = [];
|
|
369
|
-
refParam = serializeTree(ctx, values[i]);
|
|
370
|
-
ctx.stack = parentStack;
|
|
371
393
|
key = keys[i];
|
|
372
|
-
|
|
394
|
+
value = values[i];
|
|
373
395
|
parentAssignment = ctx.assignments;
|
|
374
396
|
ctx.assignments = mainAssignments;
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
397
|
+
switch (key) {
|
|
398
|
+
case SerovalObjectRecordSpecialKey.SymbolIterator: {
|
|
399
|
+
const parent = ctx.stack;
|
|
400
|
+
ctx.stack = [];
|
|
401
|
+
const serialized = serializeTree(ctx, value) + getIterableAccess(ctx);
|
|
402
|
+
ctx.stack = parent;
|
|
403
|
+
createArrayAssign(
|
|
404
|
+
ctx,
|
|
405
|
+
sourceID,
|
|
406
|
+
'Symbol.iterator',
|
|
407
|
+
ctx.features & Feature.ArrowFunction
|
|
408
|
+
? '()=>' + serialized
|
|
409
|
+
: 'function(){return ' + serialized + '}',
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
break;
|
|
413
|
+
default: {
|
|
414
|
+
const serialized = serializeTree(ctx, value);
|
|
415
|
+
const check = Number(key);
|
|
416
|
+
// Test if key is a valid number or JS identifier
|
|
417
|
+
// so that we don't have to serialize the key and wrap with brackets
|
|
418
|
+
const isIdentifier = check >= 0 || isValidIdentifier(key);
|
|
419
|
+
if (isIdentifier && Number.isNaN(check)) {
|
|
420
|
+
createObjectAssign(ctx, sourceID, key, serialized);
|
|
421
|
+
} else {
|
|
422
|
+
createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
382
425
|
}
|
|
383
426
|
ctx.assignments = parentAssignment;
|
|
384
427
|
}
|
|
@@ -391,7 +434,7 @@ function serializeDictionary(
|
|
|
391
434
|
i: number,
|
|
392
435
|
d: SerovalObjectRecordNode | undefined,
|
|
393
436
|
init: string,
|
|
394
|
-
) {
|
|
437
|
+
): string {
|
|
395
438
|
if (d) {
|
|
396
439
|
if (ctx.features & Feature.ObjectAssign) {
|
|
397
440
|
init = serializeWithObjectAssign(ctx, d, i, init);
|
|
@@ -406,36 +449,40 @@ function serializeDictionary(
|
|
|
406
449
|
return assignIndexedValue(ctx, i, init);
|
|
407
450
|
}
|
|
408
451
|
|
|
452
|
+
const NULL_CONSTRUCTOR = 'Object.create(null)';
|
|
453
|
+
|
|
409
454
|
function serializeNullConstructor(
|
|
410
455
|
ctx: SerializationContext,
|
|
411
456
|
node: SerovalNullConstructorNode,
|
|
412
|
-
) {
|
|
413
|
-
return serializeDictionary(ctx, node.i, node.d,
|
|
457
|
+
): string {
|
|
458
|
+
return serializeDictionary(ctx, node.i, node.d, NULL_CONSTRUCTOR);
|
|
414
459
|
}
|
|
415
460
|
|
|
416
461
|
function serializeObject(
|
|
417
462
|
ctx: SerializationContext,
|
|
418
463
|
node: SerovalObjectNode,
|
|
419
|
-
) {
|
|
464
|
+
): string {
|
|
420
465
|
return assignIndexedValue(ctx, node.i, serializeProperties(ctx, node.i, node.d));
|
|
421
466
|
}
|
|
422
467
|
|
|
423
468
|
function serializeSet(
|
|
424
469
|
ctx: SerializationContext,
|
|
425
470
|
node: SerovalSetNode,
|
|
426
|
-
) {
|
|
471
|
+
): string {
|
|
427
472
|
let serialized = 'new Set';
|
|
428
473
|
const size = node.l;
|
|
474
|
+
const id = node.i;
|
|
429
475
|
if (size) {
|
|
430
476
|
let result = '';
|
|
431
|
-
ctx.stack.push(node.i);
|
|
432
477
|
let item: SerovalNode;
|
|
433
478
|
let hasPrev = false;
|
|
479
|
+
const items = node.a;
|
|
480
|
+
ctx.stack.push(id);
|
|
434
481
|
for (let i = 0; i < size; i++) {
|
|
435
|
-
item =
|
|
482
|
+
item = items[i];
|
|
436
483
|
if (isIndexedValueInStack(ctx, item)) {
|
|
437
|
-
markRef(ctx,
|
|
438
|
-
createAddAssignment(ctx,
|
|
484
|
+
markRef(ctx, id);
|
|
485
|
+
createAddAssignment(ctx, id, getRefParam(ctx, item.i));
|
|
439
486
|
} else {
|
|
440
487
|
// Push directly
|
|
441
488
|
result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
|
|
@@ -447,38 +494,42 @@ function serializeSet(
|
|
|
447
494
|
serialized += '([' + result + '])';
|
|
448
495
|
}
|
|
449
496
|
}
|
|
450
|
-
return assignIndexedValue(ctx,
|
|
497
|
+
return assignIndexedValue(ctx, id, serialized);
|
|
451
498
|
}
|
|
452
499
|
|
|
453
500
|
function serializeMap(
|
|
454
501
|
ctx: SerializationContext,
|
|
455
502
|
node: SerovalMapNode,
|
|
456
|
-
) {
|
|
503
|
+
): string {
|
|
457
504
|
let serialized = 'new Map';
|
|
458
|
-
|
|
505
|
+
const size = node.d.s;
|
|
506
|
+
const id = node.i;
|
|
507
|
+
if (size) {
|
|
459
508
|
let result = '';
|
|
460
|
-
ctx.stack.push(node.i);
|
|
461
509
|
let key: SerovalNode;
|
|
462
510
|
let val: SerovalNode;
|
|
463
511
|
let keyRef: string;
|
|
464
512
|
let valueRef: string;
|
|
465
513
|
let parent: number[];
|
|
466
514
|
let hasPrev = false;
|
|
467
|
-
|
|
515
|
+
const keys = node.d.k;
|
|
516
|
+
const vals = node.d.v;
|
|
517
|
+
ctx.stack.push(id);
|
|
518
|
+
for (let i = 0; i < size; i++) {
|
|
468
519
|
// Check if key is a parent
|
|
469
|
-
key =
|
|
470
|
-
val =
|
|
520
|
+
key = keys[i];
|
|
521
|
+
val = vals[i];
|
|
471
522
|
if (isIndexedValueInStack(ctx, key)) {
|
|
472
523
|
// Create reference for the map instance
|
|
473
|
-
keyRef = getRefParam(ctx,
|
|
474
|
-
markRef(ctx,
|
|
524
|
+
keyRef = getRefParam(ctx, id);
|
|
525
|
+
markRef(ctx, id);
|
|
475
526
|
// Check if value is a parent
|
|
476
527
|
if (isIndexedValueInStack(ctx, val)) {
|
|
477
528
|
valueRef = getRefParam(ctx, val.i);
|
|
478
529
|
// Register an assignment since
|
|
479
530
|
// both key and value are a parent of this
|
|
480
531
|
// Map instance
|
|
481
|
-
createSetAssignment(ctx,
|
|
532
|
+
createSetAssignment(ctx, id, keyRef, valueRef);
|
|
482
533
|
} else {
|
|
483
534
|
// Reset the stack
|
|
484
535
|
// This is required because the serialized
|
|
@@ -487,17 +538,17 @@ function serializeMap(
|
|
|
487
538
|
// assignment
|
|
488
539
|
parent = ctx.stack;
|
|
489
540
|
ctx.stack = [];
|
|
490
|
-
createSetAssignment(ctx,
|
|
541
|
+
createSetAssignment(ctx, id, keyRef, serializeTree(ctx, val));
|
|
491
542
|
ctx.stack = parent;
|
|
492
543
|
}
|
|
493
544
|
} else if (isIndexedValueInStack(ctx, val)) {
|
|
494
545
|
// Create ref for the Map instance
|
|
495
546
|
valueRef = getRefParam(ctx, val.i);
|
|
496
|
-
markRef(ctx,
|
|
547
|
+
markRef(ctx, id);
|
|
497
548
|
// Reset stack for the key serialization
|
|
498
549
|
parent = ctx.stack;
|
|
499
550
|
ctx.stack = [];
|
|
500
|
-
createSetAssignment(ctx,
|
|
551
|
+
createSetAssignment(ctx, id, serializeTree(ctx, key), valueRef);
|
|
501
552
|
ctx.stack = parent;
|
|
502
553
|
} else {
|
|
503
554
|
result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
|
|
@@ -512,67 +563,71 @@ function serializeMap(
|
|
|
512
563
|
serialized += '([' + result + '])';
|
|
513
564
|
}
|
|
514
565
|
}
|
|
515
|
-
return assignIndexedValue(ctx,
|
|
566
|
+
return assignIndexedValue(ctx, id, serialized);
|
|
516
567
|
}
|
|
517
568
|
|
|
518
569
|
function serializeAggregateError(
|
|
519
570
|
ctx: SerializationContext,
|
|
520
571
|
node: SerovalAggregateErrorNode,
|
|
521
|
-
) {
|
|
572
|
+
): string {
|
|
522
573
|
// Serialize the required arguments
|
|
523
|
-
|
|
574
|
+
const id = node.i;
|
|
575
|
+
ctx.stack.push(id);
|
|
524
576
|
const serialized = 'new AggregateError([],"' + node.m + '")';
|
|
525
577
|
ctx.stack.pop();
|
|
526
578
|
// `AggregateError` might've been extended
|
|
527
579
|
// either through class or custom properties
|
|
528
580
|
// Make sure to assign extra properties
|
|
529
|
-
return serializeDictionary(ctx,
|
|
581
|
+
return serializeDictionary(ctx, id, node.d, serialized);
|
|
530
582
|
}
|
|
531
583
|
|
|
532
584
|
function serializeError(
|
|
533
585
|
ctx: SerializationContext,
|
|
534
586
|
node: SerovalErrorNode,
|
|
535
|
-
) {
|
|
536
|
-
|
|
537
|
-
return serializeDictionary(ctx, node.i, node.d, serialized);
|
|
587
|
+
): string {
|
|
588
|
+
return serializeDictionary(ctx, node.i, node.d, 'new ' + node.c + '("' + node.m + '")');
|
|
538
589
|
}
|
|
539
590
|
|
|
540
591
|
function serializePromise(
|
|
541
592
|
ctx: SerializationContext,
|
|
542
593
|
node: SerovalPromiseNode,
|
|
543
|
-
) {
|
|
594
|
+
): string {
|
|
544
595
|
let serialized: string;
|
|
545
596
|
// Check if resolved value is a parent expression
|
|
546
|
-
|
|
597
|
+
const fulfilled = node.f;
|
|
598
|
+
const id = node.i;
|
|
599
|
+
if (isIndexedValueInStack(ctx, fulfilled)) {
|
|
547
600
|
// A Promise trick, reference the value
|
|
548
601
|
// inside the `then` expression so that
|
|
549
602
|
// the Promise evaluates after the parent
|
|
550
603
|
// has initialized
|
|
551
|
-
const ref = getRefParam(ctx,
|
|
604
|
+
const ref = getRefParam(ctx, fulfilled.i);
|
|
552
605
|
if (ctx.features & Feature.ArrowFunction) {
|
|
553
606
|
serialized = 'Promise.resolve().then(()=>' + ref + ')';
|
|
554
607
|
} else {
|
|
555
608
|
serialized = 'Promise.resolve().then(function(){return ' + ref + '})';
|
|
556
609
|
}
|
|
557
610
|
} else {
|
|
558
|
-
ctx.stack.push(
|
|
559
|
-
const result = serializeTree(ctx,
|
|
611
|
+
ctx.stack.push(id);
|
|
612
|
+
const result = serializeTree(ctx, fulfilled);
|
|
560
613
|
ctx.stack.pop();
|
|
561
614
|
// just inline the value/reference here
|
|
562
615
|
serialized = 'Promise.resolve(' + result + ')';
|
|
563
616
|
}
|
|
564
|
-
return assignIndexedValue(ctx,
|
|
617
|
+
return assignIndexedValue(ctx, id, serialized);
|
|
565
618
|
}
|
|
566
619
|
|
|
567
620
|
function serializeArrayBuffer(
|
|
568
621
|
ctx: SerializationContext,
|
|
569
622
|
node: SerovalArrayBufferNode,
|
|
570
|
-
) {
|
|
623
|
+
): string {
|
|
571
624
|
let result = 'new Uint8Array(';
|
|
572
|
-
|
|
625
|
+
const buffer = node.s;
|
|
626
|
+
const len = buffer.length;
|
|
627
|
+
if (len) {
|
|
573
628
|
result += '[';
|
|
574
|
-
for (let i = 0
|
|
575
|
-
result += ((i > 0) ? ',' : '') +
|
|
629
|
+
for (let i = 0; i < len; i++) {
|
|
630
|
+
result += ((i > 0) ? ',' : '') + buffer[i];
|
|
576
631
|
}
|
|
577
632
|
result += ']';
|
|
578
633
|
}
|
|
@@ -582,121 +637,115 @@ function serializeArrayBuffer(
|
|
|
582
637
|
function serializeTypedArray(
|
|
583
638
|
ctx: SerializationContext,
|
|
584
639
|
node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
|
|
585
|
-
) {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
ctx: SerializationContext,
|
|
592
|
-
node: SerovalIterableNode,
|
|
593
|
-
) {
|
|
594
|
-
const parent = ctx.stack;
|
|
595
|
-
ctx.stack = [];
|
|
596
|
-
const values = serializeNodeList(ctx, node);
|
|
597
|
-
ctx.stack = parent;
|
|
598
|
-
let serialized = values;
|
|
599
|
-
if (ctx.features & Feature.ArrayPrototypeValues) {
|
|
600
|
-
serialized += '.values()';
|
|
601
|
-
} else {
|
|
602
|
-
serialized += '[Symbol.iterator]()';
|
|
603
|
-
}
|
|
604
|
-
if (ctx.features & Feature.ArrowFunction) {
|
|
605
|
-
serialized = '{[Symbol.iterator]:()=>' + serialized + '}';
|
|
606
|
-
} else if (ctx.features & Feature.MethodShorthand) {
|
|
607
|
-
serialized = '{[Symbol.iterator](){return ' + serialized + '}}';
|
|
608
|
-
} else {
|
|
609
|
-
serialized = '{[Symbol.iterator]:function(){return ' + serialized + '}}';
|
|
610
|
-
}
|
|
611
|
-
return serializeDictionary(ctx, node.i, node.d, serialized);
|
|
640
|
+
): string {
|
|
641
|
+
return assignIndexedValue(
|
|
642
|
+
ctx,
|
|
643
|
+
node.i,
|
|
644
|
+
'new ' + node.c + '(' + serializeTree(ctx, node.f) + ',' + node.b + ',' + node.l + ')',
|
|
645
|
+
);
|
|
612
646
|
}
|
|
613
647
|
|
|
614
648
|
function serializeDate(
|
|
615
649
|
ctx: SerializationContext,
|
|
616
650
|
node: SerovalDateNode,
|
|
617
|
-
) {
|
|
651
|
+
): string {
|
|
618
652
|
return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
|
|
619
653
|
}
|
|
620
654
|
|
|
621
655
|
function serializeRegExp(
|
|
622
656
|
ctx: SerializationContext,
|
|
623
657
|
node: SerovalRegExpNode,
|
|
624
|
-
) {
|
|
658
|
+
): string {
|
|
625
659
|
return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
|
|
626
660
|
}
|
|
627
661
|
|
|
628
662
|
function serializeURL(
|
|
629
663
|
ctx: SerializationContext,
|
|
630
664
|
node: SerovalURLNode,
|
|
631
|
-
) {
|
|
665
|
+
): string {
|
|
632
666
|
return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
|
|
633
667
|
}
|
|
634
668
|
|
|
635
669
|
function serializeURLSearchParams(
|
|
636
670
|
ctx: SerializationContext,
|
|
637
671
|
node: SerovalURLSearchParamsNode,
|
|
638
|
-
) {
|
|
639
|
-
return assignIndexedValue(
|
|
672
|
+
): string {
|
|
673
|
+
return assignIndexedValue(
|
|
674
|
+
ctx,
|
|
675
|
+
node.i,
|
|
676
|
+
node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams',
|
|
677
|
+
);
|
|
640
678
|
}
|
|
641
679
|
|
|
642
680
|
function serializeReference(
|
|
643
681
|
ctx: SerializationContext,
|
|
644
682
|
node: SerovalReferenceNode,
|
|
645
|
-
) {
|
|
683
|
+
): string {
|
|
646
684
|
return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
|
|
647
685
|
}
|
|
648
686
|
|
|
649
687
|
function serializeDataView(
|
|
650
688
|
ctx: SerializationContext,
|
|
651
689
|
node: SerovalDataViewNode,
|
|
652
|
-
) {
|
|
653
|
-
|
|
654
|
-
|
|
690
|
+
): string {
|
|
691
|
+
return assignIndexedValue(
|
|
692
|
+
ctx,
|
|
693
|
+
node.i,
|
|
694
|
+
'new DataView(' + serializeTree(ctx, node.f) + ',' + node.b + ',' + node.l + ')',
|
|
695
|
+
);
|
|
655
696
|
}
|
|
656
697
|
|
|
657
698
|
function serializeBlob(
|
|
658
699
|
ctx: SerializationContext,
|
|
659
700
|
node: SerovalBlobNode,
|
|
660
|
-
) {
|
|
661
|
-
|
|
662
|
-
|
|
701
|
+
): string {
|
|
702
|
+
return assignIndexedValue(
|
|
703
|
+
ctx,
|
|
704
|
+
node.i,
|
|
705
|
+
'new Blob([' + serializeTree(ctx, node.f) + '],{type:"' + node.c + '"})',
|
|
706
|
+
);
|
|
663
707
|
}
|
|
664
708
|
|
|
665
709
|
function serializeFile(
|
|
666
710
|
ctx: SerializationContext,
|
|
667
711
|
node: SerovalFileNode,
|
|
668
|
-
) {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
712
|
+
): string {
|
|
713
|
+
return assignIndexedValue(
|
|
714
|
+
ctx,
|
|
715
|
+
node.i,
|
|
716
|
+
'new File([' + serializeTree(ctx, node.f) + '],"' + node.m + '",{type:"' + node.c + '",lastModified:' + node.b + '})',
|
|
717
|
+
);
|
|
672
718
|
}
|
|
673
719
|
|
|
674
720
|
function serializeHeaders(
|
|
675
721
|
ctx: SerializationContext,
|
|
676
722
|
node: SerovalHeadersNode,
|
|
677
|
-
) {
|
|
678
|
-
return assignIndexedValue(
|
|
723
|
+
): string {
|
|
724
|
+
return assignIndexedValue(
|
|
725
|
+
ctx,
|
|
726
|
+
node.i,
|
|
727
|
+
'new Headers(' + serializeProperties(ctx, node.i, node.d) + ')',
|
|
728
|
+
);
|
|
679
729
|
}
|
|
680
730
|
|
|
681
731
|
function serializeFormDataEntries(
|
|
682
732
|
ctx: SerializationContext,
|
|
683
733
|
node: SerovalFormDataNode,
|
|
684
|
-
) {
|
|
685
|
-
ctx.stack.push(node.i);
|
|
686
|
-
const mainAssignments: Assignment[] = [];
|
|
687
|
-
let parentStack: number[];
|
|
734
|
+
): string | undefined {
|
|
688
735
|
let value: string;
|
|
689
736
|
let key: string;
|
|
737
|
+
const keys = node.d.k;
|
|
738
|
+
const vals = node.d.v;
|
|
739
|
+
const id = node.i;
|
|
740
|
+
const mainAssignments: Assignment[] = [];
|
|
690
741
|
let parentAssignment: Assignment[];
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
value = serializeTree(ctx,
|
|
695
|
-
key = node.d.k[i];
|
|
696
|
-
ctx.stack = parentStack;
|
|
742
|
+
ctx.stack.push(id);
|
|
743
|
+
for (let i = 0, len = node.d.s; i < len; i++) {
|
|
744
|
+
key = keys[i];
|
|
745
|
+
value = serializeTree(ctx, vals[i]);
|
|
697
746
|
parentAssignment = ctx.assignments;
|
|
698
747
|
ctx.assignments = mainAssignments;
|
|
699
|
-
createAppendAssignment(ctx,
|
|
748
|
+
createAppendAssignment(ctx, id, '"' + key + '"', value);
|
|
700
749
|
ctx.assignments = parentAssignment;
|
|
701
750
|
}
|
|
702
751
|
ctx.stack.pop();
|
|
@@ -706,17 +755,34 @@ function serializeFormDataEntries(
|
|
|
706
755
|
function serializeFormData(
|
|
707
756
|
ctx: SerializationContext,
|
|
708
757
|
node: SerovalFormDataNode,
|
|
709
|
-
) {
|
|
710
|
-
|
|
711
|
-
|
|
758
|
+
): string {
|
|
759
|
+
const size = node.d.s;
|
|
760
|
+
const id = node.i;
|
|
761
|
+
if (size) {
|
|
762
|
+
markRef(ctx, id);
|
|
712
763
|
}
|
|
713
|
-
const result = assignIndexedValue(ctx,
|
|
714
|
-
if (
|
|
715
|
-
|
|
764
|
+
const result = assignIndexedValue(ctx, id, 'new FormData()');
|
|
765
|
+
if (size) {
|
|
766
|
+
const entries = serializeFormDataEntries(ctx, node);
|
|
767
|
+
return '(' + result + ',' + (entries == null ? '' : entries) + getRefParam(ctx, id) + ')';
|
|
716
768
|
}
|
|
717
769
|
return result;
|
|
718
770
|
}
|
|
719
771
|
|
|
772
|
+
function serializeBoxed(
|
|
773
|
+
ctx: SerializationContext,
|
|
774
|
+
node: SerovalBoxedNode,
|
|
775
|
+
): string {
|
|
776
|
+
return assignIndexedValue(ctx, node.i, 'Object(' + serializeTree(ctx, node.f) + ')');
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function serializeWKSymbol(
|
|
780
|
+
ctx: SerializationContext,
|
|
781
|
+
node: SerovalWKSymbolNode,
|
|
782
|
+
): string {
|
|
783
|
+
return assignIndexedValue(ctx, node.i, SYMBOL_STRING[node.s]);
|
|
784
|
+
}
|
|
785
|
+
|
|
720
786
|
export default function serializeTree(
|
|
721
787
|
ctx: SerializationContext,
|
|
722
788
|
node: SerovalNode,
|
|
@@ -726,20 +792,8 @@ export default function serializeTree(
|
|
|
726
792
|
return '' + node.s;
|
|
727
793
|
case SerovalNodeType.String:
|
|
728
794
|
return '"' + node.s + '"';
|
|
729
|
-
case SerovalNodeType.
|
|
730
|
-
return node
|
|
731
|
-
case SerovalNodeType.Undefined:
|
|
732
|
-
return 'void 0';
|
|
733
|
-
case SerovalNodeType.Null:
|
|
734
|
-
return 'null';
|
|
735
|
-
case SerovalNodeType.NegativeZero:
|
|
736
|
-
return '-0';
|
|
737
|
-
case SerovalNodeType.Infinity:
|
|
738
|
-
return '1/0';
|
|
739
|
-
case SerovalNodeType.NegativeInfinity:
|
|
740
|
-
return '-1/0';
|
|
741
|
-
case SerovalNodeType.NaN:
|
|
742
|
-
return 'NaN';
|
|
795
|
+
case SerovalNodeType.Constant:
|
|
796
|
+
return serializeConstant(node);
|
|
743
797
|
case SerovalNodeType.BigInt:
|
|
744
798
|
return node.s + 'n';
|
|
745
799
|
case SerovalNodeType.IndexedValue:
|
|
@@ -769,12 +823,10 @@ export default function serializeTree(
|
|
|
769
823
|
return serializeAggregateError(ctx, node);
|
|
770
824
|
case SerovalNodeType.Error:
|
|
771
825
|
return serializeError(ctx, node);
|
|
772
|
-
case SerovalNodeType.Iterable:
|
|
773
|
-
return serializeIterable(ctx, node);
|
|
774
826
|
case SerovalNodeType.Promise:
|
|
775
827
|
return serializePromise(ctx, node);
|
|
776
828
|
case SerovalNodeType.WKSymbol:
|
|
777
|
-
return
|
|
829
|
+
return serializeWKSymbol(ctx, node);
|
|
778
830
|
case SerovalNodeType.URL:
|
|
779
831
|
return serializeURL(ctx, node);
|
|
780
832
|
case SerovalNodeType.URLSearchParams:
|
|
@@ -789,7 +841,9 @@ export default function serializeTree(
|
|
|
789
841
|
return serializeHeaders(ctx, node);
|
|
790
842
|
case SerovalNodeType.FormData:
|
|
791
843
|
return serializeFormData(ctx, node);
|
|
844
|
+
case SerovalNodeType.Boxed:
|
|
845
|
+
return serializeBoxed(ctx, node);
|
|
792
846
|
default:
|
|
793
|
-
throw new Error('
|
|
847
|
+
throw new Error('invariant');
|
|
794
848
|
}
|
|
795
849
|
}
|