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