seroval 1.2.0 → 1.3.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 (52) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cjs/development/index.cjs +283 -398
  3. package/dist/cjs/development/index.cjs.map +3 -3
  4. package/dist/cjs/production/index.cjs +5 -5
  5. package/dist/esm/development/index.mjs +283 -398
  6. package/dist/esm/development/index.mjs.map +3 -3
  7. package/dist/esm/production/index.mjs +5 -5
  8. package/dist/types/core/base-primitives.d.ts +1 -2
  9. package/dist/types/core/base-primitives.d.ts.map +1 -1
  10. package/dist/types/core/compat.d.ts +2 -3
  11. package/dist/types/core/compat.d.ts.map +1 -1
  12. package/dist/types/core/constants.d.ts +3 -6
  13. package/dist/types/core/constants.d.ts.map +1 -1
  14. package/dist/types/core/context/deserializer.d.ts +0 -3
  15. package/dist/types/core/context/deserializer.d.ts.map +1 -1
  16. package/dist/types/core/context/parser/async.d.ts +2 -2
  17. package/dist/types/core/context/parser/async.d.ts.map +1 -1
  18. package/dist/types/core/context/parser/stream.d.ts +8 -7
  19. package/dist/types/core/context/parser/stream.d.ts.map +1 -1
  20. package/dist/types/core/context/parser/sync.d.ts +3 -3
  21. package/dist/types/core/context/parser/sync.d.ts.map +1 -1
  22. package/dist/types/core/context/parser.d.ts +10 -12
  23. package/dist/types/core/context/parser.d.ts.map +1 -1
  24. package/dist/types/core/context/serializer.d.ts +1 -5
  25. package/dist/types/core/context/serializer.d.ts.map +1 -1
  26. package/dist/types/core/cross/index.d.ts.map +1 -1
  27. package/dist/types/core/function-string.d.ts +3 -0
  28. package/dist/types/core/function-string.d.ts.map +1 -0
  29. package/dist/types/core/special-reference.d.ts +4 -5
  30. package/dist/types/core/special-reference.d.ts.map +1 -1
  31. package/dist/types/core/tree/serializer.d.ts +1 -2
  32. package/dist/types/core/tree/serializer.d.ts.map +1 -1
  33. package/dist/types/core/types.d.ts +5 -19
  34. package/dist/types/core/types.d.ts.map +1 -1
  35. package/package.json +9 -9
  36. package/src/core/base-primitives.ts +2 -22
  37. package/src/core/compat.ts +6 -2
  38. package/src/core/constants.ts +2 -5
  39. package/src/core/context/deserializer.ts +2 -35
  40. package/src/core/context/parser/async.ts +67 -84
  41. package/src/core/context/parser/stream.ts +64 -109
  42. package/src/core/context/parser/sync.ts +66 -83
  43. package/src/core/context/parser.ts +24 -56
  44. package/src/core/context/serializer.ts +12 -128
  45. package/src/core/cross/index.ts +2 -6
  46. package/src/core/function-string.ts +31 -0
  47. package/src/core/special-reference.ts +96 -8
  48. package/src/core/tree/serializer.ts +0 -7
  49. package/src/core/types.ts +5 -27
  50. package/dist/types/core/abort-signal.d.ts +0 -2
  51. package/dist/types/core/abort-signal.d.ts.map +0 -1
  52. package/src/core/abort-signal.ts +0 -13
@@ -19,7 +19,7 @@ import {
19
19
  createTypedArrayNode,
20
20
  } from '../../base-primitives';
21
21
  import { Feature } from '../../compat';
22
- import { NIL, SerovalNodeType } from '../../constants';
22
+ import { NIL } from '../../constants';
23
23
  import { SerovalParserError, SerovalUnsupportedTypeError } from '../../errors';
