seroval 0.12.3 → 0.13.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 (140) hide show
  1. package/dist/cjs/development/index.cjs +1432 -958
  2. package/dist/cjs/development/index.cjs.map +3 -3
  3. package/dist/cjs/production/index.cjs +3 -3
  4. package/dist/esm/development/index.mjs +1432 -958
  5. package/dist/esm/development/index.mjs.map +3 -3
  6. package/dist/esm/production/index.mjs +3 -3
  7. package/dist/types/core/Serializer.d.ts +2 -1
  8. package/dist/types/core/Serializer.d.ts.map +1 -1
  9. package/dist/types/core/base-primitives.d.ts +12 -1
  10. package/dist/types/core/base-primitives.d.ts.map +1 -1
  11. package/dist/types/core/compat.d.ts +0 -2
  12. package/dist/types/core/compat.d.ts.map +1 -1
  13. package/dist/types/core/constants.d.ts +8 -2
  14. package/dist/types/core/constants.d.ts.map +1 -1
  15. package/dist/types/core/{tree/deserialize.d.ts → context/deserializer.d.ts} +19 -13
  16. package/dist/types/core/context/deserializer.d.ts.map +1 -0
  17. package/dist/types/core/{base → context/parser}/async.d.ts +6 -5
  18. package/dist/types/core/context/parser/async.d.ts.map +1 -0
  19. package/dist/types/core/{base → context/parser}/stream.d.ts +2 -1
  20. package/dist/types/core/context/parser/stream.d.ts.map +1 -0
  21. package/dist/types/core/{base → context/parser}/sync.d.ts +7 -9
  22. package/dist/types/core/context/parser/sync.d.ts.map +1 -0
  23. package/dist/types/core/context/parser.d.ts +27 -0
  24. package/dist/types/core/context/parser.d.ts.map +1 -0
  25. package/dist/types/core/{serializer-context.old.d.ts → context/serializer.d.ts} +21 -22
  26. package/dist/types/core/context/serializer.d.ts.map +1 -0
  27. package/dist/types/core/cross/async.d.ts +2 -2
  28. package/dist/types/core/cross/async.d.ts.map +1 -1
  29. package/dist/types/core/cross/deserializer.d.ts +9 -0
  30. package/dist/types/core/cross/deserializer.d.ts.map +1 -0
  31. package/dist/types/core/cross/index.d.ts +11 -1
  32. package/dist/types/core/cross/index.d.ts.map +1 -1
  33. package/dist/types/core/cross/parser.d.ts +6 -0
  34. package/dist/types/core/cross/parser.d.ts.map +1 -0
  35. package/dist/types/core/cross/{serialize.d.ts → serializer.d.ts} +6 -5
  36. package/dist/types/core/cross/serializer.d.ts.map +1 -0
  37. package/dist/types/core/cross/stream.d.ts +2 -2
  38. package/dist/types/core/cross/stream.d.ts.map +1 -1
  39. package/dist/types/core/cross/sync.d.ts +2 -2
  40. package/dist/types/core/cross/sync.d.ts.map +1 -1
  41. package/dist/types/core/keys.d.ts +3 -1
  42. package/dist/types/core/keys.d.ts.map +1 -1
  43. package/dist/types/core/plugin.d.ts +6 -7
  44. package/dist/types/core/plugin.d.ts.map +1 -1
  45. package/dist/types/core/special-reference.d.ts +6 -0
  46. package/dist/types/core/special-reference.d.ts.map +1 -0
  47. package/dist/types/core/tree/async.d.ts +2 -2
  48. package/dist/types/core/tree/async.d.ts.map +1 -1
  49. package/dist/types/core/tree/deserializer.d.ts +13 -0
  50. package/dist/types/core/tree/deserializer.d.ts.map +1 -0
  51. package/dist/types/core/tree/{serialize.d.ts → serializer.d.ts} +4 -4
  52. package/dist/types/core/tree/serializer.d.ts.map +1 -0
  53. package/dist/types/core/tree/sync.d.ts +2 -2
  54. package/dist/types/core/tree/sync.d.ts.map +1 -1
  55. package/dist/types/core/types.d.ts +47 -6
  56. package/dist/types/core/types.d.ts.map +1 -1
  57. package/dist/types/core/utils/assert.d.ts.map +1 -0
  58. package/dist/types/core/utils/constructors.d.ts.map +1 -0
  59. package/dist/types/core/utils/deferred.d.ts +14 -0
  60. package/dist/types/core/utils/deferred.d.ts.map +1 -0
  61. package/dist/types/core/utils/error.d.ts +5 -0
  62. package/dist/types/core/utils/error.d.ts.map +1 -0
  63. package/dist/types/core/utils/get-identifier.d.ts.map +1 -0
  64. package/dist/types/core/utils/get-object-flag.d.ts +3 -0
  65. package/dist/types/core/utils/get-object-flag.d.ts.map +1 -0
  66. package/dist/types/core/utils/is-valid-identifier.d.ts +2 -0
  67. package/dist/types/core/utils/is-valid-identifier.d.ts.map +1 -0
  68. package/dist/types/core/utils/iterator-to-sequence.d.ts +20 -0
  69. package/dist/types/core/utils/iterator-to-sequence.d.ts.map +1 -0
  70. package/dist/types/core/utils/promise-to-result.d.ts.map +1 -0
  71. package/dist/types/core/utils/typed-array.d.ts +4 -0
  72. package/dist/types/core/utils/typed-array.d.ts.map +1 -0
  73. package/dist/types/core/web-api.d.ts +4 -1
  74. package/dist/types/core/web-api.d.ts.map +1 -1
  75. package/package.json +2 -2
  76. package/src/core/Serializer.ts +3 -1
  77. package/src/core/base-primitives.ts +229 -1
  78. package/src/core/compat.ts +0 -2
  79. package/src/core/constants.ts +7 -2
  80. package/src/core/{tree/deserialize.ts → context/deserializer.ts} +159 -66
  81. package/src/core/{base → context/parser}/async.ts +181 -309
  82. package/src/core/{base → context/parser}/stream.ts +86 -11
  83. package/src/core/{base → context/parser}/sync.ts +120 -281
  84. package/src/core/context/parser.ts +259 -0
  85. package/src/core/{serializer-context.old.ts → context/serializer.ts} +241 -166
  86. package/src/core/cross/async.ts +2 -2
  87. package/src/core/cross/deserializer.ts +19 -0
  88. package/src/core/cross/index.ts +68 -47
  89. package/src/core/cross/parser.ts +7 -0
  90. package/src/core/cross/{serialize.ts → serializer.ts} +31 -12
  91. package/src/core/cross/stream.ts +2 -2
  92. package/src/core/cross/sync.ts +2 -2
  93. package/src/core/is-serializable.new.ts +1 -1
  94. package/src/core/keys.ts +8 -2
  95. package/src/core/plugin.ts +7 -7
  96. package/src/core/reference.ts +1 -1
  97. package/src/core/special-reference.ts +9 -0
  98. package/src/core/tree/async.ts +2 -2
  99. package/src/core/tree/deserializer.ts +31 -0
  100. package/src/core/tree/index.ts +2 -2
  101. package/src/core/tree/{serialize.ts → serializer.ts} +5 -16
  102. package/src/core/tree/sync.ts +2 -2
  103. package/src/core/types.ts +60 -7
  104. package/src/core/utils/deferred.ts +49 -0
  105. package/src/core/{shared.ts → utils/error.ts} +3 -60
  106. package/src/core/utils/get-object-flag.ts +14 -0
  107. package/src/core/utils/is-valid-identifier.ts +11 -0
  108. package/src/core/utils/iterator-to-sequence.ts +238 -0
  109. package/src/core/utils/typed-array.ts +30 -0
  110. package/src/core/web-api.ts +75 -1
  111. package/src/example.ts +0 -3
  112. package/dist/types/core/assert.d.ts.map +0 -1
  113. package/dist/types/core/base/async.d.ts.map +0 -1
  114. package/dist/types/core/base/stream.d.ts.map +0 -1
  115. package/dist/types/core/base/sync.d.ts.map +0 -1
  116. package/dist/types/core/constructors.d.ts.map +0 -1
  117. package/dist/types/core/cross/cross-parser.d.ts +0 -8
  118. package/dist/types/core/cross/cross-parser.d.ts.map +0 -1
  119. package/dist/types/core/cross/serialize.d.ts.map +0 -1
  120. package/dist/types/core/get-identifier.d.ts.map +0 -1
  121. package/dist/types/core/parser-context.d.ts +0 -23
  122. package/dist/types/core/parser-context.d.ts.map +0 -1
  123. package/dist/types/core/promise-to-result.d.ts.map +0 -1
  124. package/dist/types/core/serializer-context.old.d.ts.map +0 -1
  125. package/dist/types/core/shared.d.ts +0 -10
  126. package/dist/types/core/shared.d.ts.map +0 -1
  127. package/dist/types/core/tree/deserialize.d.ts.map +0 -1
  128. package/dist/types/core/tree/serialize.d.ts.map +0 -1
  129. package/src/core/cross/cross-parser.ts +0 -9
  130. package/src/core/parser-context.ts +0 -131
  131. package/src/core/serializer-context.new.ts +0 -1168
  132. package/src/core/tree/parser.ts +0 -45
  133. /package/dist/types/core/{assert.d.ts → utils/assert.d.ts} +0 -0
  134. /package/dist/types/core/{constructors.d.ts → utils/constructors.d.ts} +0 -0
  135. /package/dist/types/core/{get-identifier.d.ts → utils/get-identifier.d.ts} +0 -0
  136. /package/dist/types/core/{promise-to-result.d.ts → utils/promise-to-result.d.ts} +0 -0
  137. /package/src/core/{assert.ts → utils/assert.ts} +0 -0
  138. /package/src/core/{constructors.ts → utils/constructors.ts} +0 -0
  139. /package/src/core/{get-identifier.ts → utils/get-identifier.ts} +0 -0
  140. /package/src/core/{promise-to-result.ts → utils/promise-to-result.ts} +0 -0
@@ -1,39 +1,48 @@
1
1
  /* eslint-disable prefer-destructuring */
2
2
  /* eslint-disable no-await-in-loop */
3
- import type { BigIntTypedArrayValue, TypedArrayValue } from '../../types';
4
- import UnsupportedTypeError from '../UnsupportedTypeError';
5
- import assert from '../assert';
3
+ import type { BigIntTypedArrayValue, TypedArrayValue } from '../../../types';
4
+ import UnsupportedTypeError from '../../UnsupportedTypeError';
5
+ import assert from '../../utils/assert';
6
6
  import {
7
7
  createPluginNode,
8
8
  createDateNode,
9
9
  createRegExpNode,
10
10
  createArrayBufferNode,
11
- createWKSymbolNode,
12
11
  createBigIntNode,
13
12
  createStringNode,
14
13
  createNumberNode,
15
- } from '../base-primitives';
16
- import { BIGINT_FLAG, Feature } from '../compat';
17
- import type { WellKnownSymbols } from '../constants';
18
- import { SerovalNodeType, UNIVERSAL_SENTINEL } from '../constants';
14
+ createArrayNode,
15
+ createBoxedNode,
16
+ createTypedArrayNode,
17
+ createBigIntTypedArrayNode,
18
+ createDataViewNode,
19
+ createErrorNode,
20
+ createSetNode,
21
+ createAggregateErrorNode,
22
+ createIteratorFactoryInstanceNode,
23
+ createAsyncIteratorFactoryInstanceNode,
24
+ } from '../../base-primitives';
25
+ import { BIGINT_FLAG, Feature } from '../../compat';
26
+ import {
27
+ SerovalNodeType,
28
+ } from '../../constants';
19
29
  import {
20
30
  createRequestOptions,
21
31
  createResponseOptions,
22
32
  createEventOptions,
23
33
  createCustomEventOptions,
24
- } from '../constructors';
34
+ } from '../../utils/constructors';
25
35
  import {
26
36
  NULL_NODE,
27
37
  TRUE_NODE,
28
38
  FALSE_NODE,
29
39
  UNDEFINED_NODE,
30
- } from '../literals';
31
- import { BaseParserContext } from '../parser-context';
32
- import promiseToResult from '../promise-to-result';
33
- import { hasReferenceID } from '../reference';
34
- import { getErrorConstructor, getErrorOptions, getObjectFlag } from '../shared';
35
- import { serializeString } from '../string';
36
- import { SerovalObjectRecordSpecialKey } from '../types';
40
+ } from '../../literals';
41
+ import { asyncIteratorToSequence, iteratorToSequence, readableStreamToSequence } from '../../utils/iterator-to-sequence';
42
+ import { BaseParserContext } from '../parser';
43
+ import promiseToResult from '../../utils/promise-to-result';
44
+ import { getErrorOptions } from '../../utils/error';
45
+ import { serializeString } from '../../string';
37
46
  import type {
38
47
  SerovalErrorNode,
39
48
  SerovalArrayNode,
@@ -60,8 +69,17 @@ import type {
60
69
  SerovalResponseNode,
61
70
  SerovalSetNode,
62
71
  SerovalDataViewNode,
63
- } from '../types';
64
- import { createURLNode, createURLSearchParamsNode, createDOMExceptionNode } from '../web-api';
72
+ SerovalReadableStreamNode,
73
+ } from '../../types';
74
+ import {
75
+ createURLNode,
76
+ createURLSearchParamsNode,
77
+ createDOMExceptionNode,
78
+ createEventNode,
79
+ createCustomEventNode,
80
+ createReadableStreamNode,
81
+ } from '../../web-api';
82
+ import { UNIVERSAL_SENTINEL } from '../../special-reference';
65
83
 
66
84
  type ObjectLikeNode =
67
85
  | SerovalObjectNode
@@ -72,22 +90,10 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
72
90
  private async parseItems(
73
91
  current: unknown[],
74
92
  ): Promise<SerovalNode[]> {
75
- const size = current.length;
76
93
  const nodes = [];
77
- const deferred = [];
78
- for (let i = 0, item: unknown; i < size; i++) {
94
+ for (let i = 0, len = current.length; i < len; i++) {
79
95
  if (i in current) {
80
- item = current[i];
81
- if (this.isIterable(item)) {
82
- deferred[i] = item;
83
- } else {
84
- nodes[i] = await this.parse(item);
85
- }
86
- }
87
- }
88
- for (let i = 0; i < size; i++) {
89
- if (i in deferred) {
90
- nodes[i] = await this.parse(deferred[i]);
96
+ nodes[i] = await this.parse(current[i]);
91
97
  }
92
98
  }
93
99
  return nodes;
@@ -97,136 +103,66 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
97
103
  id: number,
98
104
  current: unknown[],
99
105
  ): Promise<SerovalArrayNode> {
100
- return {
101
- t: SerovalNodeType.Array,
102
- i: id,
103
- s: undefined,
104
- l: current.length,
105
- c: undefined,
106
- m: undefined,
107
- p: undefined,
108
- e: undefined,
109
- a: await this.parseItems(current),
110
- f: undefined,
111
- b: undefined,
112
- o: getObjectFlag(current),
113
- };
114
- }
115
-
116
- private async parseBoxed(
117
- id: number,
118
- current: object,
119
- ): Promise<SerovalBoxedNode> {
120
- return {
121
- t: SerovalNodeType.Boxed,
122
- i: id,
123
- s: undefined,
124
- l: undefined,
125
- c: undefined,
126
- m: undefined,
127
- p: undefined,
128
- e: undefined,
129
- a: undefined,
130
- f: await this.parse(current.valueOf()),
131
- b: undefined,
132
- o: undefined,
133
- };
134
- }
135
-
136
- private async parseTypedArray(
137
- id: number,
138
- current: TypedArrayValue,
139
- ): Promise<SerovalTypedArrayNode> {
140
- return {
141
- t: SerovalNodeType.TypedArray,
142
- i: id,
143
- s: undefined,
144
- l: current.length,
145
- c: current.constructor.name,
146
- m: undefined,
147
- p: undefined,
148
- e: undefined,
149
- a: undefined,
150
- f: await this.parse(current.buffer),
151
- b: current.byteOffset,
152
- o: undefined,
153
- };
154
- }
155
-
156
- private async parseBigIntTypedArray(
157
- id: number,
158
- current: BigIntTypedArrayValue,
159
- ): Promise<SerovalBigIntTypedArrayNode> {
160
- return {
161
- t: SerovalNodeType.BigIntTypedArray,
162
- i: id,
163
- s: undefined,
164
- l: current.length,
165
- c: current.constructor.name,
166
- m: undefined,
167
- p: undefined,
168
- e: undefined,
169
- a: undefined,
170
- f: await this.parse(current.buffer),
171
- b: current.byteOffset,
172
- o: undefined,
173
- };
174
- }
175
-
176
- private async parseDataView(
177
- id: number,
178
- current: DataView,
179
- ): Promise<SerovalDataViewNode> {
180
- return {
181
- t: SerovalNodeType.DataView,
182
- i: id,
183
- s: undefined,
184
- l: current.byteLength,
185
- c: undefined,
186
- m: undefined,
187
- p: undefined,
188
- e: undefined,
189
- a: undefined,
190
- f: await this.parse(current.buffer),
191
- b: current.byteOffset,
192
- o: undefined,
193
- };
106
+ return createArrayNode(
107
+ id,
108
+ current,
109
+ await this.parseItems(current),
110
+ );
194
111
  }
195
112
 
196
113
  private async parseProperties(
197
- properties: Record<string, unknown>,
114
+ properties: Record<string | symbol, unknown>,
198
115
  ): Promise<SerovalObjectRecordNode> {
199
116
  const entries = Object.entries(properties);
200
117
  const keyNodes: SerovalObjectRecordKey[] = [];
201
118
  const valueNodes: SerovalNode[] = [];
202
- const deferredKeys: string[] = [];
203
- const deferredValues: unknown[] = [];
204
119
  for (
205
- let i = 0, len = entries.length, key: string, item: unknown;
120
+ let i = 0, len = entries.length;
206
121
  i < len;
207
122
  i++
208
123
  ) {
209
- key = serializeString(entries[i][0]);
210
- item = entries[i][1];
211
- // Defer iterables since iterables have lazy evaluation.
212
- // Of course this doesn't include types seroval supports.
213
- if (this.isIterable(item)) {
214
- deferredKeys.push(key);
215
- deferredValues.push(item);
216
- } else {
217
- keyNodes.push(key);
218
- valueNodes.push(await this.parse(item));
219
- }
220
- }
221
- for (let i = 0, len = deferredKeys.length; i < len; i++) {
222
- keyNodes.push(deferredKeys[i]);
223
- valueNodes.push(await this.parse(deferredValues[i]));
124
+ keyNodes.push(serializeString(entries[i][0]));
125
+ valueNodes.push(await this.parse(entries[i][1]));
224
126
  }
225
127
  // Check special properties
226
128
  if (this.features & Feature.Symbol) {
227
- if (Symbol.iterator in properties) {
228
- keyNodes.push(SerovalObjectRecordSpecialKey.SymbolIterator);
229
- valueNodes.push(await this.parse(Array.from(properties as Iterable<unknown>)));
129
+ let symbol = Symbol.iterator;
130
+ if (symbol in properties) {
131
+ keyNodes.push(
132
+ this.parseWKSymbol(symbol),
133
+ );
134
+ valueNodes.push(
135
+ createIteratorFactoryInstanceNode(
136
+ this.parseIteratorFactory(),
137
+ await this.parse(
138
+ iteratorToSequence(properties as unknown as Iterable<unknown>),
139
+ ),
140
+ ),
141
+ );
142
+ }
143
+ symbol = Symbol.asyncIterator;
144
+ if (symbol in properties) {
145
+ keyNodes.push(
146
+ this.parseWKSymbol(symbol),
147
+ );
148
+ valueNodes.push(
149
+ createAsyncIteratorFactoryInstanceNode(
150
+ this.parseAsyncIteratorFactory(),
151
+ await this.parse(
152
+ await asyncIteratorToSequence(properties as unknown as AsyncIterable<unknown>),
153
+ ),
154
+ ),
155
+ );
156
+ }
157
+ symbol = Symbol.toStringTag;
158
+ if (symbol in properties) {
159
+ keyNodes.push(this.parseWKSymbol(symbol));
160
+ valueNodes.push(createStringNode(properties[symbol] as string));
161
+ }
162
+ symbol = Symbol.isConcatSpreadable;
163
+ if (symbol in properties) {
164
+ keyNodes.push(this.parseWKSymbol(symbol));
165
+ valueNodes.push(properties[symbol] ? TRUE_NODE : FALSE_NODE);
230
166
  }
231
167
  }
232
168
  return {
@@ -241,20 +177,40 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
241
177
  current: Record<string, unknown>,
242
178
  empty: boolean,
243
179
  ): Promise<ObjectLikeNode> {
244
- return {
245
- t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
246
- i: id,
247
- s: undefined,
248
- l: undefined,
249
- c: undefined,
250
- m: undefined,
251
- p: await this.parseProperties(current),
252
- e: undefined,
253
- a: undefined,
254
- f: undefined,
255
- b: undefined,
256
- o: getObjectFlag(current),
257
- };
180
+ return this.createObjectNode(
181
+ id,
182
+ current,
183
+ empty,
184
+ await this.parseProperties(current),
185
+ );
186
+ }
187
+
188
+ private async parseBoxed(
189
+ id: number,
190
+ current: object,
191
+ ): Promise<SerovalBoxedNode> {
192
+ return createBoxedNode(id, await this.parse(current.valueOf()));
193
+ }
194
+
195
+ private async parseTypedArray(
196
+ id: number,
197
+ current: TypedArrayValue,
198
+ ): Promise<SerovalTypedArrayNode> {
199
+ return createTypedArrayNode(id, current, await this.parse(current.buffer));
200
+ }
201
+
202
+ private async parseBigIntTypedArray(
203
+ id: number,
204
+ current: BigIntTypedArrayValue,
205
+ ): Promise<SerovalBigIntTypedArrayNode> {
206
+ return createBigIntTypedArrayNode(id, current, await this.parse(current.buffer));
207
+ }
208
+
209
+ private async parseDataView(
210
+ id: number,
211
+ current: DataView,
212
+ ): Promise<SerovalDataViewNode> {
213
+ return createDataViewNode(id, current, await this.parse(current.buffer));
258
214
  }
259
215
 
260
216
  private async parseError(
@@ -262,23 +218,27 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
262
218
  current: Error,
263
219
  ): Promise<SerovalErrorNode> {
264
220
  const options = getErrorOptions(current, this.features);
265
- const optionsNode = options
266
- ? await this.parseProperties(options)
267
- : undefined;
268
- return {
269
- t: SerovalNodeType.Error,
270
- i: id,
271
- s: getErrorConstructor(current),
272
- l: undefined,
273
- c: undefined,
274
- m: serializeString(current.message),
275
- p: optionsNode,
276
- e: undefined,
277
- a: undefined,
278
- f: undefined,
279
- b: undefined,
280
- o: undefined,
281
- };
221
+ return createErrorNode(
222
+ id,
223
+ current,
224
+ options
225
+ ? await this.parseProperties(options)
226
+ : undefined,
227
+ );
228
+ }
229
+
230
+ private async parseAggregateError(
231
+ id: number,
232
+ current: AggregateError,
233
+ ): Promise<SerovalAggregateErrorNode> {
234
+ const options = getErrorOptions(current, this.features);
235
+ return createAggregateErrorNode(
236
+ id,
237
+ current,
238
+ options
239
+ ? await this.parseProperties(options)
240
+ : undefined,
241
+ );
282
242
  }
283
243
 
284
244
  private async parseMap(
@@ -287,70 +247,27 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
287
247
  ): Promise<SerovalMapNode> {
288
248
  const keyNodes: SerovalNode[] = [];
289
249
  const valueNodes: SerovalNode[] = [];
290
- const deferredKey: unknown[] = [];
291
- const deferredValue: unknown[] = [];
292
250
  for (const [key, value] of current.entries()) {
293
- // Either key or value might be an iterable
294
- if (this.isIterable(key) || this.isIterable(value)) {
295
- deferredKey.push(key);
296
- deferredValue.push(value);
297
- } else {
298
- keyNodes.push(await this.parse(key));
299
- valueNodes.push(await this.parse(value));
300
- }
251
+ keyNodes.push(await this.parse(key));
252
+ valueNodes.push(await this.parse(value));
301
253
  }
302
- for (let i = 0, len = deferredKey.length; i < len; i++) {
303
- keyNodes.push(await this.parse(deferredKey[i]));
304
- valueNodes.push(await this.parse(deferredValue[i]));
305
- }
306
- return {
307
- t: SerovalNodeType.Map,
308
- i: id,
309
- s: undefined,
310
- l: undefined,
311
- c: undefined,
312
- m: undefined,
313
- p: undefined,
314
- e: { k: keyNodes, v: valueNodes, s: current.size },
315
- a: undefined,
316
- f: undefined,
317
- b: undefined,
318
- o: undefined,
319
- };
254
+ return this.createMapNode(
255
+ id,
256
+ keyNodes,
257
+ valueNodes,
258
+ current.size,
259
+ );
320
260
  }
321
261
 
322
262
  private async parseSet(
323
263
  id: number,
324
264
  current: Set<unknown>,
325
265
  ): Promise<SerovalSetNode> {
326
- const nodes: SerovalNode[] = [];
327
- const deferred: unknown[] = [];
266
+ const items: SerovalNode[] = [];
328
267
  for (const item of current.keys()) {
329
- // Iterables are lazy, so the evaluation must be deferred
330
- if (this.isIterable(item)) {
331
- deferred.push(item);
332
- } else {
333
- nodes.push(await this.parse(item));
334
- }
268
+ items.push(await this.parse(item));
335
269
  }
336
- // Parse deferred items
337
- for (let i = 0, len = deferred.length; i < len; i++) {
338
- nodes.push(await this.parse(deferred[i]));
339
- }
340
- return {
341
- t: SerovalNodeType.Set,
342
- i: id,
343
- s: undefined,
344
- l: current.size,
345
- c: undefined,
346
- m: undefined,
347
- p: undefined,
348
- e: undefined,
349
- a: nodes,
350
- f: undefined,
351
- b: undefined,
352
- o: undefined,
353
- };
270
+ return createSetNode(id, current.size, items);
354
271
  }
355
272
 
356
273
  private async parseBlob(
@@ -399,22 +316,9 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
399
316
  const size = entries.length;
400
317
  const keyNodes: string[] = [];
401
318
  const valueNodes: SerovalNode[] = [];
402
- const deferredKeys: string[] = [];
403
- const deferredValues: unknown[] = [];
404
- for (let i = 0, key: string, item: unknown; i < size; i++) {
405
- key = serializeString(entries[i][0]);
406
- item = entries[i][1];
407
- if (this.isIterable(item)) {
408
- deferredKeys.push(key);
409
- deferredValues.push(item);
410
- } else {
411
- keyNodes.push(key);
412
- valueNodes.push(await this.parse(item));
413
- }
414
- }
415
- for (let i = 0, len = deferredKeys.length; i < len; i++) {
416
- keyNodes.push(deferredKeys[i]);
417
- valueNodes.push(await this.parse(deferredValues[i]));
319
+ for (let i = 0; i < size; i++) {
320
+ keyNodes.push(serializeString(entries[i][0]));
321
+ valueNodes.push(await this.parse(entries[i][1]));
418
322
  }
419
323
  return {
420
324
  k: keyNodes,
@@ -522,64 +426,18 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
522
426
  id: number,
523
427
  current: Event,
524
428
  ): Promise<SerovalEventNode> {
525
- return {
526
- t: SerovalNodeType.Event,
527
- i: id,
528
- s: serializeString(current.type),
529
- l: undefined,
530
- c: undefined,
531
- m: undefined,
532
- p: undefined,
533
- e: undefined,
534
- a: undefined,
535
- f: await this.parse(createEventOptions(current)),
536
- b: undefined,
537
- o: undefined,
538
- };
429
+ return createEventNode(id, current.type, await this.parse(createEventOptions(current)));
539
430
  }
540
431
 
541
432
  private async parseCustomEvent(
542
433
  id: number,
543
434
  current: CustomEvent,
544
435
  ): Promise<SerovalCustomEventNode> {
545
- return {
546
- t: SerovalNodeType.CustomEvent,
547
- i: id,
548
- s: serializeString(current.type),
549
- l: undefined,
550
- c: undefined,
551
- m: undefined,
552
- p: undefined,
553
- e: undefined,
554
- a: undefined,
555
- f: await this.parse(createCustomEventOptions(current)),
556
- b: undefined,
557
- o: undefined,
558
- };
559
- }
560
-
561
- private async parseAggregateError(
562
- id: number,
563
- current: AggregateError,
564
- ): Promise<SerovalAggregateErrorNode> {
565
- const options = getErrorOptions(current, this.features);
566
- const optionsNode = options
567
- ? await this.parseProperties(options)
568
- : undefined;
569
- return {
570
- t: SerovalNodeType.AggregateError,
571
- i: id,
572
- s: undefined,
573
- l: undefined,
574
- c: undefined,
575
- m: serializeString(current.message),
576
- p: optionsNode,
577
- e: undefined,
578
- a: undefined,
579
- f: undefined,
580
- b: undefined,
581
- o: undefined,
582
- };
436
+ return createCustomEventNode(
437
+ id,
438
+ current.type,
439
+ await this.parse(createCustomEventOptions(current)),
440
+ );
583
441
  }
584
442
 
585
443
  private async parsePromise(
@@ -625,6 +483,19 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
625
483
  return undefined;
626
484
  }
627
485
 
486
+ private async parseReadableStream(
487
+ id: number,
488
+ current: ReadableStream,
489
+ ): Promise<SerovalReadableStreamNode> {
490
+ return createReadableStreamNode(
491
+ id,
492
+ this.parseReadableStreamFactory(),
493
+ await this.parse(
494
+ await readableStreamToSequence(current),
495
+ ),
496
+ );
497
+ }
498
+
628
499
  private async parseObject(
629
500
  id: number,
630
501
  current: object,
@@ -743,6 +614,8 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
743
614
  return this.parseCustomEvent(id, current as unknown as CustomEvent);
744
615
  case (typeof DOMException !== 'undefined' ? DOMException : UNIVERSAL_SENTINEL):
745
616
  return createDOMExceptionNode(id, current as unknown as DOMException);
617
+ case (typeof ReadableStream !== 'undefined' ? ReadableStream : UNIVERSAL_SENTINEL):
618
+ return this.parseReadableStream(id, current as unknown as ReadableStream);
746
619
  default:
747
620
  break;
748
621
  }
@@ -765,7 +638,10 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
765
638
  }
766
639
  // Generator functions don't have a global constructor
767
640
  // despite existing
768
- if (currentFeatures & Feature.Symbol && Symbol.iterator in current) {
641
+ if (
642
+ currentFeatures & Feature.Symbol
643
+ && (Symbol.iterator in current || Symbol.asyncIterator in current)
644
+ ) {
769
645
  return this.parsePlainObject(id, current, !!currentClass);
770
646
  }
771
647
  throw new UnsupportedTypeError(current);
@@ -789,14 +665,10 @@ export default abstract class BaseAsyncParserContext extends BaseParserContext {
789
665
  const id = this.getReference(current);
790
666
  return typeof id === 'number' ? this.parseObject(id, current as object) : id;
791
667
  }
792
- case 'symbol': {
793
- assert(this.features & Feature.Symbol, new UnsupportedTypeError(current));
794
- const id = this.getReference(current);
795
- return typeof id === 'number' ? createWKSymbolNode(id, current as WellKnownSymbols) : id;
796
- }
668
+ case 'symbol':
669
+ return this.parseWKSymbol(current);
797
670
  case 'function':
798
- assert(hasReferenceID(current), new Error('Cannot serialize function without reference ID.'));
799
- return this.getStrictReference(current);
671
+ return this.parseFunction(current);
800
672
  default:
801
673
  throw new UnsupportedTypeError(current);
802
674
  }