seroval 0.9.0 → 0.10.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 (90) hide show
  1. package/README.md +4 -287
  2. package/dist/cjs/development/index.cjs +3529 -1140
  3. package/dist/cjs/development/index.cjs.map +4 -4
  4. package/dist/cjs/production/index.cjs +3 -3
  5. package/dist/esm/development/index.mjs +3533 -1142
  6. package/dist/esm/development/index.mjs.map +4 -4
  7. package/dist/esm/production/index.mjs +3 -3
  8. package/dist/types/core/Serializer.d.ts +15 -0
  9. package/dist/types/{tree → core}/UnsupportedTypeError.d.ts +4 -3
  10. package/dist/types/{assert.d.ts → core/assert.d.ts} +1 -1
  11. package/dist/types/core/assignments.d.ts +33 -0
  12. package/dist/types/core/base-primitives.d.ts +12 -0
  13. package/dist/types/{compat.d.ts → core/compat.d.ts} +22 -22
  14. package/dist/types/core/constants.d.ts +89 -0
  15. package/dist/types/core/context.d.ts +9 -0
  16. package/dist/types/core/cross/async.d.ts +3 -0
  17. package/dist/types/core/cross/context.d.ts +37 -0
  18. package/dist/types/core/cross/index.d.ts +8 -0
  19. package/dist/types/core/cross/primitives.d.ts +9 -0
  20. package/dist/types/core/cross/serialize.d.ts +5 -0
  21. package/dist/types/core/cross/stream.d.ts +3 -0
  22. package/dist/types/core/cross/sync.d.ts +3 -0
  23. package/dist/types/core/cross/web-api.d.ts +4 -0
  24. package/dist/types/{get-identifier.d.ts → core/get-identifier.d.ts} +1 -1
  25. package/dist/types/core/keys.d.ts +13 -0
  26. package/dist/types/{tree/constants.d.ts → core/literals.d.ts} +9 -11
  27. package/dist/types/core/promise-to-result.d.ts +1 -0
  28. package/dist/types/{tree → core}/reference.d.ts +5 -6
  29. package/dist/types/{tree → core}/shared.d.ts +13 -13
  30. package/dist/types/{string.d.ts → core/string.d.ts} +3 -3
  31. package/dist/types/core/tree/async.d.ts +3 -0
  32. package/dist/types/core/tree/context.d.ts +44 -0
  33. package/dist/types/core/tree/deserialize.d.ts +3 -0
  34. package/dist/types/core/tree/index.d.ts +14 -0
  35. package/dist/types/core/tree/primitives.d.ts +9 -0
  36. package/dist/types/core/tree/serialize.d.ts +4 -0
  37. package/dist/types/core/tree/sync.d.ts +3 -0
  38. package/dist/types/core/tree/web-api.d.ts +4 -0
  39. package/dist/types/{tree → core}/types.d.ts +228 -238
  40. package/dist/types/core/web-api.d.ts +4 -0
  41. package/dist/types/index.d.ts +9 -19
  42. package/dist/types/types.d.ts +20 -20
  43. package/package.json +5 -5
  44. package/src/core/Serializer.ts +48 -0
  45. package/src/{tree → core}/UnsupportedTypeError.ts +1 -1
  46. package/src/core/assignments.ts +159 -0
  47. package/src/{tree/primitives.ts → core/base-primitives.ts} +33 -136
  48. package/src/core/constants.ts +169 -0
  49. package/src/core/context.ts +15 -0
  50. package/src/core/cross/async.ts +614 -0
  51. package/src/core/cross/context.ts +102 -0
  52. package/src/core/cross/index.ts +169 -0
  53. package/src/core/cross/primitives.ts +137 -0
  54. package/src/core/cross/serialize.ts +847 -0
  55. package/src/core/cross/stream.ts +745 -0
  56. package/src/core/cross/sync.ts +561 -0
  57. package/src/core/cross/web-api.ts +55 -0
  58. package/src/core/header.js +61 -0
  59. package/src/core/keys.ts +41 -0
  60. package/src/core/literals.ts +28 -0
  61. package/src/core/promise-to-result.ts +9 -0
  62. package/src/{tree → core}/reference.ts +6 -7
  63. package/src/{tree → core}/shared.ts +4 -4
  64. package/src/{tree → core/tree}/async.ts +46 -34
  65. package/src/core/tree/context.ts +125 -0
  66. package/src/{tree → core/tree}/deserialize.ts +68 -55
  67. package/src/core/tree/index.ts +142 -0
  68. package/src/core/tree/primitives.ts +132 -0
  69. package/src/{tree → core/tree}/serialize.ts +87 -193
  70. package/src/{tree → core/tree}/sync.ts +50 -39
  71. package/src/{tree → core/tree}/web-api.ts +8 -52
  72. package/src/{tree → core}/types.ts +76 -60
  73. package/src/core/web-api.ts +51 -0
  74. package/src/index.ts +7 -141
  75. package/src/types.ts +1 -1
  76. package/dist/types/context.d.ts +0 -67
  77. package/dist/types/tree/async.d.ts +0 -3
  78. package/dist/types/tree/deserialize.d.ts +0 -3
  79. package/dist/types/tree/primitives.d.ts +0 -19
  80. package/dist/types/tree/serialize.d.ts +0 -4
  81. package/dist/types/tree/symbols.d.ts +0 -33
  82. package/dist/types/tree/sync.d.ts +0 -3
  83. package/dist/types/tree/web-api.d.ts +0 -6
  84. package/src/context.ts +0 -164
  85. package/src/tree/constants.ts +0 -73
  86. package/src/tree/symbols.ts +0 -65
  87. /package/src/{assert.ts → core/assert.ts} +0 -0
  88. /package/src/{compat.ts → core/compat.ts} +0 -0
  89. /package/src/{get-identifier.ts → core/get-identifier.ts} +0 -0
  90. /package/src/{string.ts → core/string.ts} +0 -0
@@ -0,0 +1,745 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ /* eslint-disable @typescript-eslint/no-use-before-define */
3
+ import assert from '../assert';
4
+ import { Feature } from '../compat';
5
+ import type { StreamingCrossParserContext } from './context';
6
+ import {
7
+ createCrossIndexedValue, popPendingState, pushPendingState,
8
+ } from './context';
9
+ import { serializeString } from '../string';
10
+ import type {
11
+ BigIntTypedArrayValue,
12
+ TypedArrayValue,
13
+ } from '../../types';
14
+ import UnsupportedTypeError from '../UnsupportedTypeError';
15
+ import {
16
+ TRUE_NODE,
17
+ FALSE_NODE,
18
+ UNDEFINED_NODE,
19
+ NULL_NODE,
20
+ } from '../literals';
21
+ import {
22
+ createBigIntTypedArrayNode,
23
+ createTypedArrayNode,
24
+ createDataViewNode,
25
+ createSymbolNode,
26
+ createFunctionNode,
27
+ } from './primitives';
28
+ import { hasReferenceID } from '../reference';
29
+ import {
30
+ getErrorConstructorName,
31
+ getErrorOptions,
32
+ getObjectFlag,
33
+ isIterable,
34
+ } from '../shared';
35
+ import type {
36
+ SerovalAggregateErrorNode,
37
+ SerovalArrayNode,
38
+ SerovalBoxedNode,
39
+ SerovalErrorNode,
40
+ SerovalFormDataNode,
41
+ SerovalHeadersNode,
42
+ SerovalMapNode,
43
+ SerovalNode,
44
+ SerovalNullConstructorNode,
45
+ SerovalObjectNode,
46
+ SerovalObjectRecordKey,
47
+ SerovalObjectRecordNode,
48
+ SerovalPlainRecordNode,
49
+ SerovalPromiseNode,
50
+ SerovalPromiseConstructorNode,
51
+ SerovalSetNode,
52
+ SerovalReadableStreamConstructorNode,
53
+ } from '../types';
54
+ import {
55
+ SerovalObjectRecordSpecialKey,
56
+ } from '../types';
57
+ // import {
58
+ // createBlobNode,
59
+ // createFileNode,
60
+ // } from './web-api';
61
+ import { SerovalNodeType } from '../constants';
62
+ import {
63
+ createArrayBufferNode,
64
+ createBigIntNode,
65
+ createDateNode,
66
+ createIndexedValueNode,
67
+ createNumberNode,
68
+ createReferenceNode,
69
+ createRegExpNode,
70
+ createStringNode,
71
+ } from '../base-primitives';
72
+ import { createURLNode, createURLSearchParamsNode } from '../web-api';
73
+
74
+ type ObjectLikeNode =
75
+ | SerovalObjectNode
76
+ | SerovalNullConstructorNode
77
+ | SerovalPromiseNode;
78
+
79
+ function generateNodeList(
80
+ ctx: StreamingCrossParserContext,
81
+ current: unknown[],
82
+ ): SerovalNode[] {
83
+ const size = current.length;
84
+ const nodes = new Array<SerovalNode>(size);
85
+ const deferred = new Array<unknown>(size);
86
+ let item: unknown;
87
+ for (let i = 0; i < size; i++) {
88
+ if (i in current) {
89
+ item = current[i];
90
+ if (isIterable(item)) {
91
+ deferred[i] = item;
92
+ } else {
93
+ nodes[i] = crossParseStream(ctx, item);
94
+ }
95
+ }
96
+ }
97
+ for (let i = 0; i < size; i++) {
98
+ if (i in deferred) {
99
+ nodes[i] = crossParseStream(ctx, deferred[i]);
100
+ }
101
+ }
102
+ return nodes;
103
+ }
104
+
105
+ function generateArrayNode(
106
+ ctx: StreamingCrossParserContext,
107
+ id: number,
108
+ current: unknown[],
109
+ ): SerovalArrayNode {
110
+ return {
111
+ t: SerovalNodeType.Array,
112
+ i: id,
113
+ s: undefined,
114
+ l: current.length,
115
+ c: undefined,
116
+ m: undefined,
117
+ p: undefined,
118
+ e: undefined,
119
+ a: generateNodeList(ctx, current),
120
+ f: undefined,
121
+ b: undefined,
122
+ o: getObjectFlag(current),
123
+ };
124
+ }
125
+
126
+ function generateMapNode(
127
+ ctx: StreamingCrossParserContext,
128
+ id: number,
129
+ current: Map<unknown, unknown>,
130
+ ): SerovalMapNode {
131
+ assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
132
+ const len = current.size;
133
+ const keyNodes = new Array<SerovalNode>(len);
134
+ const valueNodes = new Array<SerovalNode>(len);
135
+ const deferredKey = new Array<unknown>(len);
136
+ const deferredValue = new Array<unknown>(len);
137
+ let deferredSize = 0;
138
+ let nodeSize = 0;
139
+ for (const [key, value] of current.entries()) {
140
+ // Either key or value might be an iterable
141
+ if (isIterable(key) || isIterable(value)) {
142
+ deferredKey[deferredSize] = key;
143
+ deferredValue[deferredSize] = value;
144
+ deferredSize++;
145
+ } else {
146
+ keyNodes[nodeSize] = crossParseStream(ctx, key);
147
+ valueNodes[nodeSize] = crossParseStream(ctx, value);
148
+ nodeSize++;
149
+ }
150
+ }
151
+ for (let i = 0; i < deferredSize; i++) {
152
+ keyNodes[nodeSize + i] = crossParseStream(ctx, deferredKey[i]);
153
+ valueNodes[nodeSize + i] = crossParseStream(ctx, deferredValue[i]);
154
+ }
155
+ return {
156
+ t: SerovalNodeType.Map,
157
+ i: id,
158
+ s: undefined,
159
+ l: undefined,
160
+ c: undefined,
161
+ m: undefined,
162
+ p: undefined,
163
+ e: { k: keyNodes, v: valueNodes, s: len },
164
+ a: undefined,
165
+ f: undefined,
166
+ b: undefined,
167
+ o: undefined,
168
+ };
169
+ }
170
+
171
+ function generateSetNode(
172
+ ctx: StreamingCrossParserContext,
173
+ id: number,
174
+ current: Set<unknown>,
175
+ ): SerovalSetNode {
176
+ assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
177
+ const len = current.size;
178
+ const nodes = new Array<SerovalNode>(len);
179
+ const deferred = new Array<unknown>(len);
180
+ let deferredSize = 0;
181
+ let nodeSize = 0;
182
+ for (const item of current.keys()) {
183
+ // Iterables are lazy, so the evaluation must be deferred
184
+ if (isIterable(item)) {
185
+ deferred[deferredSize++] = item;
186
+ } else {
187
+ nodes[nodeSize++] = crossParseStream(ctx, item);
188
+ }
189
+ }
190
+ // Parse deferred items
191
+ for (let i = 0; i < deferredSize; i++) {
192
+ nodes[nodeSize + i] = crossParseStream(ctx, deferred[i]);
193
+ }
194
+ return {
195
+ t: SerovalNodeType.Set,
196
+ i: id,
197
+ s: undefined,
198
+ l: len,
199
+ c: undefined,
200
+ m: undefined,
201
+ p: undefined,
202
+ e: undefined,
203
+ a: nodes,
204
+ f: undefined,
205
+ b: undefined,
206
+ o: undefined,
207
+ };
208
+ }
209
+
210
+ function generateProperties(
211
+ ctx: StreamingCrossParserContext,
212
+ properties: Record<string, unknown>,
213
+ ): SerovalObjectRecordNode {
214
+ const keys = Object.keys(properties);
215
+ let size = keys.length;
216
+ const keyNodes = new Array<SerovalObjectRecordKey>(size);
217
+ const valueNodes = new Array<SerovalNode>(size);
218
+ const deferredKeys = new Array<SerovalObjectRecordKey>(size);
219
+ const deferredValues = new Array<unknown>(size);
220
+ let deferredSize = 0;
221
+ let nodesSize = 0;
222
+ let item: unknown;
223
+ let escaped: SerovalObjectRecordKey;
224
+ for (const key of keys) {
225
+ item = properties[key];
226
+ escaped = serializeString(key);
227
+ if (isIterable(item)) {
228
+ deferredKeys[deferredSize] = escaped;
229
+ deferredValues[deferredSize] = item;
230
+ deferredSize++;
231
+ } else {
232
+ keyNodes[nodesSize] = escaped;
233
+ valueNodes[nodesSize] = crossParseStream(ctx, item);
234
+ nodesSize++;
235
+ }
236
+ }
237
+ for (let i = 0; i < deferredSize; i++) {
238
+ keyNodes[nodesSize + i] = deferredKeys[i];
239
+ valueNodes[nodesSize + i] = crossParseStream(ctx, deferredValues[i]);
240
+ }
241
+ if (ctx.features & Feature.Symbol) {
242
+ if (Symbol.iterator in properties) {
243
+ keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
244
+ const items = Array.from(properties as Iterable<unknown>);
245
+ valueNodes[size] = generateArrayNode(
246
+ ctx,
247
+ createCrossIndexedValue(ctx, items),
248
+ items,
249
+ );
250
+ size++;
251
+ }
252
+ }
253
+ return {
254
+ k: keyNodes,
255
+ v: valueNodes,
256
+ s: size,
257
+ };
258
+ }
259
+
260
+ function generatePlainProperties(
261
+ ctx: StreamingCrossParserContext,
262
+ properties: Record<string, unknown>,
263
+ ): SerovalPlainRecordNode {
264
+ const keys = Object.keys(properties);
265
+ const size = keys.length;
266
+ const keyNodes = new Array<string>(size);
267
+ const valueNodes = new Array<SerovalNode>(size);
268
+ const deferredKeys = new Array<string>(size);
269
+ const deferredValues = new Array<unknown>(size);
270
+ let deferredSize = 0;
271
+ let nodesSize = 0;
272
+ let item: unknown;
273
+ let escaped: string;
274
+ for (const key of keys) {
275
+ item = properties[key];
276
+ escaped = serializeString(key);
277
+ if (isIterable(item)) {
278
+ deferredKeys[deferredSize] = escaped;
279
+ deferredValues[deferredSize] = item;
280
+ deferredSize++;
281
+ } else {
282
+ keyNodes[nodesSize] = escaped;
283
+ valueNodes[nodesSize] = crossParseStream(ctx, item);
284
+ nodesSize++;
285
+ }
286
+ }
287
+ for (let i = 0; i < deferredSize; i++) {
288
+ keyNodes[nodesSize + i] = deferredKeys[i];
289
+ valueNodes[nodesSize + i] = crossParseStream(ctx, deferredValues[i]);
290
+ }
291
+ return {
292
+ k: keyNodes,
293
+ v: valueNodes,
294
+ s: size,
295
+ };
296
+ }
297
+
298
+ function generatePromiseNode(
299
+ ctx: StreamingCrossParserContext,
300
+ id: number,
301
+ current: Promise<unknown>,
302
+ ): SerovalPromiseConstructorNode {
303
+ assert(ctx.features & Feature.Promise, new UnsupportedTypeError(current));
304
+ current.then(
305
+ (data) => {
306
+ if (ctx.alive) {
307
+ ctx.onParse({
308
+ t: SerovalNodeType.PromiseResolve,
309
+ i: id,
310
+ s: undefined,
311
+ l: undefined,
312
+ c: undefined,
313
+ m: undefined,
314
+ p: undefined,
315
+ e: undefined,
316
+ a: undefined,
317
+ f: crossParseStream(ctx, data),
318
+ b: undefined,
319
+ o: undefined,
320
+ }, false);
321
+ popPendingState(ctx);
322
+ }
323
+ },
324
+ (data) => {
325
+ if (ctx.alive) {
326
+ ctx.onParse({
327
+ t: SerovalNodeType.PromiseReject,
328
+ i: id,
329
+ s: undefined,
330
+ l: undefined,
331
+ c: undefined,
332
+ m: undefined,
333
+ p: undefined,
334
+ e: undefined,
335
+ a: undefined,
336
+ f: crossParseStream(ctx, data),
337
+ b: undefined,
338
+ o: undefined,
339
+ }, false);
340
+ popPendingState(ctx);
341
+ }
342
+ },
343
+ );
344
+ pushPendingState(ctx);
345
+ return {
346
+ t: SerovalNodeType.PromiseConstructor,
347
+ i: id,
348
+ s: undefined,
349
+ l: undefined,
350
+ c: undefined,
351
+ m: undefined,
352
+ p: undefined,
353
+ e: undefined,
354
+ a: undefined,
355
+ f: undefined,
356
+ b: undefined,
357
+ o: undefined,
358
+ };
359
+ }
360
+
361
+ function generateObjectNode(
362
+ ctx: StreamingCrossParserContext,
363
+ id: number,
364
+ current: Record<string, unknown>,
365
+ empty: boolean,
366
+ ): ObjectLikeNode {
367
+ return {
368
+ t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
369
+ i: id,
370
+ s: undefined,
371
+ l: undefined,
372
+ c: undefined,
373
+ m: undefined,
374
+ p: generateProperties(ctx, current),
375
+ e: undefined,
376
+ a: undefined,
377
+ f: undefined,
378
+ b: undefined,
379
+ o: getObjectFlag(current),
380
+ };
381
+ }
382
+
383
+ function generateAggregateErrorNode(
384
+ ctx: StreamingCrossParserContext,
385
+ id: number,
386
+ current: AggregateError,
387
+ ): SerovalAggregateErrorNode {
388
+ const options = getErrorOptions(ctx, current);
389
+ const optionsNode = options
390
+ ? generateProperties(ctx, options)
391
+ : undefined;
392
+ return {
393
+ t: SerovalNodeType.AggregateError,
394
+ i: id,
395
+ s: undefined,
396
+ l: undefined,
397
+ c: undefined,
398
+ m: serializeString(current.message),
399
+ p: optionsNode,
400
+ e: undefined,
401
+ a: undefined,
402
+ f: undefined,
403
+ b: undefined,
404
+ o: undefined,
405
+ };
406
+ }
407
+
408
+ function generateErrorNode(
409
+ ctx: StreamingCrossParserContext,
410
+ id: number,
411
+ current: Error,
412
+ ): SerovalErrorNode {
413
+ const options = getErrorOptions(ctx, current);
414
+ const optionsNode = options
415
+ ? generateProperties(ctx, options)
416
+ : undefined;
417
+ return {
418
+ t: SerovalNodeType.Error,
419
+ i: id,
420
+ s: undefined,
421
+ l: undefined,
422
+ c: getErrorConstructorName(current),
423
+ m: serializeString(current.message),
424
+ p: optionsNode,
425
+ e: undefined,
426
+ a: undefined,
427
+ f: undefined,
428
+ b: undefined,
429
+ o: undefined,
430
+ };
431
+ }
432
+
433
+ function generateHeadersNode(
434
+ ctx: StreamingCrossParserContext,
435
+ id: number,
436
+ current: Headers,
437
+ ): SerovalHeadersNode {
438
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
439
+ const items: Record<string, string> = {};
440
+ current.forEach((value, key) => {
441
+ items[key] = value;
442
+ });
443
+ return {
444
+ t: SerovalNodeType.Headers,
445
+ i: id,
446
+ s: undefined,
447
+ l: undefined,
448
+ c: undefined,
449
+ m: undefined,
450
+ p: undefined,
451
+ e: generatePlainProperties(ctx, items),
452
+ a: undefined,
453
+ f: undefined,
454
+ b: undefined,
455
+ o: undefined,
456
+ };
457
+ }
458
+
459
+ function generateFormDataNode(
460
+ ctx: StreamingCrossParserContext,
461
+ id: number,
462
+ current: FormData,
463
+ ): SerovalFormDataNode {
464
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
465
+ const items: Record<string, FormDataEntryValue> = {};
466
+ current.forEach((value, key) => {
467
+ items[key] = value;
468
+ });
469
+ return {
470
+ t: SerovalNodeType.FormData,
471
+ i: id,
472
+ s: undefined,
473
+ l: undefined,
474
+ c: undefined,
475
+ m: undefined,
476
+ p: undefined,
477
+ e: generatePlainProperties(ctx, items),
478
+ a: undefined,
479
+ f: undefined,
480
+ b: undefined,
481
+ o: undefined,
482
+ };
483
+ }
484
+
485
+ function generateBoxedNode(
486
+ ctx: StreamingCrossParserContext,
487
+ id: number,
488
+ current: object,
489
+ ): SerovalBoxedNode {
490
+ return {
491
+ t: SerovalNodeType.Boxed,
492
+ i: id,
493
+ s: undefined,
494
+ l: undefined,
495
+ c: undefined,
496
+ m: undefined,
497
+ p: undefined,
498
+ e: undefined,
499
+ a: undefined,
500
+ f: crossParseStream(ctx, current.valueOf()),
501
+ b: undefined,
502
+ o: undefined,
503
+ };
504
+ }
505
+
506
+ function generateReadableStreamNode(
507
+ ctx: StreamingCrossParserContext,
508
+ id: number,
509
+ current: ReadableStream<unknown>,
510
+ ): SerovalReadableStreamConstructorNode {
511
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
512
+ const reader = current.getReader();
513
+ pushPendingState(ctx);
514
+
515
+ function push(): void {
516
+ reader.read().then(
517
+ (data) => {
518
+ if (ctx.alive) {
519
+ if (data.done) {
520
+ ctx.onParse({
521
+ t: SerovalNodeType.ReadableStreamClose,
522
+ i: id,
523
+ s: undefined,
524
+ l: undefined,
525
+ c: undefined,
526
+ m: undefined,
527
+ p: undefined,
528
+ e: undefined,
529
+ a: undefined,
530
+ f: undefined,
531
+ b: undefined,
532
+ o: undefined,
533
+ }, false);
534
+ popPendingState(ctx);
535
+ } else {
536
+ ctx.onParse({
537
+ t: SerovalNodeType.ReadableStreamEnqueue,
538
+ i: id,
539
+ s: undefined,
540
+ l: undefined,
541
+ c: undefined,
542
+ m: undefined,
543
+ p: undefined,
544
+ e: undefined,
545
+ a: undefined,
546
+ f: crossParseStream(ctx, data.value),
547
+ b: undefined,
548
+ o: undefined,
549
+ }, false);
550
+ push();
551
+ }
552
+ }
553
+ },
554
+ (value) => {
555
+ if (ctx.alive) {
556
+ ctx.onParse({
557
+ t: SerovalNodeType.ReadableStreamError,
558
+ i: id,
559
+ s: undefined,
560
+ l: undefined,
561
+ c: undefined,
562
+ m: undefined,
563
+ p: undefined,
564
+ e: undefined,
565
+ a: undefined,
566
+ f: crossParseStream(ctx, value),
567
+ b: undefined,
568
+ o: undefined,
569
+ }, false);
570
+ popPendingState(ctx);
571
+ }
572
+ },
573
+ );
574
+ }
575
+
576
+ push();
577
+
578
+ return {
579
+ t: SerovalNodeType.ReadableStreamConstructor,
580
+ i: id,
581
+ s: undefined,
582
+ l: undefined,
583
+ c: undefined,
584
+ m: undefined,
585
+ p: undefined,
586
+ e: undefined,
587
+ a: undefined,
588
+ f: undefined,
589
+ b: undefined,
590
+ o: undefined,
591
+ };
592
+ }
593
+
594
+ function parseObject(
595
+ ctx: StreamingCrossParserContext,
596
+ current: object | null,
597
+ ): SerovalNode {
598
+ if (!current) {
599
+ return NULL_NODE;
600
+ }
601
+ // Non-primitive values needs a reference ID
602
+ // mostly because the values themselves are stateful
603
+ const registeredID = ctx.refs.get(current);
604
+ if (registeredID != null) {
605
+ return createIndexedValueNode(registeredID);
606
+ }
607
+ const id = ctx.refs.size;
608
+ ctx.refs.set(current, id);
609
+ if (hasReferenceID(current)) {
610
+ return createReferenceNode(id, current);
611
+ }
612
+ if (Array.isArray(current)) {
613
+ return generateArrayNode(ctx, id, current);
614
+ }
615
+ switch (current.constructor) {
616
+ case Number:
617
+ case Boolean:
618
+ case String:
619
+ case BigInt:
620
+ case Function:
621
+ case Symbol:
622
+ return generateBoxedNode(ctx, id, current);
623
+ case Date:
624
+ return createDateNode(id, current as unknown as Date);
625
+ case RegExp:
626
+ return createRegExpNode(id, current as unknown as RegExp);
627
+ case Promise:
628
+ return generatePromiseNode(ctx, id, current as unknown as Promise<unknown>);
629
+ case ArrayBuffer:
630
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
631
+ case Int8Array:
632
+ case Int16Array:
633
+ case Int32Array:
634
+ case Uint8Array:
635
+ case Uint16Array:
636
+ case Uint32Array:
637
+ case Uint8ClampedArray:
638
+ case Float32Array:
639
+ case Float64Array:
640
+ return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
641
+ case BigInt64Array:
642
+ case BigUint64Array:
643
+ return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
644
+ case DataView:
645
+ return createDataViewNode(ctx, id, current as unknown as DataView);
646
+ case Map:
647
+ return generateMapNode(
648
+ ctx,
649
+ id,
650
+ current as unknown as Map<unknown, unknown>,
651
+ );
652
+ case Set:
653
+ return generateSetNode(
654
+ ctx,
655
+ id,
656
+ current as unknown as Set<unknown>,
657
+ );
658
+ case Object:
659
+ return generateObjectNode(
660
+ ctx,
661
+ id,
662
+ current as Record<string, unknown>,
663
+ false,
664
+ );
665
+ case undefined:
666
+ return generateObjectNode(
667
+ ctx,
668
+ id,
669
+ current as Record<string, unknown>,
670
+ true,
671
+ );
672
+ case AggregateError:
673
+ if (ctx.features & Feature.AggregateError) {
674
+ return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
675
+ }
676
+ return generateErrorNode(ctx, id, current as unknown as AggregateError);
677
+ case Error:
678
+ case EvalError:
679
+ case RangeError:
680
+ case ReferenceError:
681
+ case SyntaxError:
682
+ case TypeError:
683
+ case URIError:
684
+ return generateErrorNode(ctx, id, current as unknown as Error);
685
+ case URL:
686
+ return createURLNode(ctx, id, current as unknown as URL);
687
+ case URLSearchParams:
688
+ return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
689
+ // case Blob:
690
+ // return createBlobNode(ctx, id, current as unknown as Blob);
691
+ // case File:
692
+ // return createFileNode(ctx, id, current as unknown as File);
693
+ case Headers:
694
+ return generateHeadersNode(ctx, id, current as unknown as Headers);
695
+ case FormData:
696
+ return generateFormDataNode(ctx, id, current as unknown as FormData);
697
+ case ReadableStream:
698
+ return generateReadableStreamNode(ctx, id, current as unknown as ReadableStream);
699
+ default:
700
+ break;
701
+ }
702
+ if (current instanceof AggregateError) {
703
+ if (ctx.features & Feature.AggregateError) {
704
+ return generateAggregateErrorNode(ctx, id, current);
705
+ }
706
+ return generateErrorNode(ctx, id, current);
707
+ }
708
+ if (current instanceof Error) {
709
+ return generateErrorNode(ctx, id, current);
710
+ }
711
+ if (current instanceof Promise) {
712
+ return generatePromiseNode(ctx, id, current);
713
+ }
714
+ // Generator functions don't have a global constructor
715
+ if (Symbol.iterator in current) {
716
+ return generateObjectNode(ctx, id, current, !!current.constructor);
717
+ }
718
+ throw new UnsupportedTypeError(current);
719
+ }
720
+
721
+ export default function crossParseStream<T>(
722
+ ctx: StreamingCrossParserContext,
723
+ current: T,
724
+ ): SerovalNode {
725
+ switch (typeof current) {
726
+ case 'boolean':
727
+ return current ? TRUE_NODE : FALSE_NODE;
728
+ case 'undefined':
729
+ return UNDEFINED_NODE;
730
+ case 'string':
731
+ return createStringNode(current);
732
+ case 'number':
733
+ return createNumberNode(current);
734
+ case 'bigint':
735
+ return createBigIntNode(ctx, current);
736
+ case 'object':
737
+ return parseObject(ctx, current);
738
+ case 'symbol':
739
+ return createSymbolNode(ctx, current);
740
+ case 'function':
741
+ return createFunctionNode(ctx, current);
742
+ default:
743
+ throw new UnsupportedTypeError(current);
744
+ }
745
+ }