24
24
  import {
25
25
  FALSE_NODE,
@@ -27,15 +27,12 @@ import {
27
27
  TRUE_NODE,
28
28
  UNDEFINED_NODE,
29
29
  } from '../../literals';
30
- import { createSerovalNode } from '../../node';
31
30
  import { OpaqueReference } from '../../opaque-reference';
32
31
  import { SpecialReference } from '../../special-reference';
33
32
  import type { Stream } from '../../stream';
34
33
  import { createStream, isStream } from '../../stream';
35
34
  import { serializeString } from '../../string';
36
35
  import type {
37
- SerovalAbortSignalConstructorNode,
38
- SerovalAbortSignalSyncNode,
39
36
  SerovalAggregateErrorNode,
40
37
  SerovalArrayNode,
41
38
  SerovalBigIntTypedArrayNode,
@@ -60,7 +57,7 @@ import type {
60
57
  TypedArrayValue,
61
58
  } from '../../utils/typed-array';
62
59
  import type { BaseParserContextOptions } from '../parser';
63
- import { BaseParserContext } from '../parser';
60
+ import { BaseParserContext, ParserNodeType } from '../parser';
64
61
 
65
62
  type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
66
63
 
@@ -71,7 +68,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
71
68
  const nodes = [];
72
69
  for (let i = 0, len = current.length; i < len; i++) {
73
70
  if (i in current) {
74
- nodes[i] = this.parse(current[i]);
71
+ nodes[i] = this.parseTop(current[i]);
75
72
  }
76
73
  }
77
74
  return nodes;
@@ -89,7 +86,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
89
86
  const valueNodes: SerovalNode[] = [];
90
87
  for (let i = 0, len = entries.length; i < len; i++) {
91
88
  keyNodes.push(serializeString(entries[i][0]));
92
- valueNodes.push(this.parse(entries[i][1]));
89
+ valueNodes.push(this.parseTop(entries[i][1]));
93
90
  }
94
91
  // Check special properties, symbols in this case
95
92
  let symbol = Symbol.iterator;
@@ -98,7 +95,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
98
95
  valueNodes.push(
99
96
  createIteratorFactoryInstanceNode(
100
97
  this.parseIteratorFactory(),
101
- this.parse(
98
+ this.parseTop(
102
99
  iteratorToSequence(properties as unknown as Iterable<unknown>),
103
100
  ),
104
101
  ),
@@ -110,7 +107,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
110
107
  valueNodes.push(
111
108
  createAsyncIteratorFactoryInstanceNode(
112
109
  this.parseAsyncIteratorFactory(),
113
- this.parse(createStream()),
110
+ this.parseTop(createStream()),
114
111
  ),
115
112
  );
116
113
  }
@@ -145,25 +142,29 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
145
142
  }
146
143
 
147
144
  protected parseBoxed(id: number, current: object): SerovalBoxedNode {
148
- return createBoxedNode(id, this.parse(current.valueOf()));
145
+ return createBoxedNode(id, this.parseTop(current.valueOf()));
149
146
  }
150
147
 
151
148
  protected parseTypedArray(
152
149
  id: number,
153
150
  current: TypedArrayValue,
154
151
  ): SerovalTypedArrayNode {
155
- return createTypedArrayNode(id, current, this.parse(current.buffer));
152
+ return createTypedArrayNode(id, current, this.parseTop(current.buffer));
156
153
  }
157
154
 
158
155
  protected parseBigIntTypedArray(
159
156
  id: number,
160
157
  current: BigIntTypedArrayValue,
161
158
  ): SerovalBigIntTypedArrayNode {
162
- return createBigIntTypedArrayNode(id, current, this.parse(current.buffer));
159
+ return createBigIntTypedArrayNode(
160
+ id,
161
+ current,
162
+ this.parseTop(current.buffer),
163
+ );
163
164
  }
164
165
 
165
166
  protected parseDataView(id: number, current: DataView): SerovalDataViewNode {
166
- return createDataViewNode(id, current, this.parse(current.buffer));
167
+ return createDataViewNode(id, current, this.parseTop(current.buffer));
167
168
  }
168
169
 
169
170
  protected parseError(id: number, current: Error): SerovalErrorNode {
@@ -194,8 +195,8 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
194
195
  const keyNodes: SerovalNode[] = [];
195
196
  const valueNodes: SerovalNode[] = [];
196
197
  for (const [key, value] of current.entries()) {
197
- keyNodes.push(this.parse(key));
198
- valueNodes.push(this.parse(value));
198
+ keyNodes.push(this.parseTop(key));
199
+ valueNodes.push(this.parseTop(value));
199
200
  }
200
201
  return this.createMapNode(id, keyNodes, valueNodes, current.size);
201
202
  }
@@ -203,7 +204,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
203
204
  protected parseSet(id: number, current: Set<unknown>): SerovalSetNode {
204
205
  const items: SerovalNode[] = [];
205
206
  for (const item of current.keys()) {
206
- items.push(this.parse(item));
207
+ items.push(this.parseTop(item));
207
208
  }
208
209
  return createSetNode(id, current.size, items);
209
210
  }
@@ -242,37 +243,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
242
243
  id: number,
243
244
  _current: Promise<unknown>,
244
245
  ): SerovalPromiseConstructorNode {
245
- return this.createPromiseConstructorNode(id);
246
- }
247
-
248
- protected parseAbortSignalSync(
249
- id: number,
250
- current: AbortSignal,
251
- ): SerovalAbortSignalSyncNode {
252
- return createSerovalNode(
253
- SerovalNodeType.AbortSignalSync,
254
- id,
255
- NIL,
256
- NIL,
257
- NIL,
258
- NIL,
259
- NIL,
260
- NIL,
261
- NIL,
262
- this.parse(current.reason),
263
- NIL,
264
- NIL,
265
- );
266
- }
267
-
268
- protected parseAbortSignal(
269
- id: number,
270
- current: AbortSignal,
271
- ): SerovalAbortSignalConstructorNode | SerovalAbortSignalSyncNode {
272
- if (current.aborted) {
273
- return this.parseAbortSignalSync(id, current);
274
- }
275
- return this.createAbortSignalConstructorNode(id);
246
+ return this.createPromiseConstructorNode(id, this.createIndex({}));
276
247
  }
277
248
 
278
249
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: ehh
@@ -285,7 +256,7 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
285
256
  }
