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