seroval 0.12.4 → 0.13.1

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 (138) hide show
  1. package/README.md +17 -15
  2. package/dist/cjs/development/index.cjs +1432 -959
  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 +1432 -959
  6. package/dist/esm/development/index.mjs.map +3 -3
  7. package/dist/esm/production/index.mjs +3 -3
  8. package/dist/types/core/base-primitives.d.ts +12 -1
  9. package/dist/types/core/base-primitives.d.ts.map +1 -1
  10. package/dist/types/core/compat.d.ts +0 -2
  11. package/dist/types/core/compat.d.ts.map +1 -1
  12. package/dist/types/core/constants.d.ts +8 -2
  13. package/dist/types/core/constants.d.ts.map +1 -1
  14. package/dist/types/core/{tree/deserialize.d.ts → context/deserializer.d.ts} +19 -13
  15. package/dist/types/core/context/deserializer.d.ts.map +1 -0
  16. package/dist/types/core/{base → context/parser}/async.d.ts +6 -5
  17. package/dist/types/core/context/parser/async.d.ts.map +1 -0
  18. package/dist/types/core/{base → context/parser}/stream.d.ts +2 -1
  19. package/dist/types/core/context/parser/stream.d.ts.map +1 -0
  20. package/dist/types/core/{base → context/parser}/sync.d.ts +7 -9
  21. package/dist/types/core/context/parser/sync.d.ts.map +1 -0
  22. package/dist/types/core/context/parser.d.ts +27 -0
  23. package/dist/types/core/context/parser.d.ts.map +1 -0
  24. package/dist/types/core/{serializer-context.old.d.ts → context/serializer.d.ts} +21 -22
  25. package/dist/types/core/context/serializer.d.ts.map +1 -0
  26. package/dist/types/core/cross/async.d.ts +2 -2
  27. package/dist/types/core/cross/async.d.ts.map +1 -1
  28. package/dist/types/core/cross/deserializer.d.ts +9 -0
  29. package/dist/types/core/cross/deserializer.d.ts.map +1 -0
  30. package/dist/types/core/cross/index.d.ts +11 -1
  31. package/dist/types/core/cross/index.d.ts.map +1 -1
  32. package/dist/types/core/cross/parser.d.ts +6 -0
  33. package/dist/types/core/cross/parser.d.ts.map +1 -0
  34. package/dist/types/core/cross/{serialize.d.ts → serializer.d.ts} +6 -5
  35. package/dist/types/core/cross/serializer.d.ts.map +1 -0
  36. package/dist/types/core/cross/stream.d.ts +2 -2
  37. package/dist/types/core/cross/stream.d.ts.map +1 -1
  38. package/dist/types/core/cross/sync.d.ts +2 -2
  39. package/dist/types/core/cross/sync.d.ts.map +1 -1
  40. package/dist/types/core/keys.d.ts +3 -1
  41. package/dist/types/core/keys.d.ts.map +1 -1
  42. package/dist/types/core/plugin.d.ts +6 -7
  43. package/dist/types/core/plugin.d.ts.map +1 -1
  44. package/dist/types/core/special-reference.d.ts +6 -0
  45. package/dist/types/core/special-reference.d.ts.map +1 -0
  46. package/dist/types/core/tree/async.d.ts +2 -2
  47. package/dist/types/core/tree/async.d.ts.map +1 -1
  48. package/dist/types/core/tree/deserializer.d.ts +13 -0
  49. package/dist/types/core/tree/deserializer.d.ts.map +1 -0
  50. package/dist/types/core/tree/{serialize.d.ts → serializer.d.ts} +4 -4
  51. package/dist/types/core/tree/serializer.d.ts.map +1 -0
  52. package/dist/types/core/tree/sync.d.ts +2 -2
  53. package/dist/types/core/tree/sync.d.ts.map +1 -1
  54. package/dist/types/core/types.d.ts +47 -6
  55. package/dist/types/core/types.d.ts.map +1 -1
  56. package/dist/types/core/utils/assert.d.ts.map +1 -0
  57. package/dist/types/core/utils/constructors.d.ts.map +1 -0
  58. package/dist/types/core/utils/deferred.d.ts +14 -0
  59. package/dist/types/core/utils/deferred.d.ts.map +1 -0
  60. package/dist/types/core/utils/error.d.ts +5 -0
  61. package/dist/types/core/utils/error.d.ts.map +1 -0
  62. package/dist/types/core/utils/get-identifier.d.ts.map +1 -0
  63. package/dist/types/core/utils/get-object-flag.d.ts +3 -0
  64. package/dist/types/core/utils/get-object-flag.d.ts.map +1 -0
  65. package/dist/types/core/utils/is-valid-identifier.d.ts +2 -0
  66. package/dist/types/core/utils/is-valid-identifier.d.ts.map +1 -0
  67. package/dist/types/core/utils/iterator-to-sequence.d.ts +20 -0
  68. package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -0
  69. package/dist/types/core/utils/promise-to-result.d.ts.map +1 -0
  70. package/dist/types/core/utils/typed-array.d.ts +4 -0
  71. package/dist/types/core/utils/typed-array.d.ts.map +1 -0
  72. package/dist/types/core/web-api.d.ts +4 -1
  73. package/dist/types/core/web-api.d.ts.map +1 -1
  74. package/package.json +3 -3
  75. package/src/core/base-primitives.ts +229 -1
  76. package/src/core/compat.ts +0 -2
  77. package/src/core/constants.ts +7 -2
  78. package/src/core/{tree/deserialize.ts → context/deserializer.ts} +159 -66
  79. package/src/core/{base → context/parser}/async.ts +181 -309
  80. package/src/core/{base → context/parser}/stream.ts +89 -14
  81. package/src/core/{base → context/parser}/sync.ts +120 -281
  82. package/src/core/context/parser.ts +259 -0
  83. package/src/core/{serializer-context.old.ts → context/serializer.ts} +241 -166
  84. package/src/core/cross/async.ts +2 -2
  85. package/src/core/cross/deserializer.ts +19 -0
  86. package/src/core/cross/index.ts +68 -47
  87. package/src/core/cross/parser.ts +7 -0
  88. package/src/core/cross/{serialize.ts → serializer.ts} +31 -12
  89. package/src/core/cross/stream.ts +2 -2
  90. package/src/core/cross/sync.ts +2 -2
  91. package/src/core/is-serializable.new.ts +1 -1
  92. package/src/core/keys.ts +8 -2
  93. package/src/core/plugin.ts +7 -7
  94. package/src/core/reference.ts +1 -1
  95. package/src/core/special-reference.ts +9 -0
  96. package/src/core/tree/async.ts +2 -2
  97. package/src/core/tree/deserializer.ts +31 -0
  98. package/src/core/tree/index.ts +2 -2
  99. package/src/core/tree/{serialize.ts → serializer.ts} +5 -16
  100. package/src/core/tree/sync.ts +2 -2
  101. package/src/core/types.ts +60 -7
  102. package/src/core/utils/deferred.ts +49 -0
  103. package/src/core/{shared.ts → utils/error.ts} +3 -60
  104. package/src/core/utils/get-object-flag.ts +14 -0
  105. package/src/core/utils/is-valid-identifier.ts +11 -0
  106. package/src/core/utils/iterator-to-sequence.ts +238 -0
  107. package/src/core/utils/typed-array.ts +30 -0
  108. package/src/core/web-api.ts +75 -1
  109. package/src/example.ts +0 -3
  110. package/dist/types/core/assert.d.ts.map +0 -1
  111. package/dist/types/core/base/async.d.ts.map +0 -1
  112. package/dist/types/core/base/stream.d.ts.map +0 -1
  113. package/dist/types/core/base/sync.d.ts.map +0 -1
  114. package/dist/types/core/constructors.d.ts.map +0 -1
  115. package/dist/types/core/cross/cross-parser.d.ts +0 -8
  116. package/dist/types/core/cross/cross-parser.d.ts.map +0 -1
  117. package/dist/types/core/cross/serialize.d.ts.map +0 -1
  118. package/dist/types/core/get-identifier.d.ts.map +0 -1
  119. package/dist/types/core/parser-context.d.ts +0 -23
  120. package/dist/types/core/parser-context.d.ts.map +0 -1
  121. package/dist/types/core/promise-to-result.d.ts.map +0 -1
  122. package/dist/types/core/serializer-context.old.d.ts.map +0 -1
  123. package/dist/types/core/shared.d.ts +0 -10
  124. package/dist/types/core/shared.d.ts.map +0 -1
  125. package/dist/types/core/tree/deserialize.d.ts.map +0 -1
  126. package/dist/types/core/tree/serialize.d.ts.map +0 -1
  127. package/src/core/cross/cross-parser.ts +0 -9
  128. package/src/core/parser-context.ts +0 -131
  129. package/src/core/serializer-context.new.ts +0 -1168
  130. package/src/core/tree/parser.ts +0 -45
  131. /package/dist/types/core/{assert.d.ts → utils/assert.d.ts} +0 -0
  132. /package/dist/types/core/{constructors.d.ts → utils/constructors.d.ts} +0 -0
  133. /package/dist/types/core/{get-identifier.d.ts → utils/get-identifier.d.ts} +0 -0
  134. /package/dist/types/core/{promise-to-result.d.ts → utils/promise-to-result.d.ts} +0 -0
  135. /package/src/core/{assert.ts → utils/assert.ts} +0 -0
  136. /package/src/core/{constructors.ts → utils/constructors.ts} +0 -0
  137. /package/src/core/{get-identifier.ts → utils/get-identifier.ts} +0 -0
  138. /package/src/core/{promise-to-result.ts → utils/promise-to-result.ts} +0 -0
@@ -1,14 +1,13 @@
1
- import { Feature } from './compat';
1
+ import { Feature } from '../compat';
2
2
  import {
3
3
  CONSTANT_STRING,
4
4
  ERROR_CONSTRUCTOR_STRING,
5
5
  SYMBOL_STRING,
6
6
  SerovalNodeType,
7
7
  SerovalObjectFlags,
8
- } from './constants';
9
- import { REFERENCES_KEY } from './keys';
10
- import type { Plugin, PluginAccessOptions, SerovalMode } from './plugin';
11
- import { isValidIdentifier } from './shared';
8
+ } from '../constants';
9
+ import { REFERENCES_KEY } from '../keys';
10
+ import type { Plugin, PluginAccessOptions, SerovalMode } from '../plugin';
12
11
  import type {
13
12
  SerovalArrayNode,
14
13
  SerovalIndexedValueNode,
@@ -50,10 +49,15 @@ import type {
50
49
  SerovalReadableStreamEnqueueNode,
51
50
  SerovalReadableStreamErrorNode,
52
51
  SerovalReadableStreamCloseNode,
53
- } from './types';
54
- import {
55
- SerovalObjectRecordSpecialKey,
56
- } from './types';
52
+ SerovalMapSentinelNode,
53
+ SerovalIteratorFactoryInstanceNode,
54
+ SerovalIteratorFactoryNode,
55
+ SerovalAsyncIteratorFactoryInstanceNode,
56
+ SerovalAsyncIteratorFactoryNode,
57
+ SerovalReadableStreamNode,
58
+ SerovalReadableStreamFactoryNode,
59
+ } from '../types';
60
+ import { isValidIdentifier } from '../utils/is-valid-identifier';
57
61
 
58
62
  interface IndexAssignment {
59
63
  t: 'index';
@@ -180,16 +184,6 @@ const MAP_CONSTRUCTOR = 'new Map';
180
184
  const PROMISE_RESOLVE = 'Promise.resolve';
181
185
  const PROMISE_REJECT = 'Promise.reject';
182
186
 
183
- const SYMBOL_ITERATOR = 'Symbol.iterator';
184
-
185
- const enum SpecialReference {
186
- Sentinel = 0,
187
- }
188
-
189
- const SPECIAL_REFERENCE_VALUE: Record<SpecialReference, string> = {
190
- [SpecialReference.Sentinel]: '[]',
191
- };
192
-
193
187
  const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> = {
194
188
  [SerovalObjectFlags.Frozen]: 'Object.freeze',
195
189
  [SerovalObjectFlags.Sealed]: 'Object.seal',
@@ -197,6 +191,13 @@ const OBJECT_FLAG_CONSTRUCTOR: Record<SerovalObjectFlags, string | undefined> =
197
191
  [SerovalObjectFlags.None]: undefined,
198
192
  };
199
193
 
194
+ type SerovalNodeWithProperties =
195
+ | SerovalObjectNode
196
+ | SerovalNullConstructorNode
197
+ | SerovalAggregateErrorNode
198
+ | SerovalErrorNode
199
+ | SerovalHeadersNode;
200
+
200
201
  export interface BaseSerializerContextOptions extends PluginAccessOptions {
201
202
  features: number;
202
203
  markedRefs: number[] | Set<number>;
@@ -242,6 +243,32 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
242
243
 
243
244
  abstract readonly mode: SerovalMode;
244
245
 
246
+ protected createFunction(
247
+ parameters: string[],
248
+ body: string,
249
+ ): string {
250
+ if (this.features & Feature.ArrowFunction) {
251
+ const joined = parameters.length === 1
252
+ ? parameters[0]
253
+ : '(' + parameters.join(',') + ')';
254
+ return joined + '=>' + body;
255
+ }
256
+ return 'function(' + parameters.join(',') + '){return ' + body + '}';
257
+ }
258
+
259
+ protected createEffectfulFunction(
260
+ parameters: string[],
261
+ body: string,
262
+ ): string {
263
+ if (this.features & Feature.ArrowFunction) {
264
+ const joined = parameters.length === 1
265
+ ? parameters[0]
266
+ : '(' + parameters.join(',') + ')';
267
+ return joined + '=>{' + body + '}';
268
+ }
269
+ return 'function(' + parameters.join(',') + '){' + body + '}';
270
+ }
271
+
245
272
  /**
246
273
  * A tiny function that tells if a reference
247
274
  * is to be accessed. This is a requirement for
@@ -263,21 +290,6 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
263
290
  */
264
291
  abstract getRefParam(id: number | string): string;
265
292
 
266
- private specials = new Set<SpecialReference>();
267
-
268
- /**
269
- * Generates special references that isn't provided by the user
270
- * but by the script.
271
- */
272
- protected getSpecialReference(ref: SpecialReference): string {
273
- const param = this.getRefParam('_' + ref);
274
- if (this.specials.has(ref)) {
275
- return param;
276
- }
277
- this.specials.add(ref);
278
- return param + '=' + SPECIAL_REFERENCE_VALUE[ref];
279
- }
280
-
281
293
  protected pushObjectFlag(flag: SerovalObjectFlags, id: number): void {
282
294
  if (flag !== SerovalObjectFlags.None) {
283
295
  this.markRef(id);
@@ -406,30 +418,6 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
406
418
  return this.assignIndexedValue(node.i, REFERENCES_KEY + '.get("' + node.s + '")');
407
419
  }
408
420
 
409
- protected getIterableAccess(): string {
410
- return this.features & Feature.ArrayPrototypeValues
411
- ? '.values()'
412
- : '[' + SYMBOL_ITERATOR + ']()';
413
- }
414
-
415
- protected serializeIterable(
416
- node: SerovalNode,
417
- ): string {
418
- const key = '[' + SYMBOL_ITERATOR + ']';
419
- const parent = this.stack;
420
- this.stack = [];
421
- let serialized = this.serialize(node) + this.getIterableAccess();
422
- this.stack = parent;
423
- if (this.features & Feature.ArrowFunction) {
424
- serialized = ':()=>' + serialized;
425
- } else if (this.features & Feature.MethodShorthand) {
426
- serialized = '(){return ' + serialized + '}';
427
- } else {
428
- serialized = ':function(){return ' + serialized + '}';
429
- }
430
- return key + serialized;
431
- }
432
-
433
421
  protected serializeArrayItem(
434
422
  id: number,
435
423
  item: SerovalNode | undefined,
@@ -473,50 +461,43 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
473
461
  }
474
462
 
475
463
  protected serializeProperty(
476
- id: number,
464
+ source: SerovalNodeWithProperties,
477
465
  key: SerovalObjectRecordKey,
478
466
  val: SerovalNode,
479
467
  ): string {
480
- // Only reason this is a switch is so that
481
- // in the future, maybe other Symbols are going
482
- // to be introduced and/or has merit to be added
483
- // E.g. Symbol.asyncIterator
484
- switch (key) {
485
- case SerovalObjectRecordSpecialKey.SymbolIterator:
486
- return this.serializeIterable(val);
487
- default: {
488
- const check = Number(key);
489
- // Test if key is a valid number or JS identifier
490
- // so that we don't have to serialize the key and wrap with brackets
491
- const isIdentifier = check >= 0 || isValidIdentifier(key);
492
- if (this.isIndexedValueInStack(val)) {
493
- const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
494
- this.markRef(id);
495
- // eslint-disable-next-line no-self-compare
496
- if (isIdentifier && check !== check) {
497
- this.createObjectAssign(id, key, refParam);
498
- } else {
499
- this.createArrayAssign(id, isIdentifier ? key : ('"' + key + '"'), refParam);
500
- }
501
- return '';
468
+ if (typeof key === 'string') {
469
+ const check = Number(key);
470
+ // Test if key is a valid number or JS identifier
471
+ // so that we don't have to serialize the key and wrap with brackets
472
+ const isIdentifier = check >= 0 || isValidIdentifier(key);
473
+ if (this.isIndexedValueInStack(val)) {
474
+ const refParam = this.getRefParam((val as SerovalIndexedValueNode).i);
475
+ this.markRef(source.i);
476
+ // eslint-disable-next-line no-self-compare
477
+ if (isIdentifier && check !== check) {
478
+ this.createObjectAssign(source.i, key, refParam);
479
+ } else {
480
+ this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), refParam);
502
481
  }
503
- return (isIdentifier ? key : ('"' + key + '"')) + ':' + this.serialize(val);
482
+ return '';
504
483
  }
484
+ return (isIdentifier ? key : ('"' + key + '"')) + ':' + this.serialize(val);
505
485
  }
486
+ return '[' + this.serialize(key) + ']:' + this.serialize(val);
506
487
  }
507
488
 
508
489
  protected serializeProperties(
509
- sourceID: number,
510
- node: SerovalObjectRecordNode,
490
+ source: SerovalNodeWithProperties,
491
+ record: SerovalObjectRecordNode,
511
492
  ): string {
512
- const len = node.s;
493
+ const len = record.s;
513
494
  if (len) {
514
- this.stack.push(sourceID);
515
- const keys = node.k;
516
- const values = node.v;
517
- let result = this.serializeProperty(sourceID, keys[0], values[0]);
495
+ this.stack.push(source.i);
496
+ const keys = record.k;
497
+ const values = record.v;
498
+ let result = this.serializeProperty(source, keys[0], values[0]);
518
499
  for (let i = 1, item = result; i < len; i++) {
519
- item = this.serializeProperty(sourceID, keys[i], values[i]);
500
+ item = this.serializeProperty(source, keys[i], values[i]);
520
501
  result += (item && result && ',') + item;
521
502
  }
522
503
  this.stack.pop();
@@ -529,15 +510,15 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
529
510
  node: SerovalObjectNode,
530
511
  ): string {
531
512
  this.pushObjectFlag(node.o, node.i);
532
- return this.assignIndexedValue(node.i, this.serializeProperties(node.i, node.p));
513
+ return this.assignIndexedValue(node.i, this.serializeProperties(node, node.p));
533
514
  }
534
515
 
535
516
  protected serializeWithObjectAssign(
517
+ source: SerovalNodeWithProperties,
536
518
  value: SerovalObjectRecordNode,
537
- id: number,
538
519
  serialized: string,
539
520
  ): string {
540
- const fields = this.serializeProperties(id, value);
521
+ const fields = this.serializeProperties(source, value);
541
522
  if (fields !== '{}') {
542
523
  return 'Object.assign(' + serialized + ',' + fields + ')';
543
524
  }
@@ -545,68 +526,62 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
545
526
  }
546
527
 
547
528
  protected serializeAssignment(
548
- sourceID: number,
529
+ source: SerovalNodeWithProperties,
549
530
  mainAssignments: Assignment[],
550
531
  key: SerovalObjectRecordKey,
551
532
  value: SerovalNode,
552
533
  ): void {
553
- switch (key) {
554
- case SerovalObjectRecordSpecialKey.SymbolIterator: {
555
- const parent = this.stack;
556
- this.stack = [];
557
- const serialized = this.serialize(value) + this.getIterableAccess();
558
- this.stack = parent;
534
+ if (typeof key === 'string') {
535
+ const serialized = this.serialize(value);
536
+ const check = Number(key);
537
+ // Test if key is a valid number or JS identifier
538
+ // so that we don't have to serialize the key and wrap with brackets
539
+ const isIdentifier = check >= 0 || isValidIdentifier(key);
540
+ if (this.isIndexedValueInStack(value)) {
541
+ // eslint-disable-next-line no-self-compare
542
+ if (isIdentifier && check !== check) {
543
+ this.createObjectAssign(source.i, key, serialized);
544
+ } else {
545
+ this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
546
+ }
547
+ } else {
559
548
  const parentAssignment = this.assignments;
560
549
  this.assignments = mainAssignments;
561
- this.createArrayAssign(
562
- sourceID,
563
- this.getSpecialReference(SpecialReference.Sentinel),
564
- this.features & Feature.ArrowFunction
565
- ? '()=>' + serialized
566
- : 'function(){return ' + serialized + '}',
567
- );
568
- this.assignments = parentAssignment;
569
- }
570
- break;
571
- default: {
572
- const serialized = this.serialize(value);
573
- const check = Number(key);
574
- // Test if key is a valid number or JS identifier
575
- // so that we don't have to serialize the key and wrap with brackets
576
- const isIdentifier = check >= 0 || isValidIdentifier(key);
577
- if (this.isIndexedValueInStack(value)) {
578
- // eslint-disable-next-line no-self-compare
579
- if (isIdentifier && check !== check) {
580
- this.createObjectAssign(sourceID, key, serialized);
581
- } else {
582
- this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
583
- }
550
+ if (isIdentifier) {
551
+ this.createObjectAssign(source.i, key, serialized);
584
552
  } else {
585
- const parentAssignment = this.assignments;
586
- this.assignments = mainAssignments;
587
- if (isIdentifier) {
588
- this.createObjectAssign(sourceID, key, serialized);
589
- } else {
590
- this.createArrayAssign(sourceID, isIdentifier ? key : ('"' + key + '"'), serialized);
591
- }
592
- this.assignments = parentAssignment;
553
+ this.createArrayAssign(source.i, isIdentifier ? key : ('"' + key + '"'), serialized);
593
554
  }
555
+ this.assignments = parentAssignment;
594
556
  }
557
+ } else {
558
+ const parent = this.stack;
559
+ this.stack = [];
560
+ const serialized = this.serialize(value);
561
+ this.stack = parent;
562
+ const parentAssignment = this.assignments;
563
+ this.assignments = mainAssignments;
564
+ this.createArrayAssign(
565
+ source.i,
566
+ this.serialize(key),
567
+ serialized,
568
+ );
569
+ this.assignments = parentAssignment;
595
570
  }
596
571
  }
597
572
 
598
573
  protected serializeAssignments(
599
- sourceID: number,
574
+ source: SerovalNodeWithProperties,
600
575
  node: SerovalObjectRecordNode,
601
576
  ): string | undefined {
602
577
  const len = node.s;
603
578
  if (len) {
604
- this.stack.push(sourceID);
579
+ this.stack.push(source.i);
605
580
  const mainAssignments: Assignment[] = [];
606
581
  const keys = node.k;
607
582
  const values = node.v;
608
583
  for (let i = 0; i < len; i++) {
609
- this.serializeAssignment(sourceID, mainAssignments, keys[i], values[i]);
584
+ this.serializeAssignment(source, mainAssignments, keys[i], values[i]);
610
585
  }
611
586
  this.stack.pop();
612
587
  return resolveAssignments(mainAssignments);
@@ -615,29 +590,28 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
615
590
  }
616
591
 
617
592
  protected serializeDictionary(
618
- i: number,
619
- p: SerovalObjectRecordNode | undefined,
593
+ node: SerovalNodeWithProperties,
620
594
  init: string,
621
595
  ): string {
622
- if (p) {
596
+ if (node.p) {
623
597
  if (this.features & Feature.ObjectAssign) {
624
- init = this.serializeWithObjectAssign(p, i, init);
598
+ init = this.serializeWithObjectAssign(node, node.p, init);
625
599
  } else {
626
- this.markRef(i);
627
- const assignments = this.serializeAssignments(i, p);
600
+ this.markRef(node.i);
601
+ const assignments = this.serializeAssignments(node, node.p);
628
602
  if (assignments) {
629
- return '(' + this.assignIndexedValue(i, init) + ',' + assignments + this.getRefParam(i) + ')';
603
+ return '(' + this.assignIndexedValue(node.i, init) + ',' + assignments + this.getRefParam(node.i) + ')';
630
604
  }
631
605
  }
632
606
  }
633
- return this.assignIndexedValue(i, init);
607
+ return this.assignIndexedValue(node.i, init);
634
608
  }
635
609
 
636
610
  protected serializeNullConstructor(
637
611
  node: SerovalNullConstructorNode,
638
612
  ): string {
639
613
  this.pushObjectFlag(node.o, node.i);
640
- return this.serializeDictionary(node.i, node.p, NULL_CONSTRUCTOR);
614
+ return this.serializeDictionary(node, NULL_CONSTRUCTOR);
641
615
  }
642
616
 
643
617
  protected serializeDate(
@@ -690,6 +664,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
690
664
  id: number,
691
665
  key: SerovalNode,
692
666
  val: SerovalNode,
667
+ sentinel: string,
693
668
  ): string {
694
669
  if (this.isIndexedValueInStack(key)) {
695
670
  // Create reference for the map instance
@@ -714,9 +689,9 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
714
689
  // basically we serialize the intended object in place WITHOUT
715
690
  // actually returning it, this is by returning a placeholder
716
691
  // value that we will remove sometime after.
717
- const serialized = '(' + this.serialize(val) + ',[' + this.getSpecialReference(SpecialReference.Sentinel) + ',' + this.getSpecialReference(SpecialReference.Sentinel) + '])';
692
+ const serialized = '(' + this.serialize(val) + ',[' + sentinel + ',' + sentinel + '])';
718
693
  this.createSetAssignment(id, keyRef, this.getRefParam(val.i));
719
- this.createDeleteAssignment(id, this.getSpecialReference(SpecialReference.Sentinel));
694
+ this.createDeleteAssignment(id, sentinel);
720
695
  return serialized;
721
696
  }
722
697
  const parent = this.stack;
@@ -730,9 +705,9 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
730
705
  const valueRef = this.getRefParam((val as SerovalIndexedValueNode).i);
731
706
  this.markRef(id);
732
707
  if (key.t !== SerovalNodeType.IndexedValue && key.i != null && this.isMarked(key.i)) {
733
- const serialized = '(' + this.serialize(key) + ',[' + this.getSpecialReference(SpecialReference.Sentinel) + ',' + this.getSpecialReference(SpecialReference.Sentinel) + '])';
708
+ const serialized = '(' + this.serialize(key) + ',[' + sentinel + ',' + sentinel + '])';
734
709
  this.createSetAssignment(id, this.getRefParam(key.i), valueRef);
735
- this.createDeleteAssignment(id, this.getSpecialReference(SpecialReference.Sentinel));
710
+ this.createDeleteAssignment(id, sentinel);
736
711
  return serialized;
737
712
  }
738
713
  // Reset stack for the key serialization
@@ -752,13 +727,15 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
752
727
  let serialized = MAP_CONSTRUCTOR;
753
728
  const size = node.e.s;
754
729
  const id = node.i;
730
+ const sentinel = node.f;
731
+ const sentinelID = this.getRefParam(sentinel.i);
755
732
  if (size) {
756
733
  const keys = node.e.k;
757
734
  const vals = node.e.v;
758
735
  this.stack.push(id);
759
- let result = this.serializeMapEntry(id, keys[0], vals[0]);
736
+ let result = this.serializeMapEntry(id, keys[0], vals[0], sentinelID);
760
737
  for (let i = 1, item = result; i < size; i++) {
761
- item = this.serializeMapEntry(id, keys[i], vals[i]);
738
+ item = this.serializeMapEntry(id, keys[i], vals[i], sentinelID);
762
739
  result += (item && result && ',') + item;
763
740
  }
764
741
  this.stack.pop();
@@ -769,6 +746,10 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
769
746
  serialized += '([' + result + '])';
770
747
  }
771
748
  }
749
+ if (sentinel.t === SerovalNodeType.MapSentinel) {
750
+ this.markRef(sentinel.i);
751
+ serialized = '(' + this.serialize(sentinel) + ',' + serialized + ')';
752
+ }
772
753
  return this.assignIndexedValue(id, serialized);
773
754
  }
774
755
 
@@ -817,13 +798,13 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
817
798
  // `AggregateError` might've been extended
818
799
  // either through class or custom properties
819
800
  // Make sure to assign extra properties
820
- return this.serializeDictionary(id, node.p, serialized);
801
+ return this.serializeDictionary(node, serialized);
821
802
  }
822
803
 
823
804
  protected serializeError(
824
805
  node: SerovalErrorNode,
825
806
  ): string {
826
- return this.serializeDictionary(node.i, node.p, 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")');
807
+ return this.serializeDictionary(node, 'new ' + ERROR_CONSTRUCTOR_STRING[node.s] + '("' + node.m + '")');
827
808
  }
828
809
 
829
810
  protected serializePromise(
@@ -840,17 +821,11 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
840
821
  // the Promise evaluates after the parent
841
822
  // has initialized
842
823
  const ref = this.getRefParam((fulfilled as SerovalIndexedValueNode).i);
843
- if (this.features & Feature.ArrowFunction) {
844
- if (node.s) {
845
- serialized = constructor + '().then(()=>' + ref + ')';
846
- } else {
847
- serialized = constructor + '().catch(()=>{throw ' + ref + '})';
848
- }
849
- } else if (node.s) {
850
- serialized = constructor + '().then(function(){return ' + ref + '})';
851
- } else {
852
- serialized = constructor + '().catch(function(){throw ' + ref + '})';
853
- }
824
+ serialized = constructor + (
825
+ node.s
826
+ ? '().then(' + this.createFunction([], ref) + ')'
827
+ : '().catch(' + this.createEffectfulFunction([], 'throw ' + ref) + ')'
828
+ );
854
829
  } else {
855
830
  this.stack.push(id);
856
831
  const result = this.serialize(fulfilled);
@@ -905,7 +880,7 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
905
880
  ): string {
906
881
  return this.assignIndexedValue(
907
882
  node.i,
908
- 'new Headers(' + this.serializeProperties(node.i, node.e) + ')',
883
+ 'new Headers(' + this.serializeProperties(node, node.e) + ')',
909
884
  );
910
885
  }
911
886
 
@@ -999,9 +974,12 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
999
974
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
1000
975
  const plugin = currentPlugins[i];
1001
976
  if (plugin.tag === node.c) {
1002
- return plugin.serialize(node.s, this, {
1003
- id: node.i,
1004
- });
977
+ return this.assignIndexedValue(
978
+ node.i,
979
+ plugin.serialize(node.s, this, {
980
+ id: node.i,
981
+ }),
982
+ );
1005
983
  }
1006
984
  }
1007
985
  }
@@ -1036,6 +1014,89 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1036
1014
  node: SerovalReadableStreamCloseNode,
1037
1015
  ): string;
1038
1016
 
1017
+ protected serializeMapSentinel(node: SerovalMapSentinelNode): string {
1018
+ return this.assignIndexedValue(
1019
+ node.i,
1020
+ '[]',
1021
+ );
1022
+ }
1023
+
1024
+ protected serializeIteratorFactory(node: SerovalIteratorFactoryNode): string {
1025
+ return this.assignIndexedValue(
1026
+ node.i,
1027
+ this.createFunction(
1028
+ ['s'],
1029
+ this.createFunction(
1030
+ ['i', 'c', 'd', 't'],
1031
+ '(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
1032
+ + '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}') + '})',
1033
+ ),
1034
+ ),
1035
+ );
1036
+ }
1037
+
1038
+ protected serializeIteratorFactoryInstance(
1039
+ node: SerovalIteratorFactoryInstanceNode,
1040
+ ): string {
1041
+ return '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
1042
+ }
1043
+
1044
+ protected serializeAsyncIteratorFactory(node: SerovalAsyncIteratorFactoryNode): string {
1045
+ return this.assignIndexedValue(
1046
+ node.i,
1047
+ this.createFunction(
1048
+ ['s'],
1049
+ this.createFunction(
1050
+ ['i', 't'],
1051
+ '(i=0,t={[' + this.serialize(node.f) + ']:' + this.createFunction([], 't') + ','
1052
+ + 'next:' + this.createFunction(
1053
+ [],
1054
+ 'Promise.resolve().then(' + this.createEffectfulFunction(
1055
+ ['c', 'd'],
1056
+ '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}',
1057
+ ) + ')',
1058
+ ) + '})',
1059
+ ),
1060
+ ),
1061
+ );
1062
+ }
1063
+
1064
+ protected serializeAsyncIteratorFactoryInstance(
1065
+ node: SerovalAsyncIteratorFactoryInstanceNode,
1066
+ ): string {
1067
+ return '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
1068
+ }
1069
+
1070
+ protected serializeReadableStream(
1071
+ node: SerovalReadableStreamNode,
1072
+ ): string {
1073
+ this.stack.push(node.i);
1074
+ const result = '(' + this.serialize(node.a[0]) + ')(' + this.serialize(node.a[1]) + ')';
1075
+ this.stack.pop();
1076
+ return this.assignIndexedValue(
1077
+ node.i,
1078
+ result,
1079
+ );
1080
+ }
1081
+
1082
+ protected serializeReadableStreamFactory(
1083
+ node: SerovalReadableStreamFactoryNode,
1084
+ ): string {
1085
+ return this.assignIndexedValue(
1086
+ node.i,
1087
+ this.createFunction(
1088
+ ['s'],
1089
+ 'new ReadableStream({start:' + this.createFunction(
1090
+ ['c'],
1091
+ 'Promise.resolve().then(' + this.createEffectfulFunction(
1092
+ ['i', 'v'],
1093
+ 'for(i=0;i<s.d;i++)c.enqueue(s.v[i]);(s.t===-1)?c.close():c.error(s.v[i])',
1094
+ ) + ')',
1095
+ ) + '})',
1096
+ ),
1097
+ );
1098
+ }
1099
+
1039
1100
  serialize(node: SerovalNode): string {
1040
1101
  switch (node.t) {
1041
1102
  case SerovalNodeType.Constant:
@@ -1119,6 +1180,20 @@ export default abstract class BaseSerializerContext implements PluginAccessOptio
1119
1180
  return this.serializeDOMException(node);
1120
1181
  case SerovalNodeType.Plugin:
1121
1182
  return this.serializePlugin(node);
1183
+ case SerovalNodeType.MapSentinel:
1184
+ return this.serializeMapSentinel(node);
1185
+ case SerovalNodeType.IteratorFactory:
1186
+ return this.serializeIteratorFactory(node);
1187
+ case SerovalNodeType.IteratorFactoryInstance:
1188
+ return this.serializeIteratorFactoryInstance(node);
1189
+ case SerovalNodeType.AsyncIteratorFactory:
1190
+ return this.serializeAsyncIteratorFactory(node);
1191
+ case SerovalNodeType.AsyncIteratorFactoryInstance:
1192
+ return this.serializeAsyncIteratorFactoryInstance(node);
1193
+ case SerovalNodeType.ReadableStream:
1194
+ return this.serializeReadableStream(node);
1195
+ case SerovalNodeType.ReadableStreamFactory:
1196
+ return this.serializeReadableStreamFactory(node);
1122
1197
  default:
1123
1198
  throw new Error('invariant');
1124
1199
  }
@@ -1,5 +1,5 @@
1
- import BaseAsyncParserContext from '../base/async';
2
- import type { CrossParserContextOptions } from './cross-parser';
1
+ import BaseAsyncParserContext from '../context/parser/async';
2
+ import type { CrossParserContextOptions } from './parser';
3
3
  import type { SerovalMode } from '../plugin';
4
4
 
5
5
  export type CrossAsyncParserContextOptions = CrossParserContextOptions
@@ -0,0 +1,19 @@
1
+ import BaseDeserializerContext from '../context/deserializer';
2
+ import type { BaseDeserializerOptions } from '../context/deserializer';
3
+ import type { SerovalMode } from '../plugin';
4
+
5
+ export type CrossDeserializerContextOptions = BaseDeserializerOptions;
6
+
7
+ export default class CrossDeserializerContext extends BaseDeserializerContext {
8
+ readonly mode: SerovalMode = 'cross';
9
+
10
+ assignIndexedValue<T>(
11
+ index: number,
12
+ value: T,
13
+ ): T {
14
+ if (!this.refs.has(index)) {
15
+ this.refs.set(index, value);
16
+ }
17
+ return value;
18
+ }
19
+ }