286
257
  const currentClass = current.constructor;
287
258
  if (currentClass === OpaqueReference) {
288
- return this.parse(
259
+ return this.parseTop(
289
260
  (current as OpaqueReference<unknown, unknown>).replacement,
290
261
  );
291
262
  }
@@ -349,13 +320,6 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
349
320
  return this.parsePromise(id, current as unknown as Promise<unknown>);
350
321
  }
351
322
  const currentFeatures = this.features;
352
- if (
353
- currentFeatures & Feature.AbortSignal &&
354
- typeof AbortSignal !== 'undefined' &&
355
- currentClass === AbortSignal
356
- ) {
357
- return this.parseAbortSignal(id, current as unknown as AbortSignal);
358
- }
359
323
  // BigInt Typed Arrays
360
324
  if (currentFeatures & Feature.BigIntTypedArray) {
361
325
  switch (currentClass) {
@@ -389,37 +353,56 @@ export default abstract class BaseSyncParserContext extends BaseParserContext {
389
353
  throw new SerovalUnsupportedTypeError(current);
390
354
  }
391
355
 
392
- parse<T>(current: T): SerovalNode {
393
- try {
394
- switch (typeof current) {
395
- case 'boolean':
396
- return current ? TRUE_NODE : FALSE_NODE;
397
- case 'undefined':
398
- return UNDEFINED_NODE;
399
- case 'string':
400
- return createStringNode(current as string);
401
- case 'number':
402
- return createNumberNode(current as number);
403
- case 'bigint':
404
- return createBigIntNode(current as bigint);
405
- case 'object': {
406
- if (current) {
407
- const ref = this.getReference(current);
408
- return ref.type === 0
409
- ? this.parseObject(ref.value, current as object)
410
- : ref.value;
411
- }
412
- return NULL_NODE;
356
+ protected parseFunction(current: unknown): SerovalNode {
357
+ const ref = this.getReference(current);
358
+ if (ref.type !== ParserNodeType.Fresh) {
359
+ return ref.value;
360
+ }
361
+ const plugin = this.parsePlugin(ref.value, current);
362
+ if (plugin) {
363
+ return plugin;
364
+ }
365
+ throw new SerovalUnsupportedTypeError(current);
366
+ }
367
+
368
+ parseTop<T>(current: T): SerovalNode {
369
+ switch (typeof current) {
370
+ case 'boolean':
371
+ return current ? TRUE_NODE : FALSE_NODE;
372
+ case 'undefined':
373
+ return UNDEFINED_NODE;
374
+ case 'string':
375
+ return createStringNode(current as string);
376
+ case 'number':
377
+ return createNumberNode(current as number);
378
+ case 'bigint':
379
+ return createBigIntNode(current as bigint);
380
+ case 'object': {
381
+ if (current) {
382
+ const ref = this.getReference(current);
383
+ return ref.type === ParserNodeType.Fresh
384
+ ? this.parseObject(ref.value, current as object)
385
+ : ref.value;
413
386
  }
414
- case 'symbol':
415
- return this.parseWellKnownSymbol(current);
416
- case 'function':
417
- return this.parseFunction(current as (...args: unknown[]) => unknown);
418
- default:
419
- throw new SerovalUnsupportedTypeError(current);
387
+ return NULL_NODE;
420
388
  }
389
+ case 'symbol':
390
+ return this.parseWellKnownSymbol(current);
391
+ case 'function': {
392
+ return this.parseFunction(current);
393
+ }
394
+ default:
395
+ throw new SerovalUnsupportedTypeError(current);
396
+ }
397
+ }
398
+
399
+ parse<T>(current: T): SerovalNode {
400
+ try {
401
+ return this.parseTop(current);
421
402
  } catch (error) {
422
- throw new SerovalParserError(error);
403
+ throw error instanceof SerovalParserError
404
+ ? error
405
+ : new SerovalParserError(error);
423
406
  }
424
407
  }
425
408
  }
@@ -17,7 +17,6 @@ import {
17
17
  SpecialReference,
18
18
  } from '../special-reference';
19
19
  import type {
20
- SerovalAbortSignalConstructorNode,
21
20
  SerovalAsyncIteratorFactoryNode,
22
21
  SerovalIndexedValueNode,
23
22
  SerovalIteratorFactoryNode,
@@ -39,24 +38,24 @@ export interface BaseParserContextOptions extends PluginAccessOptions {
39
38
  refs?: Map<unknown, number>;
40
39
  }
41
40
 
42
- const enum NodeType {
41
+ export const enum ParserNodeType {
43
42
  Fresh = 0,
44
43
  Indexed = 1,
45
44
  Referenced = 2,
46
45
  }
47
46
 
48
- interface FreshNode {
49
- type: NodeType.Fresh;
47
+ export interface FreshNode {
48
+ type: ParserNodeType.Fresh;
50
49
  value: number;
51
50
  }
52
51
 
53
- interface IndexedNode {
54
- type: NodeType.Indexed;
52
+ export interface IndexedNode {
53
+ type: ParserNodeType.Indexed;
55
54
  value: SerovalIndexedValueNode;
56
55
  }
57
56
 
58
- interface ReferencedNode {
59
- type: NodeType.Referenced;
57
+ export interface ReferencedNode {
58
+ type: ParserNodeType.Referenced;
60
59
  value: SerovalReferenceNode;
61
60
  }
62
61
 
@@ -87,59 +86,46 @@ export abstract class BaseParserContext implements PluginAccessOptions {
87
86
  return this.marked.has(id);
88
87
  }
89
88
 
89
+ protected createIndex<T>(current: T): number {
90
+ const id = this.refs.size;
91
+ this.refs.set(current, id);
92
+ return id;
93
+ }
94
+
90
95
  protected getIndexedValue<T>(current: T): FreshNode | IndexedNode {
91
96
  const registeredId = this.refs.get(current);
92
97
  if (registeredId != null) {
93
98
  this.markRef(registeredId);
94
99
  return {
95
- type: NodeType.Indexed,
100
+ type: ParserNodeType.Indexed,
96
101
  value: createIndexedValueNode(registeredId),
97
102
  };
98
103
  }
99
- const id = this.refs.size;
100
- this.refs.set(current, id);
101
104
  return {
102
- type: NodeType.Fresh,
103
- value: id,
105
+ type: ParserNodeType.Fresh,
106
+ value: this.createIndex(current),
104
107
  };
105
108
  }
106
109
 
107
110
  protected getReference<T>(current: T): ObjectNode {
108
111
  const indexed = this.getIndexedValue(current);
109
- if (indexed.type === NodeType.Indexed) {
112
+ if (indexed.type === ParserNodeType.Indexed) {
110
113
  return indexed;
111
114
  }
112
115
  if (hasReferenceID(current)) {
113
116
  return {
114
- type: NodeType.Referenced,
117
+ type: ParserNodeType.Referenced,
115
118
  value: createReferenceNode(indexed.value, current),
116
119
  };
117
120
  }
118
121
  return indexed;
119
122
  }
120
123
 
121
- protected getStrictReference<T>(
122
- current: T,
123
- ): SerovalIndexedValueNode | SerovalReferenceNode {
124
- assert(hasReferenceID(current), new SerovalUnsupportedTypeError(current));
125
- const result = this.getIndexedValue(current);
126
- if (result.type === NodeType.Indexed) {
127
- return result.value;
128
- }
129
- return createReferenceNode(result.value, current);
130
- }
131
-
132
- protected parseFunction(
133
- current: (...args: unknown[]) => unknown,
134
- ): SerovalNode {
135
- return this.getStrictReference(current);
136
- }
137
-
138
124
  protected parseWellKnownSymbol(
139
125
  current: symbol,
140
126
  ): SerovalIndexedValueNode | SerovalWKSymbolNode | SerovalReferenceNode {
141
127
  const ref = this.getReference(current);
142
- if (ref.type !== NodeType.Fresh) {
128
+ if (ref.type !== ParserNodeType.Fresh) {
143
129
  return ref.value;
144
130
  }
145
131
  assert(current in INV_SYMBOL_REF, new SerovalUnsupportedTypeError(current));
@@ -150,7 +136,7 @@ export abstract class BaseParserContext implements PluginAccessOptions {
150
136
  ref: SpecialReference,
151
137
  ): SerovalIndexedValueNode | SerovalSpecialReferenceNode {
152
138
  const result = this.getIndexedValue(SPECIAL_REFS[ref]);
153
- if (result.type === NodeType.Indexed) {
139
+ if (result.type === ParserNodeType.Indexed) {
154
140
  return result.value;
155
141
  }
156
142
  return createSerovalNode(
@@ -173,7 +159,7 @@ export abstract class BaseParserContext implements PluginAccessOptions {
173
159
  | SerovalIndexedValueNode
174
160
  | SerovalIteratorFactoryNode {
175
161
  const result = this.getIndexedValue(ITERATOR);
176
- if (result.type === NodeType.Indexed) {
162
+ if (result.type === ParserNodeType.Indexed) {
177
163
  return result.value;
178
164
  }
179
165
  return createSerovalNode(
@@ -196,7 +182,7 @@ export abstract class BaseParserContext implements PluginAccessOptions {
196
182
  | SerovalIndexedValueNode
197
183
  | SerovalAsyncIteratorFactoryNode {
198
184
  const result = this.getIndexedValue(ASYNC_ITERATOR);
199
- if (result.type === NodeType.Indexed) {
185
+ if (result.type === ParserNodeType.Indexed) {
200
186
  return result.value;
201
187
  }
202
188
  return createSerovalNode(
@@ -264,11 +250,12 @@ export abstract class BaseParserContext implements PluginAccessOptions {
264
250
 
265
251
  protected createPromiseConstructorNode(
266
252
  id: number,
253
+ resolver: number,
267
254
  ): SerovalPromiseConstructorNode {
268
255
  return createSerovalNode(
269
256
  SerovalNodeType.PromiseConstructor,
270
257
  id,
271
- NIL,
258
+ resolver,
272
259
  NIL,
273
260
  NIL,
274
261
  NIL,
@@ -280,23 +267,4 @@ export abstract class BaseParserContext implements PluginAccessOptions {
280
267
  NIL,
281
268
  );
282
269
  }
283
-
284
- protected createAbortSignalConstructorNode(
285
- id: number,
286
- ): SerovalAbortSignalConstructorNode {
287
- return createSerovalNode(
288
- SerovalNodeType.AbortSignalConstructor,
289
- id,
290
- NIL,
291
- NIL,
292
- NIL,
293
- NIL,
294
- NIL,
295
- NIL,
296
- NIL,
297
- this.parseSpecialReference(SpecialReference.AbortSignalConstructor),
298
- NIL,
299
- NIL,
300
- );
301
- }
302
270
  }
@@ -12,13 +12,11 @@ import {
12
12
  SerovalSerializationError,
13
13
  SerovalUnsupportedNodeError,
14
14
  } from '../errors';
15
+ import { createEffectfulFunction, createFunction } from '../function-string';
15
16
  import { REFERENCES_KEY } from '../keys';
16
17
  import type { Plugin, PluginAccessOptions, SerovalMode } from '../plugin';
17
- import { SpecialReference } from '../special-reference';
18
+ import { serializeSpecialReferenceValue } from '../special-reference';
18
19
  import type {
19
- SerovalAbortSignalAbortNode,
20
- SerovalAbortSignalConstructorNode,
21
- SerovalAbortSignalSyncNode,
22
20
  SerovalAggregateErrorNode,
23
21
  SerovalArrayBufferNode,
24
22
  SerovalArrayNode,
@@ -253,25 +251,11 @@ export default abstract class BaseSerializerContext
253
251
  abstract readonly mode: SerovalMode;
254
252
 
255
253
  createFunction(parameters: string[], body: string): string {
256
- if (this.features & Feature.ArrowFunction) {
257
- const joined =
258
- parameters.length === 1
259
- ? parameters[0]
260
- : '(' + parameters.join(',') + ')';
261
- return joined + '=>' + (body.startsWith('{') ? '(' + body + ')' : body);
262
- }
263
- return 'function(' + parameters.join(',') + '){return ' + body + '}';
254
+ return createFunction(this.features, parameters, body);
264
255
  }
265
256
 
266
257
  createEffectfulFunction(parameters: string[], body: string): string {
267
- if (this.features & Feature.ArrowFunction) {
268
- const joined =
269
- parameters.length === 1
270
- ? parameters[0]
271
- : '(' + parameters.join(',') + ')';
272
- return joined + '=>{' + body + '}';
273
- }
274
- return 'function(' + parameters.join(',') + '){' + body + '}';
258
+ return createEffectfulFunction(this.features, parameters, body);
275
259
  }
276
260
 
277
261
  /**
@@ -919,7 +903,11 @@ export default abstract class BaseSerializerContext
919
903
  protected serializePromiseConstructor(
920
904
  node: SerovalPromiseConstructorNode,
921
905
  ): string {
922
- return this.assignIndexedValue(node.i, this.getConstructor(node.f) + '()');
906
+ const resolver = this.assignIndexedValue(node.s, '{p:0,s:0,f:0}');
907
+ return this.assignIndexedValue(
908
+ node.i,
909
+ this.getConstructor(node.f) + '(' + resolver + ')',
910
+ );
923
911
  }
924
912
 
925
913
  protected serializePromiseResolve(node: SerovalPromiseResolveNode): string {
@@ -944,84 +932,12 @@ export default abstract class BaseSerializerContext
944
932
  );
945
933
  }
946
934
 
947
- private serializeSpecialReferenceValue(ref: SpecialReference): string {
948
- switch (ref) {
949
- case SpecialReference.MapSentinel:
950
- return '[]';
951
- case SpecialReference.PromiseConstructor:
952
- return this.createFunction(
953
- ['s', 'f', 'p'],
954
- '((p=new Promise(' +
955
- this.createEffectfulFunction(['a', 'b'], 's=a,f=b') +
956
- ')).s=s,p.f=f,p)',
957
- );
958
- case SpecialReference.PromiseResolve:
959
- return this.createEffectfulFunction(
960
- ['p', 'd'],
961
- 'p.s(d),p.status="success",p.value=d;delete p.s;delete p.f',
962
- );
963
- case SpecialReference.PromiseReject:
964
- return this.createEffectfulFunction(
965
- ['p', 'd'],
966
- 'p.f(d),p.status="failure",p.value=d;delete p.s;delete p.f',
967
- );
968
- case SpecialReference.StreamConstructor:
969
- return this.createFunction(
970
- ['b', 'a', 's', 'l', 'p', 'f', 'e', 'n'],
971
- '(b=[],a=!0,s=!1,l=[],p=0,f=' +
972
- this.createEffectfulFunction(
973
- ['v', 'm', 'x'],
974
- 'for(x=0;x<p;x++)l[x]&&l[x][m](v)',
975
- ) +
976
- ',n=' +
977
- this.createEffectfulFunction(
978
- ['o', 'x', 'z', 'c'],
979
- 'for(x=0,z=b.length;x<z;x++)(c=b[x],(!a&&x===z-1)?o[s?"return":"throw"](c):o.next(c))',
980
- ) +
981
- ',e=' +
982
- this.createFunction(
983
- ['o', 't'],
984
- '(a&&(l[t=p++]=o),n(o),' +
985
- this.createEffectfulFunction([], 'a&&(l[t]=void 0)') +
986
- ')',
987
- ) +
988
- ',{__SEROVAL_STREAM__:!0,on:' +
989
- this.createFunction(['o'], 'e(o)') +
990
- ',next:' +
991
- this.createEffectfulFunction(['v'], 'a&&(b.push(v),f(v,"next"))') +
992
- ',throw:' +
993
- this.createEffectfulFunction(
994
- ['v'],
995
- 'a&&(b.push(v),f(v,"throw"),a=s=!1,l.length=0)',
996
- ) +
997
- ',return:' +
998
- this.createEffectfulFunction(
999
- ['v'],
1000
- 'a&&(b.push(v),f(v,"return"),a=!1,s=!0,l.length=0)',
1001
- ) +
1002
- '})',
1003
- );
1004
- case SpecialReference.AbortSignalConstructor:
1005
- return this.createFunction(
1006
- ['a', 's'],
1007
- '((s=(a=new AbortController).signal).a=a,s)',
1008
- );
1009
- case SpecialReference.AbortSignalAbort:
1010
- return this.createEffectfulFunction(
1011
- ['s', 'r'],
1012
- 's.a.abort(r);delete s.a',
1013
- );
1014
- default:
1015
- return '';
1016
- }
1017
- }
1018
-
1019
935
  protected serializeSpecialReference(
1020
936
  node: SerovalSpecialReferenceNode,
1021
937
  ): string {
1022
938
  return this.assignIndexedValue(
1023
939
  node.i,
1024
- this.serializeSpecialReferenceValue(node.s),
940
+ serializeSpecialReferenceValue(this.features, node.s),
1025
941
  );
1026
942
  }
1027
943
 
@@ -1173,32 +1089,6 @@ export default abstract class BaseSerializerContext
1173
1089
  return this.getRefParam(node.i) + '.return(' + this.serialize(node.f) + ')';
1174
1090
  }
1175
1091
 
1176
- protected serializeAbortSignalSync(node: SerovalAbortSignalSyncNode): string {
1177
- return this.assignIndexedValue(
1178
- node.i,
1179
- 'AbortSignal.abort(' + this.serialize(node.f) + ')',
1180
- );
1181
- }
1182
-
1183
- protected serializeAbortSignalConstructor(
1184
- node: SerovalAbortSignalConstructorNode,
1185
- ): string {
1186
- return this.assignIndexedValue(node.i, this.getConstructor(node.f) + '()');
1187
- }
1188
-
1189
- protected serializeAbortSignalAbort(
1190
- node: SerovalAbortSignalAbortNode,
1191
- ): string {
1192
- return (
1193
- this.getConstructor(node.a[0]) +
1194
- '(' +
1195
- this.getRefParam(node.i) +
1196
- ',' +
1197
- this.serialize(node.a[1]) +
1198
- ')'
1199
- );
1200
- }
1201
-
1202
1092
  serialize(node: SerovalNode): string {
1203
1093
  try {
1204
1094
  switch (node.t) {
@@ -1247,9 +1137,9 @@ export default abstract class BaseSerializerContext
1247
1137
  return this.serializeBoxed(node);
1248
1138
  case SerovalNodeType.PromiseConstructor:
1249
1139
  return this.serializePromiseConstructor(node);
1250
- case SerovalNodeType.PromiseResolve:
1140
+ case SerovalNodeType.PromiseSuccess:
1251
1141
  return this.serializePromiseResolve(node);
1252
- case SerovalNodeType.PromiseReject:
1142
+ case SerovalNodeType.PromiseFailure:
1253
1143
  return this.serializePromiseReject(node);
1254
1144
  case SerovalNodeType.Plugin:
1255
1145
  return this.serializePlugin(node);
@@ -1271,12 +1161,6 @@ export default abstract class BaseSerializerContext
1271
1161
  return this.serializeStreamThrow(node);
1272
1162
  case SerovalNodeType.StreamReturn:
1273
1163
  return this.serializeStreamReturn(node);
1274
- case SerovalNodeType.AbortSignalAbort:
1275
- return this.serializeAbortSignalAbort(node);
1276
- case SerovalNodeType.AbortSignalConstructor:
1277
- return this.serializeAbortSignalConstructor(node);
1278
- case SerovalNodeType.AbortSignalSync:
1279
- return this.serializeAbortSignalSync(node);
1280
1164
  default:
1281
1165
  throw new SerovalUnsupportedNodeError(node);
1282
1166
  }
@@ -131,9 +131,7 @@ export function crossSerializeStream<T>(
131
131
 
132
132
  ctx.start(source);
133
133
 
134
- return () => {
135
- ctx.destroy();
136
- };
134
+ return ctx.destroy.bind(ctx);
137
135
  }
138
136
 
139
137
  export type ToCrossJSONStreamOptions = CrossStreamParserContextOptions;
@@ -154,9 +152,7 @@ export function toCrossJSONStream<T>(
154
152
 
155
153
  ctx.start(source);
156
154
 
157
- return () => {
158
- ctx.destroy();
159
- };
155
+ return ctx.destroy.bind(ctx);
160
156
  }
161
157
 
162
158
  export type FromCrossJSONOptions = CrossDeserializerContextOptions;
@@ -0,0 +1,31 @@
1
+ import { Feature } from './compat';
2
+
3
+ export function createFunction(
4
+ features: number,
5
+ parameters: string[],
6
+ body: string,
7
+ ): string {
8
+ if (features & Feature.ArrowFunction) {
9
+ const joined =
10
+ parameters.length === 1
11
+ ? parameters[0]
12
+ : '(' + parameters.join(',') + ')';
13
+ return joined + '=>' + (body.startsWith('{') ? '(' + body + ')' : body);
14
+ }
15
+ return 'function(' + parameters.join(',') + '){return ' + body + '}';
16
+ }
17
+
18
+ export function createEffectfulFunction(
19
+ features: number,
20
+ parameters: string[],
21
+ body: string,
22
+ ): string {
23
+ if (features & Feature.ArrowFunction) {
24
+ const joined =
25
+ parameters.length === 1
26
+ ? parameters[0]
27
+ : '(' + parameters.join(',') + ')';
28
+ return joined + '=>{' + body + '}';
29
+ }
30
+ return 'function(' + parameters.join(',') + '){' + body + '}';
31
+ }