seroval 0.15.1 → 1.0.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 (114) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/development/index.cjs +1287 -1945
  3. package/dist/cjs/development/index.cjs.map +3 -3
  4. package/dist/cjs/production/index.cjs +3 -3
  5. package/dist/esm/development/index.mjs +1288 -1946
  6. package/dist/esm/development/index.mjs.map +3 -3
  7. package/dist/esm/production/index.mjs +3 -3
  8. package/dist/types/core/Serializer.d.ts +2 -1
  9. package/dist/types/core/Serializer.d.ts.map +1 -1
  10. package/dist/types/core/UnsupportedTypeError.d.ts.map +1 -1
  11. package/dist/types/core/base-primitives.d.ts +6 -2
  12. package/dist/types/core/base-primitives.d.ts.map +1 -1
  13. package/dist/types/core/compat.d.ts +5 -13
  14. package/dist/types/core/compat.d.ts.map +1 -1
  15. package/dist/types/core/constants.d.ts +17 -29
  16. package/dist/types/core/constants.d.ts.map +1 -1
  17. package/dist/types/core/context/deserializer.d.ts +6 -16
  18. package/dist/types/core/context/deserializer.d.ts.map +1 -1
  19. package/dist/types/core/context/parser/async.d.ts +2 -11
  20. package/dist/types/core/context/parser/async.d.ts.map +1 -1
  21. package/dist/types/core/context/parser/stream.d.ts +10 -10
  22. package/dist/types/core/context/parser/stream.d.ts.map +1 -1
  23. package/dist/types/core/context/parser/sync.d.ts +5 -7
  24. package/dist/types/core/context/parser/sync.d.ts.map +1 -1
  25. package/dist/types/core/context/parser.d.ts +26 -5
  26. package/dist/types/core/context/parser.d.ts.map +1 -1
  27. package/dist/types/core/context/serializer.d.ts +21 -30
  28. package/dist/types/core/context/serializer.d.ts.map +1 -1
  29. package/dist/types/core/cross/async.d.ts.map +1 -1
  30. package/dist/types/core/cross/deserializer.d.ts.map +1 -1
  31. package/dist/types/core/cross/index.d.ts.map +1 -1
  32. package/dist/types/core/cross/parser.d.ts.map +1 -1
  33. package/dist/types/core/cross/serializer.d.ts +1 -1
  34. package/dist/types/core/cross/serializer.d.ts.map +1 -1
  35. package/dist/types/core/cross/stream.d.ts.map +1 -1
  36. package/dist/types/core/cross/sync.d.ts.map +1 -1
  37. package/dist/types/core/keys.d.ts.map +1 -1
  38. package/dist/types/core/literals.d.ts.map +1 -1
  39. package/dist/types/core/plugin.d.ts +21 -0
  40. package/dist/types/core/plugin.d.ts.map +1 -1
  41. package/dist/types/core/reference.d.ts.map +1 -1
  42. package/dist/types/core/special-reference.d.ts +4 -9
  43. package/dist/types/core/special-reference.d.ts.map +1 -1
  44. package/dist/types/core/stream.d.ts +18 -0
  45. package/dist/types/core/stream.d.ts.map +1 -0
  46. package/dist/types/core/string.d.ts.map +1 -1
  47. package/dist/types/core/tree/async.d.ts.map +1 -1
  48. package/dist/types/core/tree/deserializer.d.ts.map +1 -1
  49. package/dist/types/core/tree/index.d.ts +1 -1
  50. package/dist/types/core/tree/index.d.ts.map +1 -1
  51. package/dist/types/core/tree/serializer.d.ts +3 -11
  52. package/dist/types/core/tree/serializer.d.ts.map +1 -1
  53. package/dist/types/core/types.d.ts +28 -122
  54. package/dist/types/core/types.d.ts.map +1 -1
  55. package/dist/types/core/utils/deferred.d.ts +0 -7
  56. package/dist/types/core/utils/deferred.d.ts.map +1 -1
  57. package/dist/types/core/utils/error.d.ts +2 -1
  58. package/dist/types/core/utils/error.d.ts.map +1 -1
  59. package/dist/types/core/utils/get-identifier.d.ts.map +1 -1
  60. package/dist/types/core/utils/is-valid-identifier.d.ts.map +1 -1
  61. package/dist/types/core/utils/iterator-to-sequence.d.ts +0 -12
  62. package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -1
  63. package/dist/types/core/utils/typed-array.d.ts +2 -0
  64. package/dist/types/core/utils/typed-array.d.ts.map +1 -1
  65. package/dist/types/index.d.ts +2 -3
  66. package/dist/types/index.d.ts.map +1 -1
  67. package/package.json +7 -7
  68. package/src/core/Serializer.ts +44 -28
  69. package/src/core/UnsupportedTypeError.ts +2 -3
  70. package/src/core/base-primitives.ts +124 -38
  71. package/src/core/compat.ts +5 -14
  72. package/src/core/constants.ts +28 -39
  73. package/src/core/context/deserializer.ts +122 -308
  74. package/src/core/context/parser/async.ts +163 -375
  75. package/src/core/context/parser/stream.ts +110 -381
  76. package/src/core/context/parser/sync.ts +125 -266
  77. package/src/core/context/parser.ts +119 -68
  78. package/src/core/context/serializer.ts +396 -473
  79. package/src/core/cross/async.ts +1 -1
  80. package/src/core/cross/deserializer.ts +1 -4
  81. package/src/core/cross/index.ts +26 -20
  82. package/src/core/cross/parser.ts +1 -1
  83. package/src/core/cross/serializer.ts +30 -20
  84. package/src/core/cross/stream.ts +1 -1
  85. package/src/core/cross/sync.ts +1 -1
  86. package/src/core/keys.ts +3 -1
  87. package/src/core/literals.ts +22 -8
  88. package/src/core/plugin.ts +48 -10
  89. package/src/core/reference.ts +4 -5
  90. package/src/core/special-reference.ts +5 -15
  91. package/src/core/stream.ts +205 -0
  92. package/src/core/string.ts +53 -22
  93. package/src/core/tree/async.ts +1 -1
  94. package/src/core/tree/deserializer.ts +4 -9
  95. package/src/core/tree/index.ts +15 -10
  96. package/src/core/tree/serializer.ts +6 -50
  97. package/src/core/types.ts +39 -179
  98. package/src/core/utils/deferred.ts +0 -27
  99. package/src/core/utils/error.ts +26 -15
  100. package/src/core/utils/get-identifier.ts +5 -4
  101. package/src/core/utils/is-valid-identifier.ts +6 -5
  102. package/src/core/utils/iterator-to-sequence.ts +0 -174
  103. package/src/core/utils/typed-array.ts +35 -11
  104. package/src/index.ts +3 -12
  105. package/dist/types/core/utils/constructors.d.ts +0 -5
  106. package/dist/types/core/utils/constructors.d.ts.map +0 -1
  107. package/dist/types/core/web-api.d.ts +0 -8
  108. package/dist/types/core/web-api.d.ts.map +0 -1
  109. package/dist/types/types.d.ts +0 -21
  110. package/dist/types/types.d.ts.map +0 -1
  111. package/src/core/utils/constructors.ts +0 -49
  112. package/src/core/web-api.ts +0 -138
  113. package/src/example.ts +0 -25
  114. package/src/types.ts +0 -84
@@ -30,59 +30,54 @@ import type {
30
30
  SerovalErrorNode,
31
31
  SerovalPromiseNode,
32
32
  SerovalWKSymbolNode,
33
- SerovalURLNode,
34
- SerovalURLSearchParamsNode,
35
- SerovalBlobNode,
36
- SerovalFileNode,
37
- SerovalHeadersNode,
38
- SerovalFormDataNode,
39
33
  SerovalBoxedNode,
40
- SerovalRequestNode,
41
- SerovalResponseNode,
42
- SerovalEventNode,
43
- SerovalCustomEventNode,
44
- SerovalDOMExceptionNode,
45
34
  SerovalPluginNode,
46
35
  SerovalPromiseConstructorNode,
47
36
  SerovalPromiseResolveNode,
48
37
  SerovalPromiseRejectNode,
49
- SerovalReadableStreamConstructorNode,
50
- SerovalReadableStreamEnqueueNode,
51
- SerovalReadableStreamErrorNode,
52
- SerovalReadableStreamCloseNode,
53
38
  SerovalIteratorFactoryInstanceNode,
54
39
  SerovalIteratorFactoryNode,
55
40
  SerovalAsyncIteratorFactoryInstanceNode,
56
41
  SerovalAsyncIteratorFactoryNode,
57
- SerovalReadableStreamNode,
58
42
  SerovalSpecialReferenceNode,
59
43
  SerovalNodeWithID,
44
+ SerovalStreamConstructorNode,
45
+ SerovalStreamNextNode,
46
+ SerovalStreamThrowNode,
47
+ SerovalStreamReturnNode,
60
48
  } from '../types';
61
49
  import { isValidIdentifier } from '../utils/is-valid-identifier';
62
50
 
51
+ const enum AssignmentType {
52
+ Index = 0,
53
+ Add = 1,
54
+ Set = 2,
55
+ Delete = 3,
56
+ }
57
+
63
58
  interface IndexAssignment {
64
- t: 'index';
59
+ t: AssignmentType.Index;
65
60
  s: string;
66
61
  k: undefined;
67
62
  v: string;
68
63
  }
69
64
 
70
65
  interface SetAssignment {
71
- t: 'set';
66
+ t: AssignmentType.Set;
72
67
  s: string;
73
68
  k: string;
74
69
  v: string;
75
70
  }
76
71
 
77
72
  interface AddAssignment {
78
- t: 'add';
73
+ t: AssignmentType.Add;
79
74
  s: string;
80
75
  k: undefined;
81
76
  v: string;
82
77
  }
83
78
 
84
79
  interface DeleteAssignment {
85
- t: 'delete';
80
+ t: AssignmentType.Delete;
86
81
  s: string;
87
82
  k: string;
88
83
  v: undefined;
@@ -102,53 +97,55 @@ export interface FlaggedObject {
102
97
 
103
98
  function getAssignmentExpression(assignment: Assignment): string {
104
99
  switch (assignment.t) {
105
- case 'index':
100
+ case AssignmentType.Index:
106
101
  return assignment.s + '=' + assignment.v;
107
- case 'set':
102
+ case AssignmentType.Set:
108
103
  return assignment.s + '.set(' + assignment.k + ',' + assignment.v + ')';
109
- case 'add':
104
+ case AssignmentType.Add:
110
105
  return assignment.s + '.add(' + assignment.v + ')';
111
- case 'delete':
106
+ case AssignmentType.Delete:
112
107
  return assignment.s + '.delete(' + assignment.k + ')';
113
- default:
114
- return '';
115
108
  }
116
109
  }
117
110
 
118
111
  function mergeAssignments(assignments: Assignment[]): Assignment[] {
119
112
  const newAssignments: Assignment[] = [];
120
113
  let current = assignments[0];
121
- for (let i = 1, len = assignments.length, item: Assignment, prev = current; i < len; i++) {
114
+ for (
115
+ let i = 1, len = assignments.length, item: Assignment, prev = current;
116
+ i < len;
117
+ i++
118
+ ) {
122
119
  item = assignments[i];
123
- if (item.t === 'index' && item.v === prev.v) {
120
+ if (item.t === AssignmentType.Index && item.v === prev.v) {
124
121
  // Merge if the right-hand value is the same
125
122
  // saves at least 2 chars
126
123
  current = {
127
- t: 'index',
124
+ t: AssignmentType.Index,
128
125
  s: item.s,
129
126
  k: undefined,
130
127
  v: getAssignmentExpression(current),
131
128
  } as IndexAssignment;
132
- } else if (item.t === 'set' && item.s === prev.s) {
129
+ } else if (item.t === AssignmentType.Set && item.s === prev.s) {
133
130
  // Maps has chaining methods, merge if source is the same
134
131
  current = {
135
- t: 'set',
132
+ t: AssignmentType.Set,
136
133
  s: getAssignmentExpression(current),
137
134
  k: item.k,
138
135
  v: item.v,
139
136
  } as SetAssignment;
140
- } else if (item.t === 'add' && item.s === prev.s) {
137
+ } else if (item.t === AssignmentType.Add && item.s === prev.s) {
141
138
  // Sets has chaining methods too
142
139
  current = {
143
- t: 'add',
140
+ t: AssignmentType.Add,
144
141
  s: getAssignmentExpression(current),
145
142
  k: undefined,
146
143
  v: item.v,
147
144
  } as AddAssignment;
148
- } else if (item.t === 'delete' && item.s === prev.s) {
145
+ } else if (item.t === AssignmentType.Delete && item.s === prev.s) {
149
146
  // Maps has chaining methods, merge if source is the same
150
147
  current = {
151
- t: 'delete',
148
+ t: AssignmentType.Delete,
152
149
  s: getAssignmentExpression(current),
153
150
  k: item.k,
154
151
  v: undefined,
@@ -185,26 +182,28 @@ const MAP_CONSTRUCTOR = 'new Map';
185
182
  const PROMISE_RESOLVE = 'Promise.resolve';
186
183
  const PROMISE_REJECT = 'Promise.reject';
187
184
 
188
- const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> = {
189
- [SerovalObjectFlags.Frozen]: 'Object.freeze',
190
- [SerovalObjectFlags.Sealed]: 'Object.seal',
191
- [SerovalObjectFlags.NonExtensible]: 'Object.preventExtensions',
192
- [SerovalObjectFlags.None]: undefined,
193
- };
185
+ const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> =
186
+ {
187
+ [SerovalObjectFlags.Frozen]: 'Object.freeze',
188
+ [SerovalObjectFlags.Sealed]: 'Object.seal',
189
+ [SerovalObjectFlags.NonExtensible]: 'Object.preventExtensions',
190
+ [SerovalObjectFlags.None]: undefined,
191
+ };
194
192
 
195
193
  type SerovalNodeWithProperties =
196
194
  | SerovalObjectNode
197
195
  | SerovalNullConstructorNode
198
196
  | SerovalAggregateErrorNode
199
- | SerovalErrorNode
200
- | SerovalHeadersNode;
197
+ | SerovalErrorNode;
201
198
 
202
199
  export interface BaseSerializerContextOptions extends PluginAccessOptions {
203
200
  features: number;
204
201
  markedRefs: number[] | Set<number>;
205
202
  }
206
203
 
207
- export default abstract class BaseSerializerContext implements PluginAccessOptions {
204
+ export default abstract class BaseSerializerContext
205
+ implements PluginAccessOptions
206
+ {
208
207
  /**
209
208
  * @private
210
209
  */
@@ -244,27 +243,23 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
244
243
 
245
244
  abstract readonly mode: SerovalMode;
246
245
 
247
- protected createFunction(
248
- parameters: string[],
249
- body: string,
250
- ): string {
246
+ createFunction(parameters: string[], body: string): string {
251
247
  if (this.features & Feature.ArrowFunction) {
252
- const joined = parameters.length === 1
253
- ? parameters[0]
254
- : '(' + parameters.join(',') + ')';
248
+ const joined =
249
+ parameters.length === 1
250
+ ? parameters[0]
251
+ : '(' + parameters.join(',') + ')';
255
252
  return joined + '=>' + body;
256
253
  }
257
254
  return 'function(' + parameters.join(',') + '){return ' + body + '}';
258
255
  }
259
256
 
260
- protected createEffectfulFunction(
261
- parameters: string[],
262
- body: string,
263
- ): string {
257
+ createEffectfulFunction(parameters: string[], body: string): string {
264
258
  if (this.features & Feature.ArrowFunction) {
265
- const joined = parameters.length === 1
266
- ? parameters[0]
267
- : '(' + parameters.join(',') + ')';
259
+ const joined =
260
+ parameters.length === 1
261
+ ? parameters[0]
262
+ : '(' + parameters.join(',') + ')';
268
263
  return joined + '=>{' + body + '}';
269
264
  }
270
265
  return 'function(' + parameters.join(',') + '){' + body + '}';
@@ -289,7 +284,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
289
284
  * that is used to refer to the object instance in the
290
285
  * generated script.
291
286
  */
292
- abstract getRefParam(id: number | string): string;
287
+ abstract getRefParam(id: number): string;
293
288
 
294
289
  protected pushObjectFlag(flag: SerovalObjectFlags, id: number): void {
295
290
  if (flag !== SerovalObjectFlags.None) {
@@ -327,49 +322,36 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
327
322
  * This is different from the assignments array as this one
328
323
  * signifies creation rather than mutation
329
324
  */
330
- protected createAssignment(
331
- source: string,
332
- value: string,
333
- ): void {
325
+ protected createAssignment(source: string, value: string): void {
334
326
  this.assignments.push({
335
- t: 'index',
327
+ t: AssignmentType.Index,
336
328
  s: source,
337
329
  k: undefined,
338
330
  v: value,
339
331
  });
340
332
  }
341
333
 
342
- protected createAddAssignment(
343
- ref: number,
344
- value: string,
345
- ): void {
334
+ protected createAddAssignment(ref: number, value: string): void {
346
335
  this.assignments.push({
347
- t: 'add',
336
+ t: AssignmentType.Add,
348
337
  s: this.getRefParam(ref),
349
338
  k: undefined,
350
339
  v: value,
351
340
  });
352
341
  }
353
342
 
354
- protected createSetAssignment(
355
- ref: number,
356
- key: string,
357
- value: string,
358
- ): void {
343
+ protected createSetAssignment(ref: number, key: string, value: string): void {
359
344
  this.assignments.push({
360
- t: 'set',
345
+ t: AssignmentType.Set,
361
346
  s: this.getRefParam(ref),
362
347
  k: key,
363
348
  v: value,
364
349
  });
365
350
  }
366
351
 
367
- protected createDeleteAssignment(
368
- ref: number,
369
- key: string,
370
- ): void {
352
+ protected createDeleteAssignment(ref: number, key: string): void {
371
353
  this.assignments.push({
372
- t: 'delete',
354
+ t: AssignmentType.Delete,
373
355
  s: this.getRefParam(ref),
374
356
  k: key,
375
357
  v: undefined,
@@ -384,11 +366,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
384
366
  this.createAssignment(this.getRefParam(ref) + '[' + index + ']', value);
385
367
  }
386
368
 
387
- protected createObjectAssign(
388
- ref: number,
389
- key: string,
390
- value: string,
391
- ): void {
369
+ protected createObjectAssign(ref: number, key: string, value: string): void {
392
370
  this.createAssignment(this.getRefParam(ref) + '.' + key, value);
393
371
  }
394
372
 
@@ -396,10 +374,10 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
396
374
  * Checks if the value is in the stack. Stack here is a reference
397
375
  * structure to know if a object is to be accessed in a TDZ.
398
376
  */
399
- isIndexedValueInStack(
400
- node: SerovalNode,
401
- ): boolean {
402
- return node.t === SerovalNodeType.IndexedValue && this.stack.includes(node.i);
377
+ isIndexedValueInStack(node: SerovalNode): boolean {
378
+ return (
379
+ node.t === SerovalNodeType.IndexedValue && this.stack.includes(node.i)
380
+ );
403
381
  }
404
382
 
405
383
  /**
@@ -408,15 +386,13 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
408
386
  * return the reference parameter directly or assign a value to
409
387
  * it.
410
388
  */
411
- protected abstract assignIndexedValue(
412
- id: number,
413
- value: string,
414
- ): string;
389
+ protected abstract assignIndexedValue(id: number, value: string): string;
415
390
 
416
- protected serializeReference(
417
- node: SerovalReferenceNode,
418
- ): string {
419
- return this.assignIndexedValue(node.i, REFERENCES_KEY + '.get("' + node.s + '")');
391
+ protected serializeReference(node: SerovalReferenceNode): string {
392
+ return this.assignIndexedValue(
393
+ node.i,
394
+ REFERENCES_KEY + '.get("' + node.s + '")',
395
+ );
420
396
  }
421
397
 
422
398
  protected serializeArrayItem(
@@ -429,7 +405,11 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
429
405
  // Check if item is a parent
430
406
  if (this.isIndexedValueInStack(item)) {
431
407
  this.markRef(id);
432
- this.createArrayAssign(id, index, this.getRefParam((item as SerovalIndexedValueNode).i));
408
+ this.createArrayAssign(
409
+ id,
410
+ index,
411
+ this.getRefParam((item as SerovalIndexedValueNode).i),
412
+ );
433
413
  return '';
434
414
  }
435
415
  return this.serialize(item);
@@ -437,17 +417,15 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
437
417
  return '';
438
418
  }
439
419
 
440
- protected serializeArray(
441
- node: SerovalArrayNode,
442
- ): string {
420
+ protected serializeArray(node: SerovalArrayNode): string {
443
421
  const id = node.i;
444
422
  if (node.l) {
445
423
  this.stack.push(id);
424
+ const list = node.a;
425
+ let values = this.serializeArrayItem(id, list[0], 0);
446
426
  // This is different than Map and Set
447
427
  // because we also need to serialize
448
428
  // the holes of the Array
449
- const list = node.a;
450
- let values = this.serializeArrayItem(id, list[0], 0);
451
429
  let isHoley = values === '';
452
430
  for (let i = 1, len = node.l, item: string; i < len; i++) {
453
431
  item = this.serializeArrayItem(id, list[i], i);
@@ -474,15 +452,18 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
474
452
  if (this.isIndexedValueInStack(val)) {
475
453
  const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
476
454
  this.markRef(source.i);
477
- // eslint-disable-next-line no-self-compare
478
455
  if (isIdentifier && check !== check) {
479
456
  this.createObjectAssign(source.i, key, refParam);
480
457
  } else {
481
- this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), refParam);
458
+ this.createArrayAssign(
459
+ source.i,
460
+ isIdentifier ? key : '"' + key + '"',
461
+ refParam,
462
+ );
482
463
  }
483
464
  return '';
484
465
  }
485
- return (isIdentifier ? key : ('"' + key + '"')) + ':' + this.serialize(val);
466
+ return (isIdentifier ? key : '"' + key + '"') + ':' + this.serialize(val);
486
467
  }
487
468
  return '[' + this.serialize(key) + ']:' + this.serialize(val);
488
469
  }
@@ -493,9 +474,9 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
493
474
  ): string {
494
475
  const len = record.s;
495
476
  if (len) {
496
- this.stack.push(source.i);
497
477
  const keys = record.k;
498
478
  const values = record.v;
479
+ this.stack.push(source.i);
499
480
  let result = this.serializeProperty(source, keys[0], values[0]);
500
481
  for (let i = 1, item = result; i < len; i++) {
501
482
  item = this.serializeProperty(source, keys[i], values[i]);
@@ -507,11 +488,12 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
507
488
  return '{}';
508
489
  }
509
490
 
510
- protected serializeObject(
511
- node: SerovalObjectNode,
512
- ): string {
491
+ protected serializeObject(node: SerovalObjectNode): string {
513
492
  this.pushObjectFlag(node.o, node.i);
514
- return this.assignIndexedValue(node.i, this.serializeProperties(node, node.p));
493
+ return this.assignIndexedValue(
494
+ node.i,
495
+ this.serializeProperties(node, node.p),
496
+ );
515
497
  }
516
498
 
517
499
  protected serializeWithObjectAssign(
@@ -526,6 +508,43 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
526
508
  return serialized;
527
509
  }
528
510
 
511
+ private serializeStringKeyAssignment(
512
+ source: SerovalNodeWithProperties,
513
+ mainAssignments: Assignment[],
514
+ key: string,
515
+ value: SerovalNode,
516
+ ): void {
517
+ const serialized = this.serialize(value);
518
+ const check = Number(key);
519
+ // Test if key is a valid number or JS identifier
520
+ // so that we don't have to serialize the key and wrap with brackets
521
+ const isIdentifier = check >= 0 || isValidIdentifier(key);
522
+ if (this.isIndexedValueInStack(value)) {
523
+ if (isIdentifier && check !== check) {
524
+ this.createObjectAssign(source.i, key, serialized);
525
+ } else {
526
+ this.createArrayAssign(
527
+ source.i,
528
+ isIdentifier ? key : '"' + key + '"',
529
+ serialized,
530
+ );
531
+ }
532
+ } else {
533
+ const parentAssignment = this.assignments;
534
+ this.assignments = mainAssignments;
535
+ if (isIdentifier) {
536
+ this.createObjectAssign(source.i, key, serialized);
537
+ } else {
538
+ this.createArrayAssign(
539
+ source.i,
540
+ isIdentifier ? key : '"' + key + '"',
541
+ serialized,
542
+ );
543
+ }
544
+ this.assignments = parentAssignment;
545
+ }
546
+ }
547
+
529
548
  protected serializeAssignment(
530
549
  source: SerovalNodeWithProperties,
531
550
  mainAssignments: Assignment[],
@@ -533,28 +552,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
533
552
  value: SerovalNode,
534
553
  ): void {
535
554
  if (typeof key === 'string') {
536
- const serialized = this.serialize(value);
537
- const check = Number(key);
538
- // Test if key is a valid number or JS identifier
539
- // so that we don't have to serialize the key and wrap with brackets
540
- const isIdentifier = check >= 0 || isValidIdentifier(key);
541
- if (this.isIndexedValueInStack(value)) {
542
- // eslint-disable-next-line no-self-compare
543
- if (isIdentifier && check !== check) {
544
- this.createObjectAssign(source.i, key, serialized);
545
- } else {
546
- this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
547
- }
548
- } else {
549
- const parentAssignment = this.assignments;
550
- this.assignments = mainAssignments;
551
- if (isIdentifier) {
552
- this.createObjectAssign(source.i, key, serialized);
553
- } else {
554
- this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
555
- }
556
- this.assignments = parentAssignment;
557
- }
555
+ this.serializeStringKeyAssignment(source, mainAssignments, key, value);
558
556
  } else {
559
557
  const parent = this.stack;
560
558
  this.stack = [];
@@ -562,11 +560,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
562
560
  this.stack = parent;
563
561
  const parentAssignment = this.assignments;
564
562
  this.assignments = mainAssignments;
565
- this.createArrayAssign(
566
- source.i,
567
- this.serialize(key),
568
- serialized,
569
- );
563
+ this.createArrayAssign(source.i, this.serialize(key), serialized);
570
564
  this.assignments = parentAssignment;
571
565
  }
572
566
  }
@@ -577,10 +571,10 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
577
571
  ): string | undefined {
578
572
  const len = node.s;
579
573
  if (len) {
580
- this.stack.push(source.i);
581
574
  const mainAssignments: Assignment[] = [];
582
575
  const keys = node.k;
583
576
  const values = node.v;
577
+ this.stack.push(source.i);
584
578
  for (let i = 0; i < len; i++) {
585
579
  this.serializeAssignment(source, mainAssignments, keys[i], values[i]);
586
580
  }
@@ -601,47 +595,46 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
601
595
  this.markRef(node.i);
602
596
  const assignments = this.serializeAssignments(node, node.p);
603
597
  if (assignments) {
604
- return '(' + this.assignIndexedValue(node.i, init) + ',' + assignments + this.getRefParam(node.i) + ')';
598
+ return (
599
+ '(' +
600
+ this.assignIndexedValue(node.i, init) +
601
+ ',' +
602
+ assignments +
603
+ this.getRefParam(node.i) +
604
+ ')'
605
+ );
605
606
  }
606
607
  }
607
608
  }
608
609
  return this.assignIndexedValue(node.i, init);
609
610
  }
610
611
 
611
- protected serializeNullConstructor(
612
- node: SerovalNullConstructorNode,
613
- ): string {
612
+ protected serializeNullConstructor(node: SerovalNullConstructorNode): string {
614
613
  this.pushObjectFlag(node.o, node.i);
615
614
  return this.serializeDictionary(node, NULL_CONSTRUCTOR);
616
615
  }
617
616
 
618
- protected serializeDate(
619
- node: SerovalDateNode,
620
- ): string {
617
+ protected serializeDate(node: SerovalDateNode): string {
621
618
  return this.assignIndexedValue(node.i, 'new Date("' + node.s + '")');
622
619
  }
623
620
 
624
- protected serializeRegExp(
625
- node: SerovalRegExpNode,
626
- ): string {
621
+ protected serializeRegExp(node: SerovalRegExpNode): string {
627
622
  return this.assignIndexedValue(node.i, '/' + node.c + '/' + node.m);
628
623
  }
629
624
 
630
- protected serializeSetItem(
631
- id: number,
632
- item: SerovalNode,
633
- ): string {
625
+ protected serializeSetItem(id: number, item: SerovalNode): string {
634
626
  if (this.isIndexedValueInStack(item)) {
635
627
  this.markRef(id);
636
- this.createAddAssignment(id, this.getRefParam((item as SerovalIndexedValueNode).i));
628
+ this.createAddAssignment(
629
+ id,
630
+ this.getRefParam((item as SerovalIndexedValueNode).i),
631
+ );
637
632
  return '';
638
633
  }
639
634
  return this.serialize(item);
640
635
  }
641
636
 
642
- protected serializeSet(
643
- node: SerovalSetNode,
644
- ): string {
637
+ protected serializeSet(node: SerovalSetNode): string {
645
638
  let serialized = SET_CONSTRUCTOR;
646
639
  const size = node.l;
647
640
  const id = node.i;
@@ -685,12 +678,17 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
685
678
  // value is no longer part of the expression
686
679
  // tree and has been moved to the deferred
687
680
  // assignment
688
- if (val.t !== SerovalNodeType.IndexedValue && val.i != null && this.isMarked(val.i)) {
681
+ if (
682
+ val.t !== SerovalNodeType.IndexedValue &&
683
+ val.i != null &&
684
+ this.isMarked(val.i)
685
+ ) {
689
686
  // We use a trick here using sequence (or comma) expressions
690
687
  // basically we serialize the intended object in place WITHOUT
691
688
  // actually returning it, this is by returning a placeholder
692
689
  // value that we will remove sometime after.
693
- const serialized = '(' + this.serialize(val) + ',[' + sentinel + ',' + sentinel + '])';
690
+ const serialized =
691
+ '(' + this.serialize(val) + ',[' + sentinel + ',' + sentinel + '])';
694
692
  this.createSetAssignment(id, keyRef, this.getRefParam(val.i));
695
693
  this.createDeleteAssignment(id, sentinel);
696
694
  return serialized;
@@ -705,8 +703,13 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
705
703
  // Create ref for the Map instance
706
704
  const valueRef = this.getRefParam((val as SerovalIndexedValueNode).i);
707
705
  this.markRef(id);
708
- if (key.t !== SerovalNodeType.IndexedValue && key.i != null && this.isMarked(key.i)) {
709
- const serialized = '(' + this.serialize(key) + ',[' + sentinel + ',' + sentinel + '])';
706
+ if (
707
+ key.t !== SerovalNodeType.IndexedValue &&
708
+ key.i != null &&
709
+ this.isMarked(key.i)
710
+ ) {
711
+ const serialized =
712
+ '(' + this.serialize(key) + ',[' + sentinel + ',' + sentinel + '])';
710
713
  this.createSetAssignment(id, this.getRefParam(key.i), valueRef);
711
714
  this.createDeleteAssignment(id, sentinel);
712
715
  return serialized;
@@ -722,21 +725,19 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
722
725
  return '[' + this.serialize(key) + ',' + this.serialize(val) + ']';
723
726
  }
724
727
 
725
- protected serializeMap(
726
- node: SerovalMapNode,
727
- ): string {
728
+ protected serializeMap(node: SerovalMapNode): string {
728
729
  let serialized = MAP_CONSTRUCTOR;
729
730
  const size = node.e.s;
730
731
  const id = node.i;
731
732
  const sentinel = node.f;
732
- const sentinelID = this.getRefParam(sentinel.i);
733
+ const sentinelId = this.getRefParam(sentinel.i);
733
734
  if (size) {
734
735
  const keys = node.e.k;
735
736
  const vals = node.e.v;
736
737
  this.stack.push(id);
737
- let result = this.serializeMapEntry(id, keys[0], vals[0], sentinelID);
738
+ let result = this.serializeMapEntry(id, keys[0], vals[0], sentinelId);
738
739
  for (let i = 1, item = result; i < size; i++) {
739
- item = this.serializeMapEntry(id, keys[i], vals[i], sentinelID);
740
+ item = this.serializeMapEntry(id, keys[i], vals[i], sentinelId);
740
741
  result += (item && result && ',') + item;
741
742
  }
742
743
  this.stack.pop();
@@ -754,9 +755,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
754
755
  return this.assignIndexedValue(id, serialized);
755
756
  }
756
757
 
757
- protected serializeArrayBuffer(
758
- node: SerovalArrayBufferNode,
759
- ): string {
758
+ protected serializeArrayBuffer(node: SerovalArrayBufferNode): string {
760
759
  let result = 'new Uint8Array(';
761
760
  const buffer = node.s;
762
761
  const len = buffer.length;
@@ -775,201 +774,93 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
775
774
  ): string {
776
775
  return this.assignIndexedValue(
777
776
  node.i,
778
- 'new ' + node.c + '(' + this.serialize(node.f) + ',' + node.b + ',' + node.l + ')',
777
+ 'new ' +
778
+ node.c +
779
+ '(' +
780
+ this.serialize(node.f) +
781
+ ',' +
782
+ node.b +
783
+ ',' +
784
+ node.l +
785
+ ')',
779
786
  );
780
787
  }
781
788
 
782
- protected serializeDataView(
783
- node: SerovalDataViewNode,
784
- ): string {
789
+ protected serializeDataView(node: SerovalDataViewNode): string {
785
790
  return this.assignIndexedValue(
786
791
  node.i,
787
- 'new DataView(' + this.serialize(node.f) + ',' + node.b + ',' + node.l + ')',
792
+ 'new DataView(' +
793
+ this.serialize(node.f) +
794
+ ',' +
795
+ node.b +
796
+ ',' +
797
+ node.l +
798
+ ')',
788
799
  );
789
800
  }
790
801
 
791
- protected serializeAggregateError(
792
- node: SerovalAggregateErrorNode,
793
- ): string {
794
- // Serialize the required arguments
802
+ protected serializeAggregateError(node: SerovalAggregateErrorNode): string {
795
803
  const id = node.i;
796
- this.stack.push(id);
797
- const serialized = 'new AggregateError([],"' + node.m + '")';
798
- this.stack.pop();
799
804
  // `AggregateError` might've been extended
800
805
  // either through class or custom properties
801
806
  // Make sure to assign extra properties
802
- return this.serializeDictionary(node, serialized);
807
+ this.stack.push(id);
808
+ const serialized = this.serializeDictionary(
809
+ node,
810
+ 'new AggregateError([],"' + node.m + '")',
811
+ );
812
+ this.stack.pop();
813
+ return serialized;
803
814
  }
804
815
 
805
- protected serializeError(
806
- node: SerovalErrorNode,
807
- ): string {
808
- return this.serializeDictionary(node, 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")');
816
+ protected serializeError(node: SerovalErrorNode): string {
817
+ return this.serializeDictionary(
818
+ node,
819
+ 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")',
820
+ );
809
821
  }
810
822
 
811
- protected serializePromise(
812
- node: SerovalPromiseNode,
813
- ): string {
823
+ protected serializePromise(node: SerovalPromiseNode): string {
814
824
  let serialized: string;
815
825
  // Check if resolved value is a parent expression
816
826
  const fulfilled = node.f;
817
827
  const id = node.i;
818
- const constructor = node.s ? PROMISE_RESOLVE : PROMISE_REJECT;
828
+ const promiseConstructor = node.s ? PROMISE_RESOLVE : PROMISE_REJECT;
819
829
  if (this.isIndexedValueInStack(fulfilled)) {
820
830
  // A Promise trick, reference the value
821
831
  // inside the `then` expression so that
822
832
  // the Promise evaluates after the parent
823
833
  // has initialized
824
834
  const ref = this.getRefParam((fulfilled as SerovalIndexedValueNode).i);
825
- serialized = constructor + (
826
- node.s
835
+ serialized =
836
+ promiseConstructor +
837
+ (node.s
827
838
  ? '().then(' + this.createFunction([], ref) + ')'
828
- : '().catch(' + this.createEffectfulFunction([], 'throw ' + ref) + ')'
829
- );
839
+ : '().catch(' +
840
+ this.createEffectfulFunction([], 'throw ' + ref) +
841
+ ')');
830
842
  } else {
831
843
  this.stack.push(id);
832
844
  const result = this.serialize(fulfilled);
833
845
  this.stack.pop();
834
846
  // just inline the value/reference here
835
- serialized = constructor + '(' + result + ')';
847
+ serialized = promiseConstructor + '(' + result + ')';
836
848
  }
837
849
  return this.assignIndexedValue(id, serialized);
838
850
  }
839
851
 
840
- protected serializeWKSymbol(
841
- node: SerovalWKSymbolNode,
842
- ): string {
852
+ protected serializeWellKnownSymbol(node: SerovalWKSymbolNode): string {
843
853
  return this.assignIndexedValue(node.i, SYMBOL_STRING[node.s]);
844
854
  }
845
855
 
846
- protected serializeURL(
847
- node: SerovalURLNode,
848
- ): string {
849
- return this.assignIndexedValue(node.i, 'new URL("' + node.s + '")');
850
- }
851
-
852
- protected serializeURLSearchParams(
853
- node: SerovalURLSearchParamsNode,
854
- ): string {
855
- return this.assignIndexedValue(
856
- node.i,
857
- node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams',
858
- );
859
- }
860
-
861
- protected serializeBlob(
862
- node: SerovalBlobNode,
863
- ): string {
864
- return this.assignIndexedValue(
865
- node.i,
866
- 'new Blob([' + this.serialize(node.f) + '],{type:"' + node.c + '"})',
867
- );
868
- }
869
-
870
- protected serializeFile(
871
- node: SerovalFileNode,
872
- ): string {
873
- return this.assignIndexedValue(
874
- node.i,
875
- 'new File([' + this.serialize(node.f) + '],"' + node.m + '",{type:"' + node.c + '",lastModified:' + node.b + '})',
876
- );
877
- }
878
-
879
- protected serializeHeaders(
880
- node: SerovalHeadersNode,
881
- ): string {
882
- return this.assignIndexedValue(
883
- node.i,
884
- 'new Headers(' + this.serializeProperties(node, node.e) + ')',
885
- );
886
- }
887
-
888
- protected serializeFormDataEntry(id: number, key: string, value: SerovalNode): string {
889
- return this.getRefParam(id) + '.append("' + key + '",' + this.serialize(value) + ')';
890
- }
891
-
892
- protected serializeFormDataEntries(
893
- node: SerovalFormDataNode,
894
- size: number,
895
- ): string {
896
- const keys = node.e.k;
897
- const vals = node.e.v;
898
- const id = node.i;
899
- let result = this.serializeFormDataEntry(id, keys[0], vals[0]);
900
- for (let i = 1; i < size; i++) {
901
- result += ',' + this.serializeFormDataEntry(id, keys[i], vals[i]);
902
- }
903
- return result;
904
- }
905
-
906
- protected serializeFormData(
907
- node: SerovalFormDataNode,
908
- ): string {
909
- const size = node.e.s;
910
- const id = node.i;
911
- if (size) {
912
- this.markRef(id);
913
- }
914
- const result = this.assignIndexedValue(id, 'new FormData()');
915
- if (size) {
916
- const entries = this.serializeFormDataEntries(node, size);
917
- return '(' + result + ',' + (entries ? entries + ',' : '') + this.getRefParam(id) + ')';
918
- }
919
- return result;
920
- }
921
-
922
- protected serializeBoxed(
923
- node: SerovalBoxedNode,
924
- ): string {
925
- return this.assignIndexedValue(node.i, 'Object(' + this.serialize(node.f) + ')');
926
- }
927
-
928
- protected serializeRequest(
929
- node: SerovalRequestNode,
930
- ): string {
931
- return this.assignIndexedValue(node.i, 'new Request("' + node.s + '",' + this.serialize(node.f) + ')');
932
- }
933
-
934
- protected serializeResponse(
935
- node: SerovalResponseNode,
936
- ): string {
856
+ protected serializeBoxed(node: SerovalBoxedNode): string {
937
857
  return this.assignIndexedValue(
938
858
  node.i,
939
- 'new Response(' + this.serialize(node.a[0]) + ',' + this.serialize(node.a[1]) + ')',
859
+ 'Object(' + this.serialize(node.f) + ')',
940
860
  );
941
861
  }
942
862
 
943
- protected serializeEvent(
944
- node: SerovalEventNode,
945
- ): string {
946
- return this.assignIndexedValue(
947
- node.i,
948
- 'new Event("' + node.s + '",' + this.serialize(node.f) + ')',
949
- );
950
- }
951
-
952
- protected serializeCustomEvent(
953
- node: SerovalCustomEventNode,
954
- ): string {
955
- return this.assignIndexedValue(
956
- node.i,
957
- 'new CustomEvent("' + node.s + '",' + this.serialize(node.f) + ')',
958
- );
959
- }
960
-
961
- protected serializeDOMException(
962
- node: SerovalDOMExceptionNode,
963
- ): string {
964
- return this.assignIndexedValue(
965
- node.i,
966
- 'new DOMException("' + node.s + '","' + node.c + '")',
967
- );
968
- }
969
-
970
- protected serializePlugin(
971
- node: SerovalPluginNode,
972
- ): string {
863
+ protected serializePlugin(node: SerovalPluginNode): string {
973
864
  const currentPlugins = this.plugins;
974
865
  if (currentPlugins) {
975
866
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
@@ -988,77 +879,48 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
988
879
  }
989
880
 
990
881
  private getConstructor(node: SerovalNodeWithID): string {
991
- const constructor = this.serialize(node);
992
- return (constructor === this.getRefParam(node.i)) ? constructor : ('(' + constructor + ')');
882
+ const current = this.serialize(node);
883
+ return current === this.getRefParam(node.i) ? current : '(' + current + ')';
993
884
  }
994
885
 
995
886
  protected serializePromiseConstructor(
996
887
  node: SerovalPromiseConstructorNode,
997
888
  ): string {
998
- return this.assignIndexedValue(
999
- node.i,
1000
- this.getConstructor(node.f) + '()',
1001
- );
889
+ return this.assignIndexedValue(node.i, this.getConstructor(node.f) + '()');
1002
890
  }
1003
891
 
1004
- protected serializePromiseResolve(
1005
- node: SerovalPromiseResolveNode,
1006
- ): string {
1007
- return this.getConstructor(node.a[0]) + '(' + this.getRefParam(node.i) + ',' + this.serialize(node.a[1]) + ')';
1008
- }
1009
-
1010
- protected serializePromiseReject(
1011
- node: SerovalPromiseRejectNode,
1012
- ): string {
1013
- return this.getConstructor(node.a[0]) + '(' + this.getRefParam(node.i) + ',' + this.serialize(node.a[1]) + ')';
1014
- }
1015
-
1016
- protected serializeReadableStreamConstructor(
1017
- node: SerovalReadableStreamConstructorNode,
1018
- ): string {
1019
- return this.assignIndexedValue(
1020
- node.i,
1021
- this.getConstructor(node.f) + '()',
892
+ protected serializePromiseResolve(node: SerovalPromiseResolveNode): string {
893
+ return (
894
+ this.getConstructor(node.a[0]) +
895
+ '(' +
896
+ this.getRefParam(node.i) +
897
+ ',' +
898
+ this.serialize(node.a[1]) +
899
+ ')'
1022
900
  );
1023
901
  }
1024
902
 
1025
- protected serializeReadableStreamEnqueue(
1026
- node: SerovalReadableStreamEnqueueNode,
1027
- ): string {
1028
- return this.getConstructor(node.a[0]) + '(' + this.getRefParam(node.i) + ',' + this.serialize(node.a[1]) + ')';
1029
- }
1030
-
1031
- protected serializeReadableStreamError(
1032
- node: SerovalReadableStreamErrorNode,
1033
- ): string {
1034
- return this.getConstructor(node.a[0]) + '(' + this.getRefParam(node.i) + ',' + this.serialize(node.a[1]) + ')';
1035
- }
1036
-
1037
- protected serializeReadableStreamClose(
1038
- node: SerovalReadableStreamCloseNode,
1039
- ): string {
1040
- return this.getConstructor(node.f) + '(' + this.getRefParam(node.i) + ')';
903
+ protected serializePromiseReject(node: SerovalPromiseRejectNode): string {
904
+ return (
905
+ this.getConstructor(node.a[0]) +
906
+ '(' +
907
+ this.getRefParam(node.i) +
908
+ ',' +
909
+ this.serialize(node.a[1]) +
910
+ ')'
911
+ );
1041
912
  }
1042
913
 
1043
914
  private serializeSpecialReferenceValue(ref: SpecialReference): string {
1044
915
  switch (ref) {
1045
916
  case SpecialReference.MapSentinel:
1046
917
  return '[]';
1047
- case SpecialReference.ReadableStream:
1048
- return this.createFunction(
1049
- ['s'],
1050
- 'new ReadableStream({start:' + this.createFunction(
1051
- ['c'],
1052
- 'Promise.resolve().then(' + this.createEffectfulFunction(
1053
- ['i', 'v'],
1054
- 'for(i=0;i<s.d;i++)c.enqueue(s.v[i]);(s.t===-1)?c.close():c.error(s.v[i])',
1055
- ) + ')',
1056
- ) + '})',
1057
- );
1058
918
  case SpecialReference.PromiseConstructor:
1059
919
  return this.createFunction(
1060
920
  ['s', 'f', 'p'],
1061
- '((p=new Promise(' + this.createEffectfulFunction(['a', 'b'], 's=a,f=b') + ')).s=s,p.f=f,p)',
921
+ '((p=new Promise(' +
922
+ this.createEffectfulFunction(['a', 'b'], 's=a,f=b') +
923
+ ')).s=s,p.f=f,p)',
1062
924
  );
1063
925
  case SpecialReference.PromiseResolve:
1064
926
  return this.createEffectfulFunction(
@@ -1070,32 +932,50 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1070
932
  ['p', 'd'],
1071
933
  'p.f(d),p.status="failure",p.value=d;delete p.s;delete p.f',
1072
934
  );
1073
- case SpecialReference.ReadableStreamConstructor:
935
+ case SpecialReference.StreamConstructor:
1074
936
  return this.createFunction(
1075
- ['s', 'c'],
1076
- '((s=new ReadableStream({start:' + this.createEffectfulFunction(['x'], 'c=x') + '})).c=c,s)',
1077
- );
1078
- case SpecialReference.ReadableStreamEnqueue:
1079
- return this.createEffectfulFunction(
1080
- ['s', 'd'],
1081
- 's.c.enqueue(d)',
1082
- );
1083
- case SpecialReference.ReadableStreamError:
1084
- return this.createEffectfulFunction(
1085
- ['s', 'd'],
1086
- 's.c.error(d);delete s.c',
1087
- );
1088
- case SpecialReference.ReadableStreamClose:
1089
- return this.createEffectfulFunction(
1090
- ['s'],
1091
- 's.c.close();delete s.c',
937
+ ['b', 'a', 's', 'l', 'p', 'f', 'e', 'n'],
938
+ '(b=[],a=!0,s=!1,l=[],p=0,f=' +
939
+ this.createEffectfulFunction(
940
+ ['v', 'm', 'x'],
941
+ 'for(x=0;x<p;x++)l[x]&&l[x][m](v)',
942
+ ) +
943
+ ',n=' +
944
+ this.createEffectfulFunction(
945
+ ['o', 'x', 'z', 'c'],
946
+ 'for(x=0,z=b.length;x<z;x++)(c=b[x],x===z-1?o[s?"return":"throw"](c):o.next(c))',
947
+ ) +
948
+ ',e=' +
949
+ this.createFunction(
950
+ ['o', 't'],
951
+ '(a&&(l[t=p++]=o),n(o),' +
952
+ this.createEffectfulFunction([], 'a&&(l[t]=void 0)') +
953
+ ')',
954
+ ) +
955
+ ',{__SEROVAL_STREAM__:!0,on:' +
956
+ this.createFunction(['o'], 'e(o)') +
957
+ ',next:' +
958
+ this.createEffectfulFunction(['v'], 'a&&(b.push(v),f(v,"next"))') +
959
+ ',throw:' +
960
+ this.createEffectfulFunction(
961
+ ['v'],
962
+ 'a&&(b.push(v),f(v,"throw"),a=s=!1,l.length=0)',
963
+ ) +
964
+ ',return:' +
965
+ this.createEffectfulFunction(
966
+ ['v'],
967
+ 'a&&(b.push(v),f(v,"return"),a=!1,s=!0,l.length=0)',
968
+ ) +
969
+ '})',
1092
970
  );
1093
971
  default:
1094
972
  return '';
1095
973
  }
1096
974
  }
1097
975
 
1098
- protected serializeSpecialReference(node: SerovalSpecialReferenceNode): string {
976
+ protected serializeSpecialReference(
977
+ node: SerovalSpecialReferenceNode,
978
+ ): string {
1099
979
  return this.assignIndexedValue(
1100
980
  node.i,
1101
981
  this.serializeSpecialReferenceValue(node.s),
@@ -1103,84 +983,151 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1103
983
  }
1104
984
 
1105
985
  protected serializeIteratorFactory(node: SerovalIteratorFactoryNode): string {
1106
- return this.assignIndexedValue(
986
+ let result = '';
987
+ let initialized = false;
988
+ if (node.f.t !== SerovalNodeType.IndexedValue) {
989
+ this.markRef(node.f.i);
990
+ result = '(' + this.serialize(node.f) + ',';
991
+ initialized = true;
992
+ }
993
+ result += this.assignIndexedValue(
1107
994
  node.i,
1108
995
  this.createFunction(
1109
996
  ['s'],
1110
997
  this.createFunction(
1111
998
  ['i', 'c', 'd', 't'],
1112
- '(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
1113
- + 'next:' + this.createEffectfulFunction([], 'if(i>s.d)return{done:!0,value:void 0};c=i++,d=s.v[c];if(c===s.t)throw d;return{done:c===s.d,value:d}') + '})',
999
+ '(i=0,t={[' +
1000
+ this.getRefParam(node.f.i) +
1001
+ ']:' +
1002
+ this.createFunction([], 't') +
1003
+ ',next:' +
1004
+ this.createEffectfulFunction(
1005
+ [],
1006
+ 'if(i>s.d)return{done:!0,value:void 0};if(d=s.v[c=i++],c===s.t)throw d;return{done:c===s.d,value:d}',
1007
+ ) +
1008
+ '})',
1114
1009
  ),
1115
1010
  ),
1116
1011
  );
1012
+ if (initialized) {
1013
+ result += ')';
1014
+ }
1015
+ return result;
1117
1016
  }
1118
1017
 
1119
1018
  protected serializeIteratorFactoryInstance(
1120
1019
  node: SerovalIteratorFactoryInstanceNode,
1121
1020
  ): string {
1122
- return this.getConstructor(node.a[0]) + '(' + this.serialize(node.a[1]) + ')';
1123
- }
1124
-
1125
- private getStreamingAsyncIteratorFactory(node: SerovalAsyncIteratorFactoryNode): string {
1126
- return this.createFunction(
1127
- ['s'],
1128
- this.createFunction(
1129
- ['b', 't'],
1130
- '(b=s.tee(),s=b[0],b=b[1].getReader(),t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
1131
- + 'next:' + this.createFunction(
1132
- [],
1133
- 'b.read().then(' + this.createEffectfulFunction(
1134
- ['d'],
1135
- 'if(d.done)return{done:!0,value:void 0};d=d.value;if(d[0]===1)throw d[1];return{done:d[0]===2,value:d[1]}',
1136
- ) + ')',
1137
- ) + '})',
1138
- ),
1021
+ return (
1022
+ this.getConstructor(node.a[0]) + '(' + this.serialize(node.a[1]) + ')'
1139
1023
  );
1140
1024
  }
1141
1025
 
1142
- private getBlockingAsyncIteratorFactory(node: SerovalAsyncIteratorFactoryNode): string {
1143
- return this.createFunction(
1144
- ['s'],
1026
+ protected serializeAsyncIteratorFactory(
1027
+ node: SerovalAsyncIteratorFactoryNode,
1028
+ ): string {
1029
+ const promise = node.a[0];
1030
+ const symbol = node.a[1];
1031
+
1032
+ let result = '';
1033
+
1034
+ if (promise.t !== SerovalNodeType.IndexedValue) {
1035
+ this.markRef(promise.i);
1036
+ result += '(' + this.serialize(promise);
1037
+ }
1038
+ if (symbol.t !== SerovalNodeType.IndexedValue) {
1039
+ this.markRef(symbol.i);
1040
+ result += (result ? ',' : '(') + this.serialize(symbol);
1041
+ }
1042
+ if (result) {
1043
+ result += ',';
1044
+ }
1045
+
1046
+ const iterator = this.assignIndexedValue(
1047
+ node.i,
1145
1048
  this.createFunction(
1146
- ['i', 't'],
1147
- '(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
1148
- + 'next:' + this.createFunction(
1149
- [],
1150
- 'Promise.resolve().then(' + this.createEffectfulFunction(
1151
- ['c', 'd'],
1152
- 'if(i>s.d)return{done:!0,value:void 0};c=i++,d=s.v[c];if(c===s.t)throw d;return{done:c===s.d,value:d}',
1153
- ) + ')',
1154
- ) + '})',
1049
+ ['s'],
1050
+ this.createFunction(
1051
+ ['b', 'c', 'p', 'd', 'e', 't', 'f'],
1052
+ '(b=[],c=0,p=[],d=-1,e=!1,f=' +
1053
+ this.createEffectfulFunction(
1054
+ ['i', 'l'],
1055
+ 'for(i=0,l=p.length;i<l;i++)p[i].s({done:!0,value:void 0})',
1056
+ ) +
1057
+ ',s.on({next:' +
1058
+ this.createEffectfulFunction(
1059
+ ['v', 't'],
1060
+ 'if(t=p.shift())t.s({done:!1,value:v});b.push(v)',
1061
+ ) +
1062
+ ',throw:' +
1063
+ this.createEffectfulFunction(
1064
+ ['v', 't'],
1065
+ 'if(t=p.shift())t.f(v);f(),d=b.length,e=!0,b.push(v)',
1066
+ ) +
1067
+ ',return:' +
1068
+ this.createEffectfulFunction(
1069
+ ['v', 't'],
1070
+ 'if(t=p.shift())t.s({done:!0,value:v});f(),d=b.length,b.push(v)',
1071
+ ) +
1072
+ '}),t={[' +
1073
+ this.getRefParam(symbol.i) +
1074
+ ']:' +
1075
+ this.createFunction([], 't') +
1076
+ ',next:' +
1077
+ this.createEffectfulFunction(
1078
+ ['i', 't', 'v'],
1079
+ 'if(d===-1){return((i=c++)>=b.length)?(p.push(t=' +
1080
+ this.getRefParam(promise.i) +
1081
+ '()),t):{done:!0,value:b[i]}}if(c>d)return{done:!0,value:void 0};if(v=b[i=c++],i!==d)return{done:!1,value:v};if(e)throw v;return{done:!0,value:v}',
1082
+ ) +
1083
+ '})',
1084
+ ),
1155
1085
  ),
1156
1086
  );
1157
- }
1158
1087
 
1159
- protected serializeAsyncIteratorFactory(node: SerovalAsyncIteratorFactoryNode): string {
1160
- return this.assignIndexedValue(
1161
- node.i,
1162
- node.s
1163
- ? this.getStreamingAsyncIteratorFactory(node)
1164
- : this.getBlockingAsyncIteratorFactory(node),
1165
- );
1088
+ if (result) {
1089
+ return result + iterator + ')';
1090
+ }
1091
+
1092
+ return iterator;
1166
1093
  }
1167
1094
 
1168
1095
  protected serializeAsyncIteratorFactoryInstance(
1169
1096
  node: SerovalAsyncIteratorFactoryInstanceNode,
1170
1097
  ): string {
1171
- return this.getConstructor(node.a[0]) + '(' + this.serialize(node.a[1]) + ')';
1098
+ return (
1099
+ this.getConstructor(node.a[0]) + '(' + this.serialize(node.a[1]) + ')'
1100
+ );
1172
1101
  }
1173
1102
 
1174
- protected serializeReadableStream(
1175
- node: SerovalReadableStreamNode,
1103
+ protected serializeStreamConstructor(
1104
+ node: SerovalStreamConstructorNode,
1176
1105
  ): string {
1177
- this.stack.push(node.i);
1178
- const result = this.getConstructor(node.a[0]) + '(' + this.serialize(node.a[1]) + ')';
1179
- this.stack.pop();
1180
- return this.assignIndexedValue(
1106
+ const result = this.assignIndexedValue(
1181
1107
  node.i,
1182
- result,
1108
+ this.getConstructor(node.f) + '()',
1183
1109
  );
1110
+ const len = node.a.length;
1111
+ if (len) {
1112
+ let values = this.serialize(node.a[0]);
1113
+ for (let i = 1; i < len; i++) {
1114
+ values += ',' + this.serialize(node.a[i]);
1115
+ }
1116
+ return '(' + result + ',' + values + ',' + this.getRefParam(node.i) + ')';
1117
+ }
1118
+ return result;
1119
+ }
1120
+
1121
+ protected serializeStreamNext(node: SerovalStreamNextNode): string {
1122
+ return this.getRefParam(node.i) + '.next(' + this.serialize(node.f) + ')';
1123
+ }
1124
+
1125
+ protected serializeStreamThrow(node: SerovalStreamThrowNode): string {
1126
+ return this.getRefParam(node.i) + '.throw(' + this.serialize(node.f) + ')';
1127
+ }
1128
+
1129
+ protected serializeStreamReturn(node: SerovalStreamReturnNode): string {
1130
+ return this.getRefParam(node.i) + '.return(' + this.serialize(node.f) + ')';
1184
1131
  }
1185
1132
 
1186
1133
  serialize(node: SerovalNode): string {
@@ -1225,19 +1172,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1225
1172
  case SerovalNodeType.Promise:
1226
1173
  return this.serializePromise(node);
1227
1174
  case SerovalNodeType.WKSymbol:
1228
- return this.serializeWKSymbol(node);
1229
- case SerovalNodeType.URL:
1230
- return this.serializeURL(node);
1231
- case SerovalNodeType.URLSearchParams:
1232
- return this.serializeURLSearchParams(node);
1233
- case SerovalNodeType.Blob:
1234
- return this.serializeBlob(node);
1235
- case SerovalNodeType.File:
1236
- return this.serializeFile(node);
1237
- case SerovalNodeType.Headers:
1238
- return this.serializeHeaders(node);
1239
- case SerovalNodeType.FormData:
1240
- return this.serializeFormData(node);
1175
+ return this.serializeWellKnownSymbol(node);
1241
1176
  case SerovalNodeType.Boxed:
1242
1177
  return this.serializeBoxed(node);
1243
1178
  case SerovalNodeType.PromiseConstructor:
@@ -1246,24 +1181,6 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1246
1181
  return this.serializePromiseResolve(node);
1247
1182
  case SerovalNodeType.PromiseReject:
1248
1183
  return this.serializePromiseReject(node);
1249
- case SerovalNodeType.ReadableStreamConstructor:
1250
- return this.serializeReadableStreamConstructor(node);
1251
- case SerovalNodeType.ReadableStreamEnqueue:
1252
- return this.serializeReadableStreamEnqueue(node);
1253
- case SerovalNodeType.ReadableStreamError:
1254
- return this.serializeReadableStreamError(node);
1255
- case SerovalNodeType.ReadableStreamClose:
1256
- return this.serializeReadableStreamClose(node);
1257
- case SerovalNodeType.Request:
1258
- return this.serializeRequest(node);
1259
- case SerovalNodeType.Response:
1260
- return this.serializeResponse(node);
1261
- case SerovalNodeType.Event:
1262
- return this.serializeEvent(node);
1263
- case SerovalNodeType.CustomEvent:
1264
- return this.serializeCustomEvent(node);
1265
- case SerovalNodeType.DOMException:
1266
- return this.serializeDOMException(node);
1267
1184
  case SerovalNodeType.Plugin:
1268
1185
  return this.serializePlugin(node);
1269
1186
  case SerovalNodeType.SpecialReference:
@@ -1276,8 +1193,14 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1276
1193
  return this.serializeAsyncIteratorFactory(node);
1277
1194
  case SerovalNodeType.AsyncIteratorFactoryInstance:
1278
1195
  return this.serializeAsyncIteratorFactoryInstance(node);
1279
- case SerovalNodeType.ReadableStream:
1280
- return this.serializeReadableStream(node);
1196
+ case SerovalNodeType.StreamConstructor:
1197
+ return this.serializeStreamConstructor(node);
1198
+ case SerovalNodeType.StreamNext:
1199
+ return this.serializeStreamNext(node);
1200
+ case SerovalNodeType.StreamThrow:
1201
+ return this.serializeStreamThrow(node);
1202
+ case SerovalNodeType.StreamReturn:
1203
+ return this.serializeStreamReturn(node);
1281
1204
  default:
1282
1205
  throw new Error('invariant');
1283
1206
  }