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,561 @@
1
+ /* eslint-disable @typescript-eslint/no-use-before-define */
2
+ import assert from '../assert';
3
+ import { Feature } from '../compat';
4
+ import { createCrossIndexedValue, type CrossParserContext } from './context';
5
+ import { serializeString } from '../string';
6
+ import type { BigIntTypedArrayValue, TypedArrayValue } from '../../types';
7
+ import UnsupportedTypeError from '../UnsupportedTypeError';
8
+ import {
9
+ TRUE_NODE,
10
+ FALSE_NODE,
11
+ UNDEFINED_NODE,
12
+ NULL_NODE,
13
+ } from '../literals';
14
+ import {
15
+ createBigIntTypedArrayNode,
16
+ createTypedArrayNode,
17
+ createDataViewNode,
18
+ createSymbolNode,
19
+ createFunctionNode,
20
+ } from './primitives';
21
+ import {
22
+ hasReferenceID,
23
+ } from '../reference';
24
+ import {
25
+ getErrorConstructorName,
26
+ getErrorOptions,
27
+ getObjectFlag,
28
+ isIterable,
29
+ } from '../shared';
30
+ import type {
31
+ SerovalAggregateErrorNode,
32
+ SerovalArrayNode,
33
+ SerovalBoxedNode,
34
+ SerovalErrorNode,
35
+ SerovalFormDataNode,
36
+ SerovalHeadersNode,
37
+ SerovalMapNode,
38
+ SerovalNullConstructorNode,
39
+ SerovalObjectNode,
40
+ SerovalObjectRecordKey,
41
+ SerovalObjectRecordNode,
42
+ SerovalPlainRecordNode,
43
+ SerovalSetNode,
44
+ SerovalSyncNode,
45
+ } from '../types';
46
+ import {
47
+ SerovalObjectRecordSpecialKey,
48
+ } from '../types';
49
+ import { SerovalNodeType } from '../constants';
50
+ import {
51
+ createArrayBufferNode,
52
+ createBigIntNode,
53
+ createDateNode,
54
+ createIndexedValueNode,
55
+ createNumberNode,
56
+ createReferenceNode,
57
+ createRegExpNode,
58
+ createStringNode,
59
+ } from '../base-primitives';
60
+ import { createURLNode, createURLSearchParamsNode } from '../web-api';
61
+
62
+ type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
63
+
64
+ function generateNodeList(ctx: CrossParserContext, current: unknown[]): SerovalSyncNode[] {
65
+ const size = current.length;
66
+ const nodes = new Array<SerovalSyncNode>(size);
67
+ const deferred = new Array<unknown>(size);
68
+ let item: unknown;
69
+ for (let i = 0; i < size; i++) {
70
+ if (i in current) {
71
+ item = current[i];
72
+ if (isIterable(item)) {
73
+ deferred[i] = item;
74
+ } else {
75
+ nodes[i] = crossParseSync(ctx, item);
76
+ }
77
+ }
78
+ }
79
+ for (let i = 0; i < size; i++) {
80
+ if (i in deferred) {
81
+ nodes[i] = crossParseSync(ctx, deferred[i]);
82
+ }
83
+ }
84
+ return nodes;
85
+ }
86
+
87
+ function generateArrayNode(
88
+ ctx: CrossParserContext,
89
+ id: number,
90
+ current: unknown[],
91
+ ): SerovalArrayNode {
92
+ return {
93
+ t: SerovalNodeType.Array,
94
+ i: id,
95
+ s: undefined,
96
+ l: current.length,
97
+ c: undefined,
98
+ m: undefined,
99
+ p: undefined,
100
+ e: undefined,
101
+ a: generateNodeList(ctx, current),
102
+ f: undefined,
103
+ b: undefined,
104
+ o: getObjectFlag(current),
105
+ };
106
+ }
107
+
108
+ function generateMapNode(
109
+ ctx: CrossParserContext,
110
+ id: number,
111
+ current: Map<unknown, unknown>,
112
+ ): SerovalMapNode {
113
+ assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
114
+ const len = current.size;
115
+ const keyNodes = new Array<SerovalSyncNode>(len);
116
+ const valueNodes = new Array<SerovalSyncNode>(len);
117
+ const deferredKey = new Array<unknown>(len);
118
+ const deferredValue = new Array<unknown>(len);
119
+ let deferredSize = 0;
120
+ let nodeSize = 0;
121
+ for (const [key, value] of current.entries()) {
122
+ // Either key or value might be an iterable
123
+ if (isIterable(key) || isIterable(value)) {
124
+ deferredKey[deferredSize] = key;
125
+ deferredValue[deferredSize] = value;
126
+ deferredSize++;
127
+ } else {
128
+ keyNodes[nodeSize] = crossParseSync(ctx, key);
129
+ valueNodes[nodeSize] = crossParseSync(ctx, value);
130
+ nodeSize++;
131
+ }
132
+ }
133
+ for (let i = 0; i < deferredSize; i++) {
134
+ keyNodes[nodeSize + i] = crossParseSync(ctx, deferredKey[i]);
135
+ valueNodes[nodeSize + i] = crossParseSync(ctx, deferredValue[i]);
136
+ }
137
+ return {
138
+ t: SerovalNodeType.Map,
139
+ i: id,
140
+ s: undefined,
141
+ l: undefined,
142
+ c: undefined,
143
+ m: undefined,
144
+ p: undefined,
145
+ e: { k: keyNodes, v: valueNodes, s: len },
146
+ a: undefined,
147
+ f: undefined,
148
+ b: undefined,
149
+ o: undefined,
150
+ };
151
+ }
152
+
153
+ function generateSetNode(
154
+ ctx: CrossParserContext,
155
+ id: number,
156
+ current: Set<unknown>,
157
+ ): SerovalSetNode {
158
+ assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
159
+ const len = current.size;
160
+ const nodes = new Array<SerovalSyncNode>(len);
161
+ const deferred = new Array<unknown>(len);
162
+ let deferredSize = 0;
163
+ let nodeSize = 0;
164
+ for (const item of current.keys()) {
165
+ // Iterables are lazy, so the evaluation must be deferred
166
+ if (isIterable(item)) {
167
+ deferred[deferredSize++] = item;
168
+ } else {
169
+ nodes[nodeSize++] = crossParseSync(ctx, item);
170
+ }
171
+ }
172
+ // Parse deferred items
173
+ for (let i = 0; i < deferredSize; i++) {
174
+ nodes[nodeSize + i] = crossParseSync(ctx, deferred[i]);
175
+ }
176
+ return {
177
+ t: SerovalNodeType.Set,
178
+ i: id,
179
+ s: undefined,
180
+ l: len,
181
+ c: undefined,
182
+ m: undefined,
183
+ p: undefined,
184
+ e: undefined,
185
+ a: nodes,
186
+ f: undefined,
187
+ b: undefined,
188
+ o: undefined,
189
+ };
190
+ }
191
+
192
+ function generateProperties(
193
+ ctx: CrossParserContext,
194
+ properties: Record<string, unknown>,
195
+ ): SerovalObjectRecordNode {
196
+ const keys = Object.keys(properties);
197
+ let size = keys.length;
198
+ const keyNodes = new Array<SerovalObjectRecordKey>(size);
199
+ const valueNodes = new Array<SerovalSyncNode>(size);
200
+ const deferredKeys = new Array<SerovalObjectRecordKey>(size);
201
+ const deferredValues = new Array<unknown>(size);
202
+ let deferredSize = 0;
203
+ let nodesSize = 0;
204
+ let item: unknown;
205
+ let escaped: SerovalObjectRecordKey;
206
+ for (const key of keys) {
207
+ item = properties[key];
208
+ escaped = serializeString(key);
209
+ if (isIterable(item)) {
210
+ deferredKeys[deferredSize] = escaped;
211
+ deferredValues[deferredSize] = item;
212
+ deferredSize++;
213
+ } else {
214
+ keyNodes[nodesSize] = escaped;
215
+ valueNodes[nodesSize] = crossParseSync(ctx, item);
216
+ nodesSize++;
217
+ }
218
+ }
219
+ for (let i = 0; i < deferredSize; i++) {
220
+ keyNodes[nodesSize + i] = deferredKeys[i];
221
+ valueNodes[nodesSize + i] = crossParseSync(ctx, deferredValues[i]);
222
+ }
223
+ if (ctx.features & Feature.Symbol) {
224
+ if (Symbol.iterator in properties) {
225
+ keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
226
+ const items = Array.from(properties as Iterable<unknown>);
227
+ valueNodes[size] = generateArrayNode(ctx, createCrossIndexedValue(ctx, items), items);
228
+ size++;
229
+ }
230
+ }
231
+ return {
232
+ k: keyNodes,
233
+ v: valueNodes,
234
+ s: size,
235
+ };
236
+ }
237
+
238
+ function generatePlainProperties(
239
+ ctx: CrossParserContext,
240
+ properties: Record<string, unknown>,
241
+ ): SerovalPlainRecordNode {
242
+ const keys = Object.keys(properties);
243
+ const size = keys.length;
244
+ const keyNodes = new Array<string>(size);
245
+ const valueNodes = new Array<SerovalSyncNode>(size);
246
+ const deferredKeys = new Array<string>(size);
247
+ const deferredValues = new Array<unknown>(size);
248
+ let deferredSize = 0;
249
+ let nodesSize = 0;
250
+ let item: unknown;
251
+ let escaped: string;
252
+ for (const key of keys) {
253
+ item = properties[key];
254
+ escaped = serializeString(key);
255
+ if (isIterable(item)) {
256
+ deferredKeys[deferredSize] = escaped;
257
+ deferredValues[deferredSize] = item;
258
+ deferredSize++;
259
+ } else {
260
+ keyNodes[nodesSize] = escaped;
261
+ valueNodes[nodesSize] = crossParseSync(ctx, item);
262
+ nodesSize++;
263
+ }
264
+ }
265
+ for (let i = 0; i < deferredSize; i++) {
266
+ keyNodes[nodesSize + i] = deferredKeys[i];
267
+ valueNodes[nodesSize + i] = crossParseSync(ctx, deferredValues[i]);
268
+ }
269
+ return {
270
+ k: keyNodes,
271
+ v: valueNodes,
272
+ s: size,
273
+ };
274
+ }
275
+
276
+ function generateObjectNode(
277
+ ctx: CrossParserContext,
278
+ id: number,
279
+ current: Record<string, unknown>,
280
+ empty: boolean,
281
+ ): ObjectLikeNode {
282
+ return {
283
+ t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
284
+ i: id,
285
+ s: undefined,
286
+ l: undefined,
287
+ c: undefined,
288
+ m: undefined,
289
+ p: generateProperties(ctx, current),
290
+ e: undefined,
291
+ a: undefined,
292
+ f: undefined,
293
+ b: undefined,
294
+ o: getObjectFlag(current),
295
+ };
296
+ }
297
+
298
+ function generateAggregateErrorNode(
299
+ ctx: CrossParserContext,
300
+ id: number,
301
+ current: AggregateError,
302
+ ): SerovalAggregateErrorNode {
303
+ const options = getErrorOptions(ctx, current);
304
+ const optionsNode = options
305
+ ? generateProperties(ctx, options)
306
+ : undefined;
307
+ return {
308
+ t: SerovalNodeType.AggregateError,
309
+ i: id,
310
+ s: undefined,
311
+ l: undefined,
312
+ c: undefined,
313
+ m: serializeString(current.message),
314
+ p: optionsNode,
315
+ e: undefined,
316
+ a: undefined,
317
+ f: undefined,
318
+ b: undefined,
319
+ o: undefined,
320
+ };
321
+ }
322
+
323
+ function generateErrorNode(
324
+ ctx: CrossParserContext,
325
+ id: number,
326
+ current: Error,
327
+ ): SerovalErrorNode {
328
+ const options = getErrorOptions(ctx, current);
329
+ const optionsNode = options
330
+ ? generateProperties(ctx, options)
331
+ : undefined;
332
+ return {
333
+ t: SerovalNodeType.Error,
334
+ i: id,
335
+ s: undefined,
336
+ l: undefined,
337
+ c: getErrorConstructorName(current),
338
+ m: serializeString(current.message),
339
+ p: optionsNode,
340
+ e: undefined,
341
+ a: undefined,
342
+ f: undefined,
343
+ b: undefined,
344
+ o: undefined,
345
+ };
346
+ }
347
+
348
+ function generateHeadersNode(
349
+ ctx: CrossParserContext,
350
+ id: number,
351
+ current: Headers,
352
+ ): SerovalHeadersNode {
353
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
354
+ const items: Record<string, string> = {};
355
+ // TS Headers not an Iterable
356
+ current.forEach((value, key) => {
357
+ items[key] = value;
358
+ });
359
+ return {
360
+ t: SerovalNodeType.Headers,
361
+ i: id,
362
+ s: undefined,
363
+ l: undefined,
364
+ c: undefined,
365
+ m: undefined,
366
+ p: undefined,
367
+ e: generatePlainProperties(ctx, items),
368
+ a: undefined,
369
+ f: undefined,
370
+ b: undefined,
371
+ o: undefined,
372
+ };
373
+ }
374
+
375
+ function generateFormDataNode(
376
+ ctx: CrossParserContext,
377
+ id: number,
378
+ current: FormData,
379
+ ): SerovalFormDataNode {
380
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
381
+ const items: Record<string, FormDataEntryValue> = {};
382
+ // TS FormData isn't an Iterable sadly
383
+ current.forEach((value, key) => {
384
+ items[key] = value;
385
+ });
386
+ return {
387
+ t: SerovalNodeType.FormData,
388
+ i: id,
389
+ s: undefined,
390
+ l: undefined,
391
+ c: undefined,
392
+ m: undefined,
393
+ p: undefined,
394
+ e: generatePlainProperties(ctx, items),
395
+ a: undefined,
396
+ f: undefined,
397
+ b: undefined,
398
+ o: undefined,
399
+ };
400
+ }
401
+
402
+ function generateBoxedNode(
403
+ ctx: CrossParserContext,
404
+ id: number,
405
+ current: object,
406
+ ): SerovalBoxedNode {
407
+ return {
408
+ t: SerovalNodeType.Boxed,
409
+ i: id,
410
+ s: undefined,
411
+ l: undefined,
412
+ c: undefined,
413
+ m: undefined,
414
+ p: undefined,
415
+ e: undefined,
416
+ a: undefined,
417
+ f: crossParseSync(ctx, current.valueOf()),
418
+ b: undefined,
419
+ o: undefined,
420
+ };
421
+ }
422
+
423
+ function parseObject(
424
+ ctx: CrossParserContext,
425
+ current: object | null,
426
+ ): SerovalSyncNode {
427
+ if (!current) {
428
+ return NULL_NODE;
429
+ }
430
+ // Non-primitive values needs a reference ID
431
+ // mostly because the values themselves are stateful
432
+ const registeredID = ctx.refs.get(current);
433
+ if (registeredID != null) {
434
+ return createIndexedValueNode(registeredID);
435
+ }
436
+ const id = ctx.refs.size;
437
+ ctx.refs.set(current, id);
438
+ if (hasReferenceID(current)) {
439
+ return createReferenceNode(id, current);
440
+ }
441
+ // Well well well
442
+ if (Array.isArray(current)) {
443
+ return generateArrayNode(ctx, id, current);
444
+ }
445
+ // Fast path
446
+ switch (current.constructor) {
447
+ case Number:
448
+ case Boolean:
449
+ case String:
450
+ case BigInt:
451
+ case Function:
452
+ case Symbol:
453
+ return generateBoxedNode(ctx, id, current);
454
+ case Date:
455
+ return createDateNode(id, current as unknown as Date);
456
+ case RegExp:
457
+ return createRegExpNode(id, current as unknown as RegExp);
458
+ case ArrayBuffer:
459
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
460
+ case Int8Array:
461
+ case Int16Array:
462
+ case Int32Array:
463
+ case Uint8Array:
464
+ case Uint16Array:
465
+ case Uint32Array:
466
+ case Uint8ClampedArray:
467
+ case Float32Array:
468
+ case Float64Array:
469
+ return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
470
+ case BigInt64Array:
471
+ case BigUint64Array:
472
+ return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
473
+ case DataView:
474
+ return createDataViewNode(ctx, id, current as unknown as DataView);
475
+ case Map:
476
+ return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
477
+ case Set:
478
+ return generateSetNode(ctx, id, current as unknown as Set<unknown>);
479
+ case Object:
480
+ return generateObjectNode(
481
+ ctx,
482
+ id,
483
+ current as unknown as Record<string, unknown>,
484
+ false,
485
+ );
486
+ case undefined:
487
+ return generateObjectNode(
488
+ ctx,
489
+ id,
490
+ current as unknown as Record<string, unknown>,
491
+ true,
492
+ );
493
+ case AggregateError:
494
+ // Compile-down AggregateError to Error if disabled
495
+ if (ctx.features & Feature.AggregateError) {
496
+ return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
497
+ }
498
+ return generateErrorNode(ctx, id, current as unknown as AggregateError);
499
+ case Error:
500
+ case EvalError:
501
+ case RangeError:
502
+ case ReferenceError:
503
+ case SyntaxError:
504
+ case TypeError:
505
+ case URIError:
506
+ return generateErrorNode(ctx, id, current as unknown as Error);
507
+ case URL:
508
+ return createURLNode(ctx, id, current as unknown as URL);
509
+ case URLSearchParams:
510
+ return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
511
+ case Headers:
512
+ return generateHeadersNode(ctx, id, current as unknown as Headers);
513
+ case FormData:
514
+ return generateFormDataNode(ctx, id, current as unknown as FormData);
515
+ default:
516
+ break;
517
+ }
518
+ // Slow path. We only need to handle Errors and Iterators
519
+ // since they have very broad implementations.
520
+ if (current instanceof AggregateError) {
521
+ if (ctx.features & Feature.AggregateError) {
522
+ return generateAggregateErrorNode(ctx, id, current);
523
+ }
524
+ return generateErrorNode(ctx, id, current);
525
+ }
526
+ if (current instanceof Error) {
527
+ return generateErrorNode(ctx, id, current);
528
+ }
529
+ // Generator functions don't have a global constructor
530
+ // despite existing
531
+ if (Symbol.iterator in current) {
532
+ return generateObjectNode(ctx, id, current, !!current.constructor);
533
+ }
534
+ throw new UnsupportedTypeError(current);
535
+ }
536
+
537
+ export default function crossParseSync<T>(
538
+ ctx: CrossParserContext,
539
+ current: T,
540
+ ): SerovalSyncNode {
541
+ switch (typeof current) {
542
+ case 'boolean':
543
+ return current ? TRUE_NODE : FALSE_NODE;
544
+ case 'undefined':
545
+ return UNDEFINED_NODE;
546
+ case 'string':
547
+ return createStringNode(current);
548
+ case 'number':
549
+ return createNumberNode(current);
550
+ case 'bigint':
551
+ return createBigIntNode(ctx, current);
552
+ case 'object':
553
+ return parseObject(ctx, current);
554
+ case 'symbol':
555
+ return createSymbolNode(ctx, current);
556
+ case 'function':
557
+ return createFunctionNode(ctx, current);
558
+ default:
559
+ throw new UnsupportedTypeError(current);
560
+ }
561
+ }
@@ -0,0 +1,55 @@
1
+ import assert from '../assert';
2
+ import { Feature } from '../compat';
3
+ import type { CrossParserContext } from './context';
4
+ import { serializeString } from '../string';
5
+ import UnsupportedTypeError from '../UnsupportedTypeError';
6
+ import { serializeArrayBuffer } from './primitives';
7
+ import type {
8
+ SerovalBlobNode,
9
+ SerovalFileNode,
10
+ } from '../types';
11
+ import { SerovalNodeType } from '../constants';
12
+
13
+ export async function createBlobNode(
14
+ ctx: CrossParserContext,
15
+ id: number,
16
+ current: Blob,
17
+ ): Promise<SerovalBlobNode> {
18
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
19
+ return {
20
+ t: SerovalNodeType.Blob,
21
+ i: id,
22
+ s: undefined,
23
+ l: undefined,
24
+ c: serializeString(current.type),
25
+ m: undefined,
26
+ p: undefined,
27
+ e: undefined,
28
+ f: serializeArrayBuffer(ctx, await current.arrayBuffer()),
29
+ a: undefined,
30
+ b: undefined,
31
+ o: undefined,
32
+ };
33
+ }
34
+
35
+ export async function createFileNode(
36
+ ctx: CrossParserContext,
37
+ id: number,
38
+ current: File,
39
+ ): Promise<SerovalFileNode> {
40
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
41
+ return {
42
+ t: SerovalNodeType.File,
43
+ i: id,
44
+ s: undefined,
45
+ l: undefined,
46
+ c: serializeString(current.type),
47
+ m: serializeString(current.name),
48
+ p: undefined,
49
+ e: undefined,
50
+ f: serializeArrayBuffer(ctx, await current.arrayBuffer()),
51
+ a: undefined,
52
+ b: current.lastModified,
53
+ o: undefined,
54
+ };
55
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * This file is used to represent the minified header script located at ./keys.ts
3
+ * If anything, this code is the unminified, readable version of it.
4
+ */
5
+
6
+ // Global references array. Global because we (ideally) want <script> elements to share it.
7
+ self._$ = self._$ || {
8
+ // Promise constructor, used to construct deferred Promises
9
+ P(success, failure, promise) {
10
+ promise = new Promise(function (resolve, reject) {
11
+ success = resolve;
12
+ failure = reject;
13
+ });
14
+
15
+ promise.s = success;
16
+ promise.f = failure;
17
+
18
+ return promise;
19
+ },
20
+ // This unsets the custom properties of the Promise instance
21
+ uP(promise) {
22
+ delete promise.s;
23
+ delete promise.f;
24
+ },
25
+ // Promise resolution
26
+ Ps(promise, data) {
27
+ promise.s(data);
28
+ promise.value = data;
29
+ this.uP(promise);
30
+ },
31
+ Pf(promise, data) {
32
+ promise.f(data);
33
+ this.uP(promise);
34
+ },
35
+ // Unset stream
36
+ uS(stream) {
37
+ delete stream.c;
38
+ },
39
+ Se(stream, type, data, controller) {
40
+ controller = stream.c;
41
+ switch (type) {
42
+ case 0: return controller.enqueue(data);
43
+ case 1:
44
+ this.uS(stream);
45
+ return controller.error(data);
46
+ case 2:
47
+ this.uS(stream);
48
+ return controller.close();
49
+ }
50
+ },
51
+ // ReadableStream constructor
52
+ S(stream, controller) {
53
+ stream = new ReadableStream({
54
+ start: function (c) {
55
+ controller = c;
56
+ }
57
+ });
58
+ stream.c = controller;
59
+ return stream;
60
+ },
61
+ };
@@ -0,0 +1,41 @@
1
+ import { serializeString } from './string';
2
+
3
+ // Used for mapping isomorphic references
4
+ export const REFERENCES_KEY = '__SEROVAL_REFS__';
5
+
6
+ export const GLOBAL_CONTEXT_API = '_$';
7
+
8
+ export const GLOBAL_CONTEXT_REFERENCES = '$R';
9
+
10
+ export const LOCAL_CONTEXT_PROMISE_RESOLVE = 's';
11
+
12
+ export const LOCAL_CONTEXT_PROMISE_REJECT = 'f';
13
+
14
+ export const GLOBAL_CONTEXT_PROMISE_CONSTRUCTOR = 'P';
15
+
16
+ export const GLOBAL_CONTEXT_PROMISE_RESOLVE = 'Ps';
17
+
18
+ export const GLOBAL_CONTEXT_PROMISE_REJECT = 'Pf';
19
+
20
+ export const LOCAL_CONTEXT_STREAM_CONTROLLER = 'c';
21
+
22
+ export const GLOBAL_CONTEXT_STREAM_CONSTRUCTOR = 'S';
23
+
24
+ export const GLOBAL_CONTEXT_STREAM_EMIT = 'Se';
25
+
26
+ export const GLOBAL_CONTEXT_API_SCRIPT = `self.${GLOBAL_CONTEXT_API}=self.${GLOBAL_CONTEXT_API}||{`
27
+ + `${GLOBAL_CONTEXT_PROMISE_CONSTRUCTOR}:function(s,f,p){return(p=new Promise(function(a,b){s=a,f=b})).${LOCAL_CONTEXT_PROMISE_RESOLVE}=s,p.${LOCAL_CONTEXT_PROMISE_REJECT}=f,p},`
28
+ + `uP:function(p){delete p.${LOCAL_CONTEXT_PROMISE_RESOLVE};delete p.${LOCAL_CONTEXT_PROMISE_REJECT}},`
29
+ + `${GLOBAL_CONTEXT_PROMISE_RESOLVE}:function(p,d){p.${LOCAL_CONTEXT_PROMISE_RESOLVE}(d),p.value=d,this.uP(p)},`
30
+ + `${GLOBAL_CONTEXT_PROMISE_REJECT}:function(p,d){p.${LOCAL_CONTEXT_PROMISE_REJECT}(d),this.uP(p)},`
31
+ + `uS:function(s){delete s.${LOCAL_CONTEXT_STREAM_CONTROLLER}},`
32
+ + `${GLOBAL_CONTEXT_STREAM_EMIT}:function(s,t,d,c){switch(c=s.${LOCAL_CONTEXT_STREAM_CONTROLLER},t){case 0:return c.enqueue(d);case 1:return(this.uS(s),c.error(d));case 2:return(this.uS(s),c.close())}},`
33
+ + `${GLOBAL_CONTEXT_STREAM_CONSTRUCTOR}:function(s,c){return(s=new ReadableStream({start:function(x){c=x}})).${LOCAL_CONTEXT_STREAM_CONTROLLER}=c,s},`
34
+ + '}';
35
+
36
+ export function getCrossReferenceHeader(id?: string): string {
37
+ if (id == null) {
38
+ return `self.${GLOBAL_CONTEXT_REFERENCES}=self.${GLOBAL_CONTEXT_REFERENCES}||[];`;
39
+ }
40
+ return `(self.${GLOBAL_CONTEXT_REFERENCES}=self.${GLOBAL_CONTEXT_REFERENCES}||{})["${serializeString(id)}"]=[]`;
41
+ }