seroval 0.7.0 → 0.9.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 (42) hide show
  1. package/dist/cjs/development/index.cjs +1247 -1069
  2. package/dist/cjs/development/index.cjs.map +4 -4
  3. package/dist/cjs/production/index.cjs +3 -3
  4. package/dist/esm/development/index.mjs +1247 -1069
  5. package/dist/esm/development/index.mjs.map +4 -4
  6. package/dist/esm/production/index.mjs +3 -3
  7. package/dist/types/assert.d.ts +1 -1
  8. package/dist/types/context.d.ts +8 -2
  9. package/dist/types/index.d.ts +3 -4
  10. package/dist/types/string.d.ts +1 -1
  11. package/dist/types/tree/UnsupportedTypeError.d.ts +3 -0
  12. package/dist/types/tree/async.d.ts +3 -3
  13. package/dist/types/tree/constants.d.ts +11 -0
  14. package/dist/types/tree/deserialize.d.ts +2 -2
  15. package/dist/types/tree/primitives.d.ts +9 -15
  16. package/dist/types/tree/serialize.d.ts +2 -2
  17. package/dist/types/tree/shared.d.ts +12 -8
  18. package/dist/types/tree/sync.d.ts +3 -3
  19. package/dist/types/tree/types.d.ts +74 -71
  20. package/dist/types/tree/web-api.d.ts +2 -2
  21. package/dist/types/types.d.ts +4 -4
  22. package/package.json +11 -9
  23. package/src/assert.ts +2 -2
  24. package/src/compat.ts +0 -1
  25. package/src/context.ts +20 -7
  26. package/src/get-identifier.ts +1 -1
  27. package/src/index.ts +35 -26
  28. package/src/string.ts +2 -2
  29. package/src/tree/UnsupportedTypeError.ts +8 -0
  30. package/src/tree/async.ts +256 -233
  31. package/src/tree/constants.ts +73 -0
  32. package/src/tree/deserialize.ts +112 -93
  33. package/src/tree/primitives.ts +93 -134
  34. package/src/tree/reference.ts +3 -3
  35. package/src/tree/serialize.ts +307 -201
  36. package/src/tree/shared.ts +45 -22
  37. package/src/tree/symbols.ts +13 -13
  38. package/src/tree/sync.ts +236 -198
  39. package/src/tree/types.ts +87 -94
  40. package/src/tree/web-api.ts +14 -7
  41. package/src/types.ts +7 -3
  42. package/src/tree/iterator.ts +0 -14
package/src/tree/sync.ts CHANGED
@@ -1,9 +1,17 @@
1
1
  /* eslint-disable @typescript-eslint/no-use-before-define */
2
2
  import assert from '../assert';
3
3
  import { Feature } from '../compat';
4
- import { createIndexedValue, getRootID, ParserContext } from '../context';
4
+ import type { ParserContext } from '../context';
5
+ import { createIndexedValue } from '../context';
5
6
  import { serializeString } from '../string';
6
- import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
7
+ import type { BigIntTypedArrayValue, TypedArrayValue } from '../types';
8
+ import UnsupportedTypeError from './UnsupportedTypeError';
9
+ import {
10
+ TRUE_NODE,
11
+ FALSE_NODE,
12
+ UNDEFINED_NODE,
13
+ NULL_NODE,
14
+ } from './constants';
7
15
  import {
8
16
  createBigIntNode,
9
17
  createBigIntTypedArrayNode,
@@ -13,18 +21,11 @@ import {
13
21
  createRegExpNode,
14
22
  createStringNode,
15
23
  createTypedArrayNode,
16
- createWKSymbolNode,
17
- FALSE_NODE,
18
- INFINITY_NODE,
19
- NAN_NODE,
20
- NEG_INFINITY_NODE,
21
- NEG_ZERO_NODE,
22
- NULL_NODE,
23
- TRUE_NODE,
24
- UNDEFINED_NODE,
25
24
  createReferenceNode,
26
25
  createArrayBufferNode,
27
26
  createDataViewNode,
27
+ createSymbolNode,
28
+ createFunctionNode,
28
29
  } from './primitives';
29
30
  import {
30
31
  hasReferenceID,
@@ -32,30 +33,34 @@ import {
32
33
  import {
33
34
  getErrorConstructorName,
34
35
  getErrorOptions,
35
- getIterableOptions,
36
+ getObjectFlag,
36
37
  isIterable,
37
38
  } from './shared';
38
- import { WellKnownSymbols } from './symbols';
39
- import {
39
+ import type {
40
40
  SerovalAggregateErrorNode,
41
41
  SerovalArrayNode,
42
+ SerovalBoxedNode,
42
43
  SerovalErrorNode,
43
44
  SerovalFormDataNode,
44
45
  SerovalHeadersNode,
45
- SerovalIterableNode,
46
46
  SerovalMapNode,
47
47
  SerovalNode,
48
- SerovalNodeType,
49
48
  SerovalNullConstructorNode,
50
49
  SerovalObjectNode,
50
+ SerovalObjectRecordKey,
51
51
  SerovalObjectRecordNode,
52
+ SerovalPlainRecordNode,
52
53
  SerovalSetNode,
53
54
  } from './types';
55
+ import {
56
+ SerovalNodeType,
57
+ SerovalObjectRecordSpecialKey,
58
+ } from './types';
54
59
  import { createURLNode, createURLSearchParamsNode } from './web-api';
55
60
 
56
- type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode | SerovalIterableNode;
61
+ type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode;
57
62
 
58
- function generateNodeList(ctx: ParserContext, current: unknown[]) {
63
+ function generateNodeList(ctx: ParserContext, current: unknown[]): SerovalNode[] {
59
64
  const size = current.length;
60
65
  const nodes = new Array<SerovalNode>(size);
61
66
  const deferred = new Array<unknown>(size);
@@ -66,13 +71,13 @@ function generateNodeList(ctx: ParserContext, current: unknown[]) {
66
71
  if (isIterable(item)) {
67
72
  deferred[i] = item;
68
73
  } else {
69
- nodes[i] = parse(ctx, item);
74
+ nodes[i] = parseSync(ctx, item);
70
75
  }
71
76
  }
72
77
  }
73
78
  for (let i = 0; i < size; i++) {
74
79
  if (i in deferred) {
75
- nodes[i] = parse(ctx, deferred[i]);
80
+ nodes[i] = parseSync(ctx, deferred[i]);
76
81
  }
77
82
  }
78
83
  return nodes;
@@ -94,6 +99,7 @@ function generateArrayNode(
94
99
  a: generateNodeList(ctx, current),
95
100
  f: undefined,
96
101
  b: undefined,
102
+ o: getObjectFlag(current),
97
103
  };
98
104
  }
99
105
 
@@ -102,7 +108,7 @@ function generateMapNode(
102
108
  id: number,
103
109
  current: Map<unknown, unknown>,
104
110
  ): SerovalMapNode {
105
- assert(ctx.features & Feature.Map, 'Unsupported type "Map"');
111
+ assert(ctx.features & Feature.Map, new UnsupportedTypeError(current));
106
112
  const len = current.size;
107
113
  const keyNodes = new Array<SerovalNode>(len);
108
114
  const valueNodes = new Array<SerovalNode>(len);
@@ -117,14 +123,14 @@ function generateMapNode(
117
123
  deferredValue[deferredSize] = value;
118
124
  deferredSize++;
119
125
  } else {
120
- keyNodes[nodeSize] = parse(ctx, key);
121
- valueNodes[nodeSize] = parse(ctx, value);
126
+ keyNodes[nodeSize] = parseSync(ctx, key);
127
+ valueNodes[nodeSize] = parseSync(ctx, value);
122
128
  nodeSize++;
123
129
  }
124
130
  }
125
131
  for (let i = 0; i < deferredSize; i++) {
126
- keyNodes[nodeSize + i] = parse(ctx, deferredKey[i]);
127
- valueNodes[nodeSize + i] = parse(ctx, deferredValue[i]);
132
+ keyNodes[nodeSize + i] = parseSync(ctx, deferredKey[i]);
133
+ valueNodes[nodeSize + i] = parseSync(ctx, deferredValue[i]);
128
134
  }
129
135
  return {
130
136
  t: SerovalNodeType.Map,
@@ -137,6 +143,7 @@ function generateMapNode(
137
143
  a: undefined,
138
144
  f: undefined,
139
145
  b: undefined,
146
+ o: undefined,
140
147
  };
141
148
  }
142
149
 
@@ -145,7 +152,7 @@ function generateSetNode(
145
152
  id: number,
146
153
  current: Set<unknown>,
147
154
  ): SerovalSetNode {
148
- assert(ctx.features & Feature.Set, 'Unsupported type "Set"');
155
+ assert(ctx.features & Feature.Set, new UnsupportedTypeError(current));
149
156
  const len = current.size;
150
157
  const nodes = new Array<SerovalNode>(len);
151
158
  const deferred = new Array<unknown>(len);
@@ -156,12 +163,12 @@ function generateSetNode(
156
163
  if (isIterable(item)) {
157
164
  deferred[deferredSize++] = item;
158
165
  } else {
159
- nodes[nodeSize++] = parse(ctx, item);
166
+ nodes[nodeSize++] = parseSync(ctx, item);
160
167
  }
161
168
  }
162
169
  // Parse deferred items
163
170
  for (let i = 0; i < deferredSize; i++) {
164
- nodes[nodeSize + i] = parse(ctx, deferred[i]);
171
+ nodes[nodeSize + i] = parseSync(ctx, deferred[i]);
165
172
  }
166
173
  return {
167
174
  t: SerovalNodeType.Set,
@@ -174,6 +181,7 @@ function generateSetNode(
174
181
  a: nodes,
175
182
  f: undefined,
176
183
  b: undefined,
184
+ o: undefined,
177
185
  };
178
186
  }
179
187
 
@@ -182,15 +190,15 @@ function generateProperties(
182
190
  properties: Record<string, unknown>,
183
191
  ): SerovalObjectRecordNode {
184
192
  const keys = Object.keys(properties);
185
- const size = keys.length;
186
- const keyNodes = new Array<string>(size);
193
+ let size = keys.length;
194
+ const keyNodes = new Array<SerovalObjectRecordKey>(size);
187
195
  const valueNodes = new Array<SerovalNode>(size);
188
- const deferredKeys = new Array<string>(size);
196
+ const deferredKeys = new Array<SerovalObjectRecordKey>(size);
189
197
  const deferredValues = new Array<unknown>(size);
190
198
  let deferredSize = 0;
191
199
  let nodesSize = 0;
192
200
  let item: unknown;
193
- let escaped: string;
201
+ let escaped: SerovalObjectRecordKey;
194
202
  for (const key of keys) {
195
203
  item = properties[key];
196
204
  escaped = serializeString(key);
@@ -200,13 +208,22 @@ function generateProperties(
200
208
  deferredSize++;
201
209
  } else {
202
210
  keyNodes[nodesSize] = escaped;
203
- valueNodes[nodesSize] = parse(ctx, item);
211
+ valueNodes[nodesSize] = parseSync(ctx, item);
204
212
  nodesSize++;
205
213
  }
206
214
  }
207
215
  for (let i = 0; i < deferredSize; i++) {
208
216
  keyNodes[nodesSize + i] = deferredKeys[i];
209
- valueNodes[nodesSize + i] = parse(ctx, deferredValues[i]);
217
+ valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
218
+ }
219
+ if (ctx.features & Feature.Symbol) {
220
+ if (Symbol.iterator in properties) {
221
+ keyNodes[size] = SerovalObjectRecordSpecialKey.SymbolIterator;
222
+ const items = Array.from(properties as Iterable<unknown>);
223
+ const id = createIndexedValue(ctx, items);
224
+ valueNodes[size] = generateArrayNode(ctx, id, items);
225
+ size++;
226
+ }
210
227
  }
211
228
  return {
212
229
  k: keyNodes,
@@ -215,40 +232,50 @@ function generateProperties(
215
232
  };
216
233
  }
217
234
 
218
- function generateIterableNode(
235
+ function generatePlainProperties(
219
236
  ctx: ParserContext,
220
- id: number,
221
- current: Iterable<unknown>,
222
- ): SerovalIterableNode {
223
- assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
224
- const options = getIterableOptions(current);
225
- const array = Array.from(current);
237
+ properties: Record<string, unknown>,
238
+ ): SerovalPlainRecordNode {
239
+ const keys = Object.keys(properties);
240
+ const size = keys.length;
241
+ const keyNodes = new Array<string>(size);
242
+ const valueNodes = new Array<SerovalNode>(size);
243
+ const deferredKeys = new Array<string>(size);
244
+ const deferredValues = new Array<unknown>(size);
245
+ let deferredSize = 0;
246
+ let nodesSize = 0;
247
+ let item: unknown;
248
+ let escaped: string;
249
+ for (const key of keys) {
250
+ item = properties[key];
251
+ escaped = serializeString(key);
252
+ if (isIterable(item)) {
253
+ deferredKeys[deferredSize] = escaped;
254
+ deferredValues[deferredSize] = item;
255
+ deferredSize++;
256
+ } else {
257
+ keyNodes[nodesSize] = escaped;
258
+ valueNodes[nodesSize] = parseSync(ctx, item);
259
+ nodesSize++;
260
+ }
261
+ }
262
+ for (let i = 0; i < deferredSize; i++) {
263
+ keyNodes[nodesSize + i] = deferredKeys[i];
264
+ valueNodes[nodesSize + i] = parseSync(ctx, deferredValues[i]);
265
+ }
226
266
  return {
227
- t: SerovalNodeType.Iterable,
228
- i: id,
229
- s: undefined,
230
- l: array.length,
231
- c: undefined,
232
- m: undefined,
233
- // Parse options first before the items
234
- d: options
235
- ? generateProperties(ctx, options)
236
- : undefined,
237
- a: generateNodeList(ctx, array),
238
- f: undefined,
239
- b: undefined,
267
+ k: keyNodes,
268
+ v: valueNodes,
269
+ s: size,
240
270
  };
241
271
  }
242
272
 
243
273
  function generateObjectNode(
244
274
  ctx: ParserContext,
245
275
  id: number,
246
- current: Record<string, unknown> | Iterable<unknown>,
276
+ current: Record<string, unknown>,
247
277
  empty: boolean,
248
278
  ): ObjectLikeNode {
249
- if (Symbol.iterator in current) {
250
- return generateIterableNode(ctx, id, current);
251
- }
252
279
  return {
253
280
  t: empty ? SerovalNodeType.NullConstructor : SerovalNodeType.Object,
254
281
  i: id,
@@ -260,6 +287,7 @@ function generateObjectNode(
260
287
  a: undefined,
261
288
  f: undefined,
262
289
  b: undefined,
290
+ o: getObjectFlag(current),
263
291
  };
264
292
  }
265
293
 
@@ -283,6 +311,7 @@ function generateAggregateErrorNode(
283
311
  a: undefined,
284
312
  f: undefined,
285
313
  b: undefined,
314
+ o: undefined,
286
315
  };
287
316
  }
288
317
 
@@ -306,6 +335,7 @@ function generateErrorNode(
306
335
  a: undefined,
307
336
  f: undefined,
308
337
  b: undefined,
338
+ o: undefined,
309
339
  };
310
340
  }
311
341
 
@@ -314,8 +344,9 @@ function generateHeadersNode(
314
344
  id: number,
315
345
  current: Headers,
316
346
  ): SerovalHeadersNode {
317
- assert(ctx.features & Feature.WebAPI, 'Unsupported type "Headers"');
347
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
318
348
  const items: Record<string, string> = {};
349
+ // TS Headers not an Iterable
319
350
  current.forEach((value, key) => {
320
351
  items[key] = value;
321
352
  });
@@ -326,10 +357,11 @@ function generateHeadersNode(
326
357
  l: undefined,
327
358
  c: undefined,
328
359
  m: undefined,
329
- d: generateProperties(ctx, items),
360
+ d: generatePlainProperties(ctx, items),
330
361
  a: undefined,
331
362
  f: undefined,
332
363
  b: undefined,
364
+ o: undefined,
333
365
  };
334
366
  }
335
367
 
@@ -338,8 +370,9 @@ function generateFormDataNode(
338
370
  id: number,
339
371
  current: FormData,
340
372
  ): SerovalFormDataNode {
341
- assert(ctx.features & Feature.WebAPI, 'Unsupported type "FormData"');
373
+ assert(ctx.features & Feature.WebAPI, new UnsupportedTypeError(current));
342
374
  const items: Record<string, FormDataEntryValue> = {};
375
+ // TS FormData isn't an Iterable sadly
343
376
  current.forEach((value, key) => {
344
377
  items[key] = value;
345
378
  });
@@ -350,14 +383,147 @@ function generateFormDataNode(
350
383
  l: undefined,
351
384
  c: undefined,
352
385
  m: undefined,
353
- d: generateProperties(ctx, items),
386
+ d: generatePlainProperties(ctx, items),
354
387
  a: undefined,
355
388
  f: undefined,
356
389
  b: undefined,
390
+ o: undefined,
357
391
  };
358
392
  }
359
393
 
360
- function parse<T>(
394
+ function generateBoxedNode(
395
+ ctx: ParserContext,
396
+ id: number,
397
+ current: object,
398
+ ): SerovalBoxedNode {
399
+ return {
400
+ t: SerovalNodeType.Boxed,
401
+ i: id,
402
+ s: undefined,
403
+ l: undefined,
404
+ c: undefined,
405
+ m: undefined,
406
+ d: undefined,
407
+ a: undefined,
408
+ f: parseSync(ctx, current.valueOf()),
409
+ b: undefined,
410
+ o: undefined,
411
+ };
412
+ }
413
+
414
+ function parseObject(
415
+ ctx: ParserContext,
416
+ current: object | null,
417
+ ): SerovalNode {
418
+ if (!current) {
419
+ return NULL_NODE;
420
+ }
421
+ // Non-primitive values needs a reference ID
422
+ // mostly because the values themselves are stateful
423
+ const id = createIndexedValue(ctx, current);
424
+ if (ctx.markedRefs.has(id)) {
425
+ return createIndexedValueNode(id);
426
+ }
427
+ if (hasReferenceID(current)) {
428
+ return createReferenceNode(id, current);
429
+ }
430
+ // Well well well
431
+ if (Array.isArray(current)) {
432
+ return generateArrayNode(ctx, id, current);
433
+ }
434
+ // Fast path
435
+ switch (current.constructor) {
436
+ case Number:
437
+ case Boolean:
438
+ case String:
439
+ case BigInt:
440
+ case Function:
441
+ case Symbol:
442
+ return generateBoxedNode(ctx, id, current);
443
+ case Date:
444
+ return createDateNode(id, current as unknown as Date);
445
+ case RegExp:
446
+ return createRegExpNode(id, current as unknown as RegExp);
447
+ case ArrayBuffer:
448
+ return createArrayBufferNode(id, current as unknown as ArrayBuffer);
449
+ case Int8Array:
450
+ case Int16Array:
451
+ case Int32Array:
452
+ case Uint8Array:
453
+ case Uint16Array:
454
+ case Uint32Array:
455
+ case Uint8ClampedArray:
456
+ case Float32Array:
457
+ case Float64Array:
458
+ return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
459
+ case BigInt64Array:
460
+ case BigUint64Array:
461
+ return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
462
+ case DataView:
463
+ return createDataViewNode(ctx, id, current as unknown as DataView);
464
+ case Map:
465
+ return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
466
+ case Set:
467
+ return generateSetNode(ctx, id, current as unknown as Set<unknown>);
468
+ case Object:
469
+ return generateObjectNode(
470
+ ctx,
471
+ id,
472
+ current as unknown as Record<string, unknown>,
473
+ false,
474
+ );
475
+ case undefined:
476
+ return generateObjectNode(
477
+ ctx,
478
+ id,
479
+ current as unknown as Record<string, unknown>,
480
+ true,
481
+ );
482
+ case AggregateError:
483
+ // Compile-down AggregateError to Error if disabled
484
+ if (ctx.features & Feature.AggregateError) {
485
+ return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
486
+ }
487
+ return generateErrorNode(ctx, id, current as unknown as AggregateError);
488
+ case Error:
489
+ case EvalError:
490
+ case RangeError:
491
+ case ReferenceError:
492
+ case SyntaxError:
493
+ case TypeError:
494
+ case URIError:
495
+ return generateErrorNode(ctx, id, current as unknown as Error);
496
+ case URL:
497
+ return createURLNode(ctx, id, current as unknown as URL);
498
+ case URLSearchParams:
499
+ return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
500
+ case Headers:
501
+ return generateHeadersNode(ctx, id, current as unknown as Headers);
502
+ case FormData:
503
+ return generateFormDataNode(ctx, id, current as unknown as FormData);
504
+ default:
505
+ break;
506
+ }
507
+ // Slow path. We only need to handle Errors and Iterators
508
+ // since they have very broad implementations.
509
+ if (current instanceof AggregateError) {
510
+ if (ctx.features & Feature.AggregateError) {
511
+ return generateAggregateErrorNode(ctx, id, current);
512
+ }
513
+ return generateErrorNode(ctx, id, current);
514
+ }
515
+ if (current instanceof Error) {
516
+ return generateErrorNode(ctx, id, current);
517
+ }
518
+ // Generator functions don't have a global constructor
519
+ // despite existing
520
+ if (Symbol.iterator in current) {
521
+ return generateObjectNode(ctx, id, current, !!current.constructor);
522
+ }
523
+ throw new UnsupportedTypeError(current);
524
+ }
525
+
526
+ export default function parseSync<T>(
361
527
  ctx: ParserContext,
362
528
  current: T,
363
529
  ): SerovalNode {
@@ -369,144 +535,16 @@ function parse<T>(
369
535
  case 'string':
370
536
  return createStringNode(current);
371
537
  case 'number':
372
- switch (current) {
373
- case Infinity: return INFINITY_NODE;
374
- case -Infinity: return NEG_INFINITY_NODE;
375
- default:
376
- // eslint-disable-next-line no-self-compare
377
- if (current !== current) {
378
- return NAN_NODE;
379
- }
380
- if (Object.is(current, -0)) {
381
- return NEG_ZERO_NODE;
382
- }
383
- return createNumberNode(current);
384
- }
538
+ return createNumberNode(current);
385
539
  case 'bigint':
386
540
  return createBigIntNode(ctx, current);
387
- case 'object': {
388
- if (!current) {
389
- return NULL_NODE;
390
- }
391
- // Non-primitive values needs a reference ID
392
- // mostly because the values themselves are stateful
393
- const id = createIndexedValue(ctx, current);
394
- if (ctx.markedRefs.has(id)) {
395
- return createIndexedValueNode(id);
396
- }
397
- if (hasReferenceID(current)) {
398
- return createReferenceNode(id, current);
399
- }
400
- if (Array.isArray(current)) {
401
- return generateArrayNode(ctx, id, current);
402
- }
403
- switch (current.constructor) {
404
- case Date:
405
- return createDateNode(id, current as unknown as Date);
406
- case RegExp:
407
- return createRegExpNode(id, current as unknown as RegExp);
408
- case ArrayBuffer:
409
- return createArrayBufferNode(id, current as unknown as ArrayBuffer);
410
- case Int8Array:
411
- case Int16Array:
412
- case Int32Array:
413
- case Uint8Array:
414
- case Uint16Array:
415
- case Uint32Array:
416
- case Uint8ClampedArray:
417
- case Float32Array:
418
- case Float64Array:
419
- return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
420
- case BigInt64Array:
421
- case BigUint64Array:
422
- return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
423
- case DataView:
424
- return createDataViewNode(ctx, id, current as unknown as DataView);
425
- case Map:
426
- return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
427
- case Set:
428
- return generateSetNode(ctx, id, current as unknown as Set<unknown>);
429
- case Object:
430
- return generateObjectNode(
431
- ctx,
432
- id,
433
- current as unknown as Record<string, unknown>,
434
- false,
435
- );
436
- case undefined:
437
- return generateObjectNode(
438
- ctx,
439
- id,
440
- current as unknown as Record<string, unknown>,
441
- true,
442
- );
443
- case AggregateError:
444
- if (ctx.features & Feature.AggregateError) {
445
- return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
446
- }
447
- return generateErrorNode(ctx, id, current as unknown as AggregateError);
448
- case Error:
449
- case EvalError:
450
- case RangeError:
451
- case ReferenceError:
452
- case SyntaxError:
453
- case TypeError:
454
- case URIError:
455
- return generateErrorNode(ctx, id, current as unknown as Error);
456
- case URL:
457
- return createURLNode(ctx, id, current as unknown as URL);
458
- case URLSearchParams:
459
- return createURLSearchParamsNode(ctx, id, current as unknown as URLSearchParams);
460
- case Headers:
461
- return generateHeadersNode(ctx, id, current as unknown as Headers);
462
- case FormData:
463
- return generateFormDataNode(ctx, id, current as unknown as FormData);
464
- default:
465
- break;
466
- }
467
- if (current instanceof AggregateError) {
468
- if (ctx.features & Feature.AggregateError) {
469
- return generateAggregateErrorNode(ctx, id, current);
470
- }
471
- return generateErrorNode(ctx, id, current);
472
- }
473
- if (current instanceof Error) {
474
- return generateErrorNode(ctx, id, current);
475
- }
476
- // Generator functions don't have a global constructor
477
- if (Symbol.iterator in current) {
478
- return generateIterableNode(ctx, id, current as Iterable<unknown>);
479
- }
480
- throw new Error('Unsupported type');
481
- }
541
+ case 'object':
542
+ return parseObject(ctx, current);
482
543
  case 'symbol':
483
- if (hasReferenceID(current)) {
484
- const id = createIndexedValue(ctx, current);
485
- if (ctx.markedRefs.has(id)) {
486
- return createIndexedValueNode(id);
487
- }
488
- return createReferenceNode(id, current);
489
- }
490
- return createWKSymbolNode(ctx, current as WellKnownSymbols);
491
- case 'function': {
492
- assert(hasReferenceID(current), 'Cannot serialize function without reference ID.');
493
- const id = createIndexedValue(ctx, current);
494
- if (ctx.markedRefs.has(id)) {
495
- return createIndexedValueNode(id);
496
- }
497
- return createReferenceNode(id, current);
498
- }
544
+ return createSymbolNode(ctx, current);
545
+ case 'function':
546
+ return createFunctionNode(ctx, current);
499
547
  default:
500
- throw new Error('Unsupported type');
548
+ throw new UnsupportedTypeError(current);
501
549
  }
502
550
  }
503
-
504
- export default function parseSync<T>(
505
- ctx: ParserContext,
506
- current: T,
507
- ) {
508
- const result = parse(ctx, current);
509
- const isObject = result.t === SerovalNodeType.Object
510
- || result.t === SerovalNodeType.Iterable;
511
- return [result, getRootID(ctx, current), isObject] as const;
512
- }