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