seroval 0.11.6 → 0.12.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 (122) hide show
  1. package/README.md +29 -16
  2. package/dist/cjs/development/index.cjs +3072 -4875
  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 +3069 -4874
  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 +2 -0
  9. package/dist/types/core/Serializer.d.ts.map +1 -0
  10. package/dist/types/core/UnsupportedTypeError.d.ts +1 -0
  11. package/dist/types/core/UnsupportedTypeError.d.ts.map +1 -0
  12. package/dist/types/core/assert.d.ts +1 -0
  13. package/dist/types/core/assert.d.ts.map +1 -0
  14. package/dist/types/core/base/async.d.ts +30 -0
  15. package/dist/types/core/base/async.d.ts.map +1 -0
  16. package/dist/types/core/base/stream.d.ts +40 -0
  17. package/dist/types/core/base/stream.d.ts.map +1 -0
  18. package/dist/types/core/base/sync.d.ts +32 -0
  19. package/dist/types/core/base/sync.d.ts.map +1 -0
  20. package/dist/types/core/base-primitives.d.ts +3 -1
  21. package/dist/types/core/base-primitives.d.ts.map +1 -0
  22. package/dist/types/core/compat.d.ts +1 -0
  23. package/dist/types/core/compat.d.ts.map +1 -0
  24. package/dist/types/core/constants.d.ts +19 -4
  25. package/dist/types/core/constants.d.ts.map +1 -0
  26. package/dist/types/core/constructors.d.ts +1 -0
  27. package/dist/types/core/constructors.d.ts.map +1 -0
  28. package/dist/types/core/cross/async.d.ts +8 -3
  29. package/dist/types/core/cross/async.d.ts.map +1 -0
  30. package/dist/types/core/cross/cross-parser.d.ts +8 -0
  31. package/dist/types/core/cross/cross-parser.d.ts.map +1 -0
  32. package/dist/types/core/cross/index.d.ts +12 -5
  33. package/dist/types/core/cross/index.d.ts.map +1 -0
  34. package/dist/types/core/cross/serialize.d.ts +23 -5
  35. package/dist/types/core/cross/serialize.d.ts.map +1 -0
  36. package/dist/types/core/cross/stream.d.ts +8 -3
  37. package/dist/types/core/cross/stream.d.ts.map +1 -0
  38. package/dist/types/core/cross/sync.d.ts +8 -3
  39. package/dist/types/core/cross/sync.d.ts.map +1 -0
  40. package/dist/types/core/get-identifier.d.ts +1 -0
  41. package/dist/types/core/get-identifier.d.ts.map +1 -0
  42. package/dist/types/core/keys.d.ts +1 -0
  43. package/dist/types/core/keys.d.ts.map +1 -0
  44. package/dist/types/core/literals.d.ts +1 -0
  45. package/dist/types/core/literals.d.ts.map +1 -0
  46. package/dist/types/core/parser-context.d.ts +23 -0
  47. package/dist/types/core/parser-context.d.ts.map +1 -0
  48. package/dist/types/core/plugin.d.ts +26 -0
  49. package/dist/types/core/plugin.d.ts.map +1 -0
  50. package/dist/types/core/promise-to-result.d.ts +1 -0
  51. package/dist/types/core/promise-to-result.d.ts.map +1 -0
  52. package/dist/types/core/reference.d.ts +1 -0
  53. package/dist/types/core/reference.d.ts.map +1 -0
  54. package/dist/types/core/serializer-context.old.d.ts +165 -0
  55. package/dist/types/core/serializer-context.old.d.ts.map +1 -0
  56. package/dist/types/core/shared.d.ts +4 -7
  57. package/dist/types/core/shared.d.ts.map +1 -0
  58. package/dist/types/core/string.d.ts +1 -0
  59. package/dist/types/core/string.d.ts.map +1 -0
  60. package/dist/types/core/tree/async.d.ts +8 -3
  61. package/dist/types/core/tree/async.d.ts.map +1 -0
  62. package/dist/types/core/tree/deserialize.d.ts +49 -2
  63. package/dist/types/core/tree/deserialize.d.ts.map +1 -0
  64. package/dist/types/core/tree/index.d.ts +10 -7
  65. package/dist/types/core/tree/index.d.ts.map +1 -0
  66. package/dist/types/core/tree/serialize.d.ts +37 -4
  67. package/dist/types/core/tree/serialize.d.ts.map +1 -0
  68. package/dist/types/core/tree/sync.d.ts +8 -3
  69. package/dist/types/core/tree/sync.d.ts.map +1 -0
  70. package/dist/types/core/types.d.ts +10 -3
  71. package/dist/types/core/types.d.ts.map +1 -0
  72. package/dist/types/core/web-api.d.ts +1 -0
  73. package/dist/types/core/web-api.d.ts.map +1 -0
  74. package/dist/types/index.d.ts +3 -0
  75. package/dist/types/index.d.ts.map +1 -0
  76. package/dist/types/types.d.ts +1 -0
  77. package/dist/types/types.d.ts.map +1 -0
  78. package/package.json +2 -2
  79. package/src/core/Serializer.ts +2 -0
  80. package/src/core/base/async.ts +804 -0
  81. package/src/core/base/stream.ts +496 -0
  82. package/src/core/base/sync.ts +675 -0
  83. package/src/core/base-primitives.ts +22 -0
  84. package/src/core/constants.ts +61 -45
  85. package/src/core/cross/async.ts +6 -751
  86. package/src/core/cross/cross-parser.ts +9 -0
  87. package/src/core/cross/index.ts +62 -84
  88. package/src/core/cross/serialize.ts +71 -862
  89. package/src/core/cross/stream.ts +6 -873
  90. package/src/core/cross/sync.ts +6 -624
  91. package/src/core/is-serializable.new.ts +208 -0
  92. package/src/core/keys.ts +1 -1
  93. package/src/core/parser-context.ts +131 -0
  94. package/src/core/plugin.ts +55 -0
  95. package/src/core/serializer-context.new.ts +1168 -0
  96. package/src/core/serializer-context.old.ts +1126 -0
  97. package/src/core/shared.ts +46 -123
  98. package/src/core/tree/async.ts +6 -750
  99. package/src/core/tree/deserialize.ts +423 -420
  100. package/src/core/tree/index.ts +49 -91
  101. package/src/core/tree/parser.ts +45 -0
  102. package/src/core/tree/serialize.ts +122 -828
  103. package/src/core/tree/sync.ts +6 -624
  104. package/src/core/types.ts +13 -2
  105. package/src/example.ts +28 -0
  106. package/src/index.ts +3 -0
  107. package/dist/types/core/assignments.d.ts +0 -33
  108. package/dist/types/core/context.d.ts +0 -9
  109. package/dist/types/core/cross/context.d.ts +0 -37
  110. package/dist/types/core/cross/primitives.d.ts +0 -9
  111. package/dist/types/core/cross/web-api.d.ts +0 -4
  112. package/dist/types/core/tree/context.d.ts +0 -44
  113. package/dist/types/core/tree/primitives.d.ts +0 -9
  114. package/dist/types/core/tree/web-api.d.ts +0 -4
  115. package/src/core/assignments.ts +0 -159
  116. package/src/core/context.ts +0 -15
  117. package/src/core/cross/context.ts +0 -102
  118. package/src/core/cross/primitives.ts +0 -128
  119. package/src/core/cross/web-api.ts +0 -50
  120. package/src/core/tree/context.ts +0 -125
  121. package/src/core/tree/primitives.ts +0 -123
  122. package/src/core/tree/web-api.ts +0 -50
@@ -0,0 +1,496 @@
1
+ import type { BigIntTypedArrayValue, TypedArrayValue } from '../../types';
2
+ import UnsupportedTypeError from '../UnsupportedTypeError';
3
+ import {
4
+ createArrayBufferNode,
5
+ createDateNode,
6
+ createPluginNode,
7
+ createRegExpNode,
8
+ } from '../base-primitives';
9
+ import type { BaseSyncParserContextOptions } from './sync';
10
+ import BaseSyncParserContext from './sync';
11
+ import { BIGINT_FLAG, Feature } from '../compat';
12
+ import { SerovalNodeType, UNIVERSAL_SENTINEL } from '../constants';
13
+ import { createRequestOptions, createResponseOptions } from '../constructors';
14
+ import { NULL_NODE } from '../literals';
15
+ import { serializeString } from '../string';
16
+ import type {
17
+ SerovalNode,
18
+ SerovalPluginNode,
19
+ SerovalPromiseConstructorNode,
20
+ SerovalReadableStreamConstructorNode,
21
+ SerovalRequestNode,
22
+ SerovalResponseNode,
23
+ } from '../types';
24
+ import { createDOMExceptionNode, createURLNode, createURLSearchParamsNode } from '../web-api';
25
+
26
+ export interface BaseStreamParserContextOptions extends BaseSyncParserContextOptions {
27
+ onParse: (node: SerovalNode, initial: boolean) => void;
28
+ onError?: (error: unknown) => void;
29
+ onDone?: () => void;
30
+ }
31
+
32
+ export default abstract class BaseStreamParserContext extends BaseSyncParserContext {
33
+ // Life
34
+ private alive = true;
35
+
36
+ // Amount of pending promises/streams
37
+ private pending = 0;
38
+
39
+ private onParseCallback: (node: SerovalNode, initial: boolean) => void;
40
+
41
+ private onErrorCallback?: (error: unknown) => void;
42
+
43
+ private onDoneCallback?: () => void;
44
+
45
+ constructor(options: BaseStreamParserContextOptions) {
46
+ super(options);
47
+ this.onParseCallback = options.onParse;
48
+ this.onErrorCallback = options.onError;
49
+ this.onDoneCallback = options.onDone;
50
+ }
51
+
52
+ private onParse(node: SerovalNode, initial: boolean): void {
53
+ this.onParseCallback(node, initial);
54
+ }
55
+
56
+ private onError(error: unknown): void {
57
+ if (this.onErrorCallback) {
58
+ this.onErrorCallback(error);
59
+ } else {
60
+ throw error;
61
+ }
62
+ }
63
+
64
+ private onDone(): void {
65
+ if (this.onDoneCallback) {
66
+ this.onDoneCallback();
67
+ }
68
+ }
69
+
70
+ push<T>(value: T): void {
71
+ this.onParse(
72
+ this.parse(value),
73
+ false,
74
+ );
75
+ }
76
+
77
+ pushPendingState(): void {
78
+ this.pending++;
79
+ }
80
+
81
+ popPendingState(): void {
82
+ if (--this.pending <= 0) {
83
+ this.onDone();
84
+ }
85
+ }
86
+
87
+ private pushReadableStreamReader(
88
+ id: number,
89
+ reader: ReadableStreamDefaultReader,
90
+ ): void {
91
+ reader.read().then(
92
+ (data) => {
93
+ if (this.alive) {
94
+ if (data.done) {
95
+ this.onParse({
96
+ t: SerovalNodeType.ReadableStreamClose,
97
+ i: id,
98
+ s: undefined,
99
+ l: undefined,
100
+ c: undefined,
101
+ m: undefined,
102
+ p: undefined,
103
+ e: undefined,
104
+ a: undefined,
105
+ f: undefined,
106
+ b: undefined,
107
+ o: undefined,
108
+ }, false);
109
+ this.popPendingState();
110
+ } else {
111
+ const parsed = this.parseWithError(data.value);
112
+ if (parsed) {
113
+ this.onParse({
114
+ t: SerovalNodeType.ReadableStreamEnqueue,
115
+ i: id,
116
+ s: undefined,
117
+ l: undefined,
118
+ c: undefined,
119
+ m: undefined,
120
+ p: undefined,
121
+ e: undefined,
122
+ a: undefined,
123
+ f: parsed,
124
+ b: undefined,
125
+ o: undefined,
126
+ }, false);
127
+ this.pushReadableStreamReader(id, reader);
128
+ }
129
+ }
130
+ }
131
+ },
132
+ (value) => {
133
+ if (this.alive) {
134
+ const parsed = this.parseWithError(value);
135
+ if (parsed) {
136
+ this.onParse({
137
+ t: SerovalNodeType.ReadableStreamError,
138
+ i: id,
139
+ s: undefined,
140
+ l: undefined,
141
+ c: undefined,
142
+ m: undefined,
143
+ p: undefined,
144
+ e: undefined,
145
+ a: undefined,
146
+ f: parsed,
147
+ b: undefined,
148
+ o: undefined,
149
+ }, false);
150
+ this.popPendingState();
151
+ }
152
+ }
153
+ },
154
+ );
155
+ }
156
+
157
+ private parseReadableStream(
158
+ id: number,
159
+ current: ReadableStream<unknown>,
160
+ ): SerovalReadableStreamConstructorNode {
161
+ const reader = current.getReader();
162
+ this.pushPendingState();
163
+ this.pushReadableStreamReader(id, reader);
164
+
165
+ return {
166
+ t: SerovalNodeType.ReadableStreamConstructor,
167
+ i: id,
168
+ s: undefined,
169
+ l: undefined,
170
+ c: undefined,
171
+ m: undefined,
172
+ p: undefined,
173
+ e: undefined,
174
+ a: undefined,
175
+ f: undefined,
176
+ b: undefined,
177
+ o: undefined,
178
+ };
179
+ }
180
+
181
+ private parseRequest(
182
+ id: number,
183
+ current: Request,
184
+ ): SerovalRequestNode {
185
+ return {
186
+ t: SerovalNodeType.Request,
187
+ i: id,
188
+ s: serializeString(current.url),
189
+ l: undefined,
190
+ c: undefined,
191
+ m: undefined,
192
+ p: undefined,
193
+ e: undefined,
194
+ f: this.parse(
195
+ createRequestOptions(current, current.clone().body),
196
+ ),
197
+ a: undefined,
198
+ b: undefined,
199
+ o: undefined,
200
+ };
201
+ }
202
+
203
+ private parseResponse(
204
+ id: number,
205
+ current: Response,
206
+ ): SerovalResponseNode {
207
+ return {
208
+ t: SerovalNodeType.Response,
209
+ i: id,
210
+ s: undefined,
211
+ l: undefined,
212
+ c: undefined,
213
+ m: undefined,
214
+ p: undefined,
215
+ e: undefined,
216
+ f: undefined,
217
+ a: [
218
+ current.body
219
+ ? this.parse(current.clone().body)
220
+ : NULL_NODE,
221
+ this.parse(createResponseOptions(current)),
222
+ ],
223
+ b: undefined,
224
+ o: undefined,
225
+ };
226
+ }
227
+
228
+ private parsePromise(
229
+ id: number,
230
+ current: Promise<unknown>,
231
+ ): SerovalPromiseConstructorNode {
232
+ current.then(
233
+ (data) => {
234
+ const parsed = this.parseWithError(data);
235
+ if (parsed) {
236
+ this.onParse({
237
+ t: SerovalNodeType.PromiseResolve,
238
+ i: id,
239
+ s: undefined,
240
+ l: undefined,
241
+ c: undefined,
242
+ m: undefined,
243
+ p: undefined,
244
+ e: undefined,
245
+ a: undefined,
246
+ f: parsed,
247
+ b: undefined,
248
+ o: undefined,
249
+ }, false);
250
+ this.popPendingState();
251
+ }
252
+ },
253
+ (data) => {
254
+ if (this.alive) {
255
+ const parsed = this.parseWithError(data);
256
+ if (parsed) {
257
+ this.onParse({
258
+ t: SerovalNodeType.PromiseReject,
259
+ i: id,
260
+ s: undefined,
261
+ l: undefined,
262
+ c: undefined,
263
+ m: undefined,
264
+ p: undefined,
265
+ e: undefined,
266
+ a: undefined,
267
+ f: parsed,
268
+ b: undefined,
269
+ o: undefined,
270
+ }, false);
271
+ this.popPendingState();
272
+ }
273
+ }
274
+ },
275
+ );
276
+ this.pushPendingState();
277
+ return {
278
+ t: SerovalNodeType.PromiseConstructor,
279
+ i: id,
280
+ s: undefined,
281
+ l: undefined,
282
+ c: undefined,
283
+ m: undefined,
284
+ p: undefined,
285
+ e: undefined,
286
+ a: undefined,
287
+ f: undefined,
288
+ b: undefined,
289
+ o: undefined,
290
+ };
291
+ }
292
+
293
+ protected parsePlugin(
294
+ id: number,
295
+ current: unknown,
296
+ ): SerovalPluginNode | undefined {
297
+ const currentPlugins = this.plugins;
298
+ if (currentPlugins) {
299
+ for (let i = 0, len = currentPlugins.length; i < len; i++) {
300
+ const plugin = currentPlugins[i];
301
+ if (plugin.parse.stream && plugin.test(current)) {
302
+ return createPluginNode(
303
+ id,
304
+ plugin.tag,
305
+ plugin.parse.stream(current, this, {
306
+ id,
307
+ }),
308
+ );
309
+ }
310
+ }
311
+ }
312
+ return undefined;
313
+ }
314
+
315
+ protected parseObject(
316
+ id: number,
317
+ current: object,
318
+ ): SerovalNode {
319
+ if (Array.isArray(current)) {
320
+ return this.parseArray(id, current);
321
+ }
322
+ const currentClass = current.constructor;
323
+ switch (currentClass) {
324
+ case Object:
325
+ return this.parsePlainObject(
326
+ id,
327
+ current as Record<string, unknown>,
328
+ false,
329
+ );
330
+ case undefined:
331
+ return this.parsePlainObject(
332
+ id,
333
+ current as Record<string, unknown>,
334
+ true,
335
+ );
336
+ case Date:
337
+ return createDateNode(id, current as unknown as Date);
338
+ case RegExp:
339
+ return createRegExpNode(id, current as unknown as RegExp);
340
+ case Error:
341
+ case EvalError:
342
+ case RangeError:
343
+ case ReferenceError:
344
+ case SyntaxError:
345
+ case TypeError:
346
+ case URIError:
347
+ return this.parseError(id, current as unknown as Error);
348
+ case Number:
349
+ case Boolean:
350
+ case String:
351
+ case BigInt:
352
+ return this.parseBoxed(id, current);
353
+ default:
354
+ break;
355
+ }
356
+ const currentFeatures = this.features;
357
+ // Promises
358
+ if (
359
+ (currentFeatures & Feature.Promise)
360
+ && (currentClass === Promise || current instanceof Promise)
361
+ ) {
362
+ return this.parsePromise(id, current as unknown as Promise<unknown>);
363
+ }
364
+ // Typed Arrays
365
+ if (currentFeatures & Feature.TypedArray) {
366
+ switch (currentClass) {
367
+ case ArrayBuffer:
368
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
369
+ case Int8Array:
370
+ case Int16Array:
371
+ case Int32Array:
372
+ case Uint8Array:
373
+ case Uint16Array:
374
+ case Uint32Array:
375
+ case Uint8ClampedArray:
376
+ case Float32Array:
377
+ case Float64Array:
378
+ return this.parseTypedArray(id, current as unknown as TypedArrayValue);
379
+ case DataView:
380
+ return this.parseDataView(id, current as unknown as DataView);
381
+ default:
382
+ break;
383
+ }
384
+ }
385
+ // BigInt Typed Arrays
386
+ if ((currentFeatures & BIGINT_FLAG) === BIGINT_FLAG) {
387
+ switch (currentClass) {
388
+ case BigInt64Array:
389
+ case BigUint64Array:
390
+ return this.parseBigIntTypedArray(id, current as unknown as BigIntTypedArrayValue);
391
+ default:
392
+ break;
393
+ }
394
+ }
395
+ // ES Collection
396
+ if (currentFeatures & Feature.Map && currentClass === Map) {
397
+ return this.parseMap(
398
+ id,
399
+ current as unknown as Map<unknown, unknown>,
400
+ );
401
+ }
402
+ if (currentFeatures & Feature.Set && currentClass === Set) {
403
+ return this.parseSet(
404
+ id,
405
+ current as unknown as Set<unknown>,
406
+ );
407
+ }
408
+ // Web APIs
409
+ if (currentFeatures & Feature.WebAPI) {
410
+ switch (currentClass) {
411
+ case (typeof URL !== 'undefined' ? URL : UNIVERSAL_SENTINEL):
412
+ return createURLNode(id, current as unknown as URL);
413
+ case (typeof URLSearchParams !== 'undefined' ? URLSearchParams : UNIVERSAL_SENTINEL):
414
+ return createURLSearchParamsNode(id, current as unknown as URLSearchParams);
415
+ case (typeof Headers !== 'undefined' ? Headers : UNIVERSAL_SENTINEL):
416
+ return this.parseHeaders(id, current as unknown as Headers);
417
+ case (typeof FormData !== 'undefined' ? FormData : UNIVERSAL_SENTINEL):
418
+ return this.parseFormData(id, current as unknown as FormData);
419
+ case (typeof ReadableStream !== 'undefined' ? ReadableStream : UNIVERSAL_SENTINEL):
420
+ return this.parseReadableStream(id, current as unknown as ReadableStream);
421
+ case (typeof Request !== 'undefined' ? Request : UNIVERSAL_SENTINEL):
422
+ return this.parseRequest(id, current as unknown as Request);
423
+ case (typeof Response !== 'undefined' ? Response : UNIVERSAL_SENTINEL):
424
+ return this.parseResponse(id, current as unknown as Response);
425
+ case (typeof Event !== 'undefined' ? Event : UNIVERSAL_SENTINEL):
426
+ return this.parseEvent(id, current as unknown as Event);
427
+ case (typeof CustomEvent !== 'undefined' ? CustomEvent : UNIVERSAL_SENTINEL):
428
+ return this.parseCustomEvent(id, current as unknown as CustomEvent);
429
+ case (typeof DOMException !== 'undefined' ? DOMException : UNIVERSAL_SENTINEL):
430
+ return createDOMExceptionNode(id, current as unknown as DOMException);
431
+ default:
432
+ break;
433
+ }
434
+ }
435
+ const parsed = this.parsePlugin(id, current);
436
+ if (parsed) {
437
+ return parsed;
438
+ }
439
+ if (
440
+ (currentFeatures & Feature.AggregateError)
441
+ && typeof AggregateError !== 'undefined'
442
+ && (currentClass === AggregateError || current instanceof AggregateError)
443
+ ) {
444
+ return this.parseAggregateError(id, current as unknown as AggregateError);
445
+ }
446
+ // Slow path. We only need to handle Errors and Iterators
447
+ // since they have very broad implementations.
448
+ if (current instanceof Error) {
449
+ return this.parseError(id, current);
450
+ }
451
+ // Generator functions don't have a global constructor
452
+ // despite existing
453
+ if (currentFeatures & Feature.Symbol && Symbol.iterator in current) {
454
+ return this.parsePlainObject(id, current, !!currentClass);
455
+ }
456
+ throw new UnsupportedTypeError(current);
457
+ }
458
+
459
+ private parseWithError<T>(current: T): SerovalNode | undefined {
460
+ try {
461
+ return this.parse(current);
462
+ } catch (err) {
463
+ this.onError(err);
464
+ return undefined;
465
+ }
466
+ }
467
+
468
+ /**
469
+ * @private
470
+ */
471
+ start<T>(current: T): void {
472
+ const parsed = this.parseWithError(current);
473
+ if (parsed) {
474
+ this.onParse(parsed, true);
475
+
476
+ // Check if there's any pending pushes
477
+ if (this.pending <= 0) {
478
+ this.destroy();
479
+ }
480
+ }
481
+ }
482
+
483
+ /**
484
+ * @private
485
+ */
486
+ destroy(): void {
487
+ if (this.alive) {
488
+ this.onDone();
489
+ this.alive = false;
490
+ }
491
+ }
492
+
493
+ isAlive(): boolean {
494
+ return this.alive;
495
+ }
496
+ }