seroval 0.5.1 → 0.6.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.
@@ -7,6 +7,7 @@ import {
7
7
  markRef,
8
8
  } from '../context';
9
9
  import quote from '../quote';
10
+ import { GLOBAL_KEY } from './reference';
10
11
  import { isValidIdentifier } from './shared';
11
12
  import { SYMBOL_STRING } from './symbols';
12
13
  import {
@@ -22,7 +23,7 @@ import {
22
23
  SerovalObjectNode,
23
24
  SerovalObjectRecordNode,
24
25
  SerovalPromiseNode,
25
- SerovalReferenceNode,
26
+ SerovalIndexedValueNode,
26
27
  SerovalSetNode,
27
28
  SerovalTypedArrayNode,
28
29
  } from './types';
@@ -194,7 +195,7 @@ function createObjectAssign(
194
195
  createAssignment(ctx, getRefParam(ctx, ref) + '.' + key, value);
195
196
  }
196
197
 
197
- function assignRef(
198
+ function assignIndexedValue(
198
199
  ctx: SerializationContext,
199
200
  index: number,
200
201
  value: string,
@@ -205,11 +206,11 @@ function assignRef(
205
206
  return value;
206
207
  }
207
208
 
208
- function isReferenceInStack(
209
+ function isIndexedValueInStack(
209
210
  ctx: SerializationContext,
210
211
  node: SerovalNode,
211
- ): node is SerovalReferenceNode {
212
- return node.t === SerovalNodeType.Reference && ctx.stack.includes(node.i);
212
+ ): node is SerovalIndexedValueNode {
213
+ return node.t === SerovalNodeType.IndexedValue && ctx.stack.includes(node.i);
213
214
  }
214
215
 
215
216
  function serializeNodeList(
@@ -232,7 +233,7 @@ function serializeNodeList(
232
233
  // Check if index is a hole
233
234
  if (item) {
234
235
  // Check if item is a parent
235
- if (isReferenceInStack(ctx, item)) {
236
+ if (isIndexedValueInStack(ctx, item)) {
236
237
  createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
237
238
  isHoley = true;
238
239
  } else {
@@ -253,7 +254,7 @@ function serializeArray(
253
254
  ctx.stack.push(node.i);
254
255
  const result = serializeNodeList(ctx, node);
255
256
  ctx.stack.pop();
256
- return assignRef(ctx, node.i, result);
257
+ return assignIndexedValue(ctx, node.i, result);
257
258
  }
258
259
 
259
260
  function serializeProperties(
@@ -279,7 +280,7 @@ function serializeProperties(
279
280
  // Test if key is a valid number or JS identifier
280
281
  // so that we don't have to serialize the key and wrap with brackets
281
282
  isIdentifier = check >= 0 || isValidIdentifier(key);
282
- if (isReferenceInStack(ctx, val)) {
283
+ if (isIndexedValueInStack(ctx, val)) {
283
284
  refParam = getRefParam(ctx, val.i);
284
285
  if (isIdentifier && Number.isNaN(check)) {
285
286
  createObjectAssign(ctx, sourceID, key, refParam);
@@ -359,11 +360,11 @@ function serializeDictionary(
359
360
  markRef(ctx, i);
360
361
  const assignments = serializeAssignments(ctx, i, d);
361
362
  if (assignments) {
362
- return '(' + assignRef(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
363
+ return '(' + assignIndexedValue(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
363
364
  }
364
365
  }
365
366
  }
366
- return assignRef(ctx, i, init);
367
+ return assignIndexedValue(ctx, i, init);
367
368
  }
368
369
 
369
370
  function serializeNullConstructor(
@@ -377,7 +378,7 @@ function serializeObject(
377
378
  ctx: SerializationContext,
378
379
  node: SerovalObjectNode,
379
380
  ) {
380
- return assignRef(ctx, node.i, serializeProperties(ctx, node.i, node.d));
381
+ return assignIndexedValue(ctx, node.i, serializeProperties(ctx, node.i, node.d));
381
382
  }
382
383
 
383
384
  function serializeSet(
@@ -393,7 +394,7 @@ function serializeSet(
393
394
  let hasPrev = false;
394
395
  for (let i = 0; i < size; i++) {
395
396
  item = node.a[i];
396
- if (isReferenceInStack(ctx, item)) {
397
+ if (isIndexedValueInStack(ctx, item)) {
397
398
  createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
398
399
  } else {
399
400
  // Push directly
@@ -406,7 +407,7 @@ function serializeSet(
406
407
  serialized += '([' + result + '])';
407
408
  }
408
409
  }
409
- return assignRef(ctx, node.i, serialized);
410
+ return assignIndexedValue(ctx, node.i, serialized);
410
411
  }
411
412
 
412
413
  function serializeMap(
@@ -427,11 +428,11 @@ function serializeMap(
427
428
  // Check if key is a parent
428
429
  key = node.d.k[i];
429
430
  val = node.d.v[i];
430
- if (isReferenceInStack(ctx, key)) {
431
+ if (isIndexedValueInStack(ctx, key)) {
431
432
  // Create reference for the map instance
432
433
  keyRef = getRefParam(ctx, key.i);
433
434
  // Check if value is a parent
434
- if (isReferenceInStack(ctx, val)) {
435
+ if (isIndexedValueInStack(ctx, val)) {
435
436
  valueRef = getRefParam(ctx, val.i);
436
437
  // Register an assignment since
437
438
  // both key and value are a parent of this
@@ -448,7 +449,7 @@ function serializeMap(
448
449
  createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
449
450
  ctx.stack = parent;
450
451
  }
451
- } else if (isReferenceInStack(ctx, val)) {
452
+ } else if (isIndexedValueInStack(ctx, val)) {
452
453
  // Create ref for the Map instance
453
454
  valueRef = getRefParam(ctx, val.i);
454
455
  // Reset stack for the key serialization
@@ -469,7 +470,7 @@ function serializeMap(
469
470
  serialized += '([' + result + '])';
470
471
  }
471
472
  }
472
- return assignRef(ctx, node.i, serialized);
473
+ return assignIndexedValue(ctx, node.i, serialized);
473
474
  }
474
475
 
475
476
  function serializeAggregateError(
@@ -500,7 +501,7 @@ function serializePromise(
500
501
  ) {
501
502
  let serialized: string;
502
503
  // Check if resolved value is a parent expression
503
- if (isReferenceInStack(ctx, node.f)) {
504
+ if (isIndexedValueInStack(ctx, node.f)) {
504
505
  // A Promise trick, reference the value
505
506
  // inside the `then` expression so that
506
507
  // the Promise evaluates after the parent
@@ -518,7 +519,7 @@ function serializePromise(
518
519
  // just inline the value/reference here
519
520
  serialized = 'Promise.resolve(' + result + ')';
520
521
  }
521
- return assignRef(ctx, node.i, serialized);
522
+ return assignIndexedValue(ctx, node.i, serialized);
522
523
  }
523
524
 
524
525
  function serializeTypedArray(
@@ -531,7 +532,7 @@ function serializeTypedArray(
531
532
  result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
532
533
  }
533
534
  const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
534
- return assignRef(ctx, node.i, 'new ' + node.c + '(' + args + ')');
535
+ return assignIndexedValue(ctx, node.i, 'new ' + node.c + '(' + args + ')');
535
536
  }
536
537
 
537
538
  function serializeIterable(
@@ -583,7 +584,7 @@ export default function serializeTree(
583
584
  return 'NaN';
584
585
  case SerovalNodeType.BigInt:
585
586
  return node.s + 'n';
586
- case SerovalNodeType.Reference:
587
+ case SerovalNodeType.IndexedValue:
587
588
  return getRefParam(ctx, node.i);
588
589
  case SerovalNodeType.Array:
589
590
  return serializeArray(ctx, node);
@@ -592,9 +593,9 @@ export default function serializeTree(
592
593
  case SerovalNodeType.NullConstructor:
593
594
  return serializeNullConstructor(ctx, node);
594
595
  case SerovalNodeType.Date:
595
- return assignRef(ctx, node.i, 'new Date("' + node.s + '")');
596
+ return assignIndexedValue(ctx, node.i, 'new Date("' + node.s + '")');
596
597
  case SerovalNodeType.RegExp:
597
- return assignRef(ctx, node.i, '/' + node.c + '/' + node.m);
598
+ return assignIndexedValue(ctx, node.i, '/' + node.c + '/' + node.m);
598
599
  case SerovalNodeType.Set:
599
600
  return serializeSet(ctx, node);
600
601
  case SerovalNodeType.Map:
@@ -612,6 +613,12 @@ export default function serializeTree(
612
613
  return serializePromise(ctx, node);
613
614
  case SerovalNodeType.WKSymbol:
614
615
  return SYMBOL_STRING[node.s];
616
+ case SerovalNodeType.URL:
617
+ return assignIndexedValue(ctx, node.i, 'new URL("' + node.s + '")');
618
+ case SerovalNodeType.URLSearchParams:
619
+ return assignIndexedValue(ctx, node.i, node.s ? 'new URLSearchParams("' + node.s + '")' : 'new URLSearchParams');
620
+ case SerovalNodeType.Reference:
621
+ return assignIndexedValue(ctx, node.i, GLOBAL_KEY + '.get("' + node.s + '")');
615
622
  default:
616
623
  throw new Error('Unsupported type');
617
624
  }
package/src/tree/sync.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/no-use-before-define */
2
2
  import assert from '../assert';
3
3
  import { Feature } from '../compat';
4
- import { createRef, getRootID, ParserContext } from '../context';
5
- import { BigIntTypedArrayValue, ServerValue, TypedArrayValue } from '../types';
4
+ import { createIndexedValue, getRootID, ParserContext } from '../context';
5
+ import quote from '../quote';
6
+ import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
6
7
  import {
7
8
  createBigIntNode,
8
9
  createBigIntTypedArrayNode,
9
10
  createDateNode,
10
11
  createNumberNode,
11
- createReferenceNode,
12
+ createIndexedValueNode,
12
13
  createRegExpNode,
13
14
  createStringNode,
14
15
  createTypedArrayNode,
@@ -21,14 +22,18 @@ import {
21
22
  NULL_NODE,
22
23
  TRUE_NODE,
23
24
  UNDEFINED_NODE,
25
+ createReferenceNode,
24
26
  } from './primitives';
27
+ import {
28
+ hasReferenceID,
29
+ } from './reference';
25
30
  import {
26
31
  getErrorConstructorName,
27
32
  getErrorOptions,
28
33
  getIterableOptions,
29
34
  isIterable,
30
35
  } from './shared';
31
- import { INV_SYMBOL_REF } from './symbols';
36
+ import { WellKnownSymbols } from './symbols';
32
37
  import {
33
38
  SerovalAggregateErrorNode,
34
39
  SerovalArrayNode,
@@ -42,14 +47,15 @@ import {
42
47
  SerovalObjectRecordNode,
43
48
  SerovalSetNode,
44
49
  } from './types';
50
+ import { createURLNode, createURLSearchParamsNode } from './web-api';
45
51
 
46
52
  type ObjectLikeNode = SerovalObjectNode | SerovalNullConstructorNode | SerovalIterableNode;
47
53
 
48
- function generateNodeList(ctx: ParserContext, current: ServerValue[]) {
54
+ function generateNodeList(ctx: ParserContext, current: unknown[]) {
49
55
  const size = current.length;
50
56
  const nodes = new Array<SerovalNode>(size);
51
- const deferred = new Array<ServerValue>(size);
52
- let item: ServerValue;
57
+ const deferred = new Array<unknown>(size);
58
+ let item: unknown;
53
59
  for (let i = 0; i < size; i++) {
54
60
  if (i in current) {
55
61
  item = current[i];
@@ -71,7 +77,7 @@ function generateNodeList(ctx: ParserContext, current: ServerValue[]) {
71
77
  function generateArrayNode(
72
78
  ctx: ParserContext,
73
79
  id: number,
74
- current: ServerValue[],
80
+ current: unknown[],
75
81
  ): SerovalArrayNode {
76
82
  return {
77
83
  t: SerovalNodeType.Array,
@@ -89,14 +95,14 @@ function generateArrayNode(
89
95
  function generateMapNode(
90
96
  ctx: ParserContext,
91
97
  id: number,
92
- current: Map<ServerValue, ServerValue>,
98
+ current: Map<unknown, unknown>,
93
99
  ): SerovalMapNode {
94
100
  assert(ctx.features & Feature.Map, 'Unsupported type "Map"');
95
101
  const len = current.size;
96
102
  const keyNodes = new Array<SerovalNode>(len);
97
103
  const valueNodes = new Array<SerovalNode>(len);
98
- const deferredKey = new Array<ServerValue>(len);
99
- const deferredValue = new Array<ServerValue>(len);
104
+ const deferredKey = new Array<unknown>(len);
105
+ const deferredValue = new Array<unknown>(len);
100
106
  let deferredSize = 0;
101
107
  let nodeSize = 0;
102
108
  for (const [key, value] of current.entries()) {
@@ -131,12 +137,12 @@ function generateMapNode(
131
137
  function generateSetNode(
132
138
  ctx: ParserContext,
133
139
  id: number,
134
- current: Set<ServerValue>,
140
+ current: Set<unknown>,
135
141
  ): SerovalSetNode {
136
142
  assert(ctx.features & Feature.Set, 'Unsupported type "Set"');
137
143
  const len = current.size;
138
144
  const nodes = new Array<SerovalNode>(len);
139
- const deferred = new Array<ServerValue>(len);
145
+ const deferred = new Array<unknown>(len);
140
146
  let deferredSize = 0;
141
147
  let nodeSize = 0;
142
148
  for (const item of current.keys()) {
@@ -166,17 +172,17 @@ function generateSetNode(
166
172
 
167
173
  function generateProperties(
168
174
  ctx: ParserContext,
169
- properties: Record<string, ServerValue>,
175
+ properties: Record<string, unknown>,
170
176
  ): SerovalObjectRecordNode {
171
177
  const keys = Object.keys(properties);
172
178
  const size = keys.length;
173
179
  const keyNodes = new Array<string>(size);
174
180
  const valueNodes = new Array<SerovalNode>(size);
175
181
  const deferredKeys = new Array<string>(size);
176
- const deferredValues = new Array<ServerValue>(size);
182
+ const deferredValues = new Array<unknown>(size);
177
183
  let deferredSize = 0;
178
184
  let nodesSize = 0;
179
- let item: ServerValue;
185
+ let item: unknown;
180
186
  for (const key of keys) {
181
187
  item = properties[key];
182
188
  if (isIterable(item)) {
@@ -203,7 +209,7 @@ function generateProperties(
203
209
  function generateIterableNode(
204
210
  ctx: ParserContext,
205
211
  id: number,
206
- current: Iterable<ServerValue>,
212
+ current: Iterable<unknown>,
207
213
  ): SerovalIterableNode {
208
214
  assert(ctx.features & Feature.Symbol, 'Unsupported type "Iterable"');
209
215
  const options = getIterableOptions(current);
@@ -217,7 +223,7 @@ function generateIterableNode(
217
223
  m: undefined,
218
224
  // Parse options first before the items
219
225
  d: options
220
- ? generateProperties(ctx, options as Record<string, ServerValue>)
226
+ ? generateProperties(ctx, options)
221
227
  : undefined,
222
228
  a: generateNodeList(ctx, array),
223
229
  f: undefined,
@@ -227,7 +233,7 @@ function generateIterableNode(
227
233
  function generateObjectNode(
228
234
  ctx: ParserContext,
229
235
  id: number,
230
- current: Record<string, ServerValue> | Iterable<ServerValue>,
236
+ current: Record<string, unknown> | Iterable<unknown>,
231
237
  empty: boolean,
232
238
  ): ObjectLikeNode {
233
239
  if (Symbol.iterator in current) {
@@ -261,9 +267,9 @@ function generateAggregateErrorNode(
261
267
  s: undefined,
262
268
  l: current.errors.length,
263
269
  c: undefined,
264
- m: current.message,
270
+ m: quote(current.message),
265
271
  d: optionsNode,
266
- a: generateNodeList(ctx, current.errors as ServerValue[]),
272
+ a: generateNodeList(ctx, current.errors as unknown[]),
267
273
  f: undefined,
268
274
  };
269
275
  }
@@ -283,16 +289,16 @@ function generateErrorNode(
283
289
  s: undefined,
284
290
  l: undefined,
285
291
  c: getErrorConstructorName(current),
286
- m: current.message,
292
+ m: quote(current.message),
287
293
  d: optionsNode,
288
294
  a: undefined,
289
295
  f: undefined,
290
296
  };
291
297
  }
292
298
 
293
- function parse(
299
+ function parse<T>(
294
300
  ctx: ParserContext,
295
- current: ServerValue,
301
+ current: T,
296
302
  ): SerovalNode {
297
303
  switch (typeof current) {
298
304
  case 'boolean':
@@ -305,16 +311,16 @@ function parse(
305
311
  switch (current) {
306
312
  case Infinity: return INFINITY_NODE;
307
313
  case -Infinity: return NEG_INFINITY_NODE;
308
- default: break;
309
- }
310
- // eslint-disable-next-line no-self-compare
311
- if (current !== current) {
312
- return NAN_NODE;
313
- }
314
- if (Object.is(current, -0)) {
315
- return NEG_ZERO_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);
316
323
  }
317
- return createNumberNode(current);
318
324
  case 'bigint':
319
325
  return createBigIntNode(ctx, current);
320
326
  case 'object': {
@@ -323,18 +329,21 @@ function parse(
323
329
  }
324
330
  // Non-primitive values needs a reference ID
325
331
  // mostly because the values themselves are stateful
326
- const id = createRef(ctx, current);
332
+ const id = createIndexedValue(ctx, current);
327
333
  if (ctx.markedRefs.has(id)) {
328
- return createReferenceNode(id);
334
+ return createIndexedValueNode(id);
335
+ }
336
+ if (hasReferenceID(current)) {
337
+ return createReferenceNode(id, current);
329
338
  }
330
339
  if (Array.isArray(current)) {
331
340
  return generateArrayNode(ctx, id, current);
332
341
  }
333
342
  switch (current.constructor) {
334
343
  case Date:
335
- return createDateNode(id, current as Date);
344
+ return createDateNode(id, current as unknown as Date);
336
345
  case RegExp:
337
- return createRegExpNode(id, current as RegExp);
346
+ return createRegExpNode(id, current as unknown as RegExp);
338
347
  case Int8Array:
339
348
  case Int16Array:
340
349
  case Int32Array:
@@ -344,23 +353,33 @@ function parse(
344
353
  case Uint8ClampedArray:
345
354
  case Float32Array:
346
355
  case Float64Array:
347
- return createTypedArrayNode(ctx, id, current as TypedArrayValue);
356
+ return createTypedArrayNode(ctx, id, current as unknown as TypedArrayValue);
348
357
  case BigInt64Array:
349
358
  case BigUint64Array:
350
- return createBigIntTypedArrayNode(ctx, id, current as BigIntTypedArrayValue);
359
+ return createBigIntTypedArrayNode(ctx, id, current as unknown as BigIntTypedArrayValue);
351
360
  case Map:
352
- return generateMapNode(ctx, id, current as Map<ServerValue, ServerValue>);
361
+ return generateMapNode(ctx, id, current as unknown as Map<unknown, unknown>);
353
362
  case Set:
354
- return generateSetNode(ctx, id, current as Set<ServerValue>);
363
+ return generateSetNode(ctx, id, current as unknown as Set<unknown>);
355
364
  case Object:
356
- return generateObjectNode(ctx, id, current as Record<string, ServerValue>, false);
365
+ return generateObjectNode(
366
+ ctx,
367
+ id,
368
+ current as unknown as Record<string, unknown>,
369
+ false,
370
+ );
357
371
  case undefined:
358
- return generateObjectNode(ctx, id, current as Record<string, ServerValue>, true);
372
+ return generateObjectNode(
373
+ ctx,
374
+ id,
375
+ current as unknown as Record<string, unknown>,
376
+ true,
377
+ );
359
378
  case AggregateError:
360
379
  if (ctx.features & Feature.AggregateError) {
361
- return generateAggregateErrorNode(ctx, id, current as AggregateError);
380
+ return generateAggregateErrorNode(ctx, id, current as unknown as AggregateError);
362
381
  }
363
- return generateErrorNode(ctx, id, current as AggregateError);
382
+ return generateErrorNode(ctx, id, current as unknown as AggregateError);
364
383
  case Error:
365
384
  case EvalError:
366
385
  case RangeError:
@@ -368,7 +387,11 @@ function parse(
368
387
  case SyntaxError:
369
388
  case TypeError:
370
389
  case URIError:
371
- return generateErrorNode(ctx, id, current as Error);
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);
372
395
  default:
373
396
  break;
374
397
  }
@@ -383,22 +406,35 @@ function parse(
383
406
  }
384
407
  // Generator functions don't have a global constructor
385
408
  if (Symbol.iterator in current) {
386
- return generateIterableNode(ctx, id, current);
409
+ return generateIterableNode(ctx, id, current as Iterable<unknown>);
387
410
  }
388
411
  throw new Error('Unsupported type');
389
412
  }
390
413
  case 'symbol':
391
- assert(ctx.features & Feature.Symbol, 'Unsupported type "symbol"');
392
- assert(current in INV_SYMBOL_REF, 'seroval only supports well-known symbols');
393
- return createWKSymbolNode(current);
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
+ }
394
430
  default:
395
431
  throw new Error('Unsupported type');
396
432
  }
397
433
  }
398
434
 
399
- export default function parseSync(
435
+ export default function parseSync<T>(
400
436
  ctx: ParserContext,
401
- current: ServerValue,
437
+ current: T,
402
438
  ) {
403
439
  const result = parse(ctx, current);
404
440
  const isObject = result.t === SerovalNodeType.Object
package/src/tree/types.ts CHANGED
@@ -11,7 +11,7 @@ export const enum SerovalNodeType {
11
11
  NegativeInfinity,
12
12
  NaN,
13
13
  BigInt,
14
- Reference,
14
+ IndexedValue,
15
15
  Date,
16
16
  RegExp,
17
17
  Set,
@@ -26,6 +26,9 @@ export const enum SerovalNodeType {
26
26
  TypedArray,
27
27
  BigIntTypedArray,
28
28
  WKSymbol,
29
+ URL,
30
+ URLSearchParams,
31
+ Reference,
29
32
  }
30
33
 
31
34
  export interface SerovalBaseNode {
@@ -115,8 +118,8 @@ export type SerovalPrimitiveNode =
115
118
  | SerovalInfinityNode
116
119
  | SerovalNaNNode;
117
120
 
118
- export interface SerovalReferenceNode extends SerovalBaseNode {
119
- t: SerovalNodeType.Reference;
121
+ export interface SerovalIndexedValueNode extends SerovalBaseNode {
122
+ t: SerovalNodeType.IndexedValue;
120
123
  i: number;
121
124
  }
122
125
 
@@ -231,9 +234,27 @@ export interface SerovalWKSymbolNode extends SerovalBaseNode {
231
234
  s: Symbols;
232
235
  }
233
236
 
237
+ export interface SerovalURLNode extends SerovalBaseNode {
238
+ t: SerovalNodeType.URL;
239
+ i: number;
240
+ s: string;
241
+ }
242
+
243
+ export interface SerovalURLSearchParamsNode extends SerovalBaseNode {
244
+ t: SerovalNodeType.URLSearchParams;
245
+ i: number;
246
+ s: string;
247
+ }
248
+
249
+ export interface SerovalReferenceNode extends SerovalBaseNode {
250
+ t: SerovalNodeType.Reference;
251
+ i: number;
252
+ s: string;
253
+ }
254
+
234
255
  export type SerovalNode =
235
256
  | SerovalPrimitiveNode
236
- | SerovalReferenceNode
257
+ | SerovalIndexedValueNode
237
258
  | SerovalSemiPrimitiveNode
238
259
  | SerovalSetNode
239
260
  | SerovalMapNode
@@ -244,4 +265,7 @@ export type SerovalNode =
244
265
  | SerovalErrorNode
245
266
  | SerovalAggregateErrorNode
246
267
  | SerovalIterableNode
247
- | SerovalWKSymbolNode;
268
+ | SerovalWKSymbolNode
269
+ | SerovalURLNode
270
+ | SerovalURLSearchParamsNode
271
+ | SerovalReferenceNode;
@@ -0,0 +1,42 @@
1
+ import assert from '../assert';
2
+ import { Feature } from '../compat';
3
+ import { ParserContext } from '../context';
4
+ import { SerovalNodeType, SerovalURLNode, SerovalURLSearchParamsNode } from './types';
5
+
6
+ export function createURLNode(
7
+ ctx: ParserContext,
8
+ id: number,
9
+ current: URL,
10
+ ): SerovalURLNode {
11
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "URL"');
12
+ return {
13
+ t: SerovalNodeType.URL,
14
+ i: id,
15
+ s: current.href,
16
+ l: undefined,
17
+ c: undefined,
18
+ m: undefined,
19
+ d: undefined,
20
+ f: undefined,
21
+ a: undefined,
22
+ };
23
+ }
24
+
25
+ export function createURLSearchParamsNode(
26
+ ctx: ParserContext,
27
+ id: number,
28
+ current: URLSearchParams,
29
+ ): SerovalURLSearchParamsNode {
30
+ assert(ctx.features & Feature.WebAPI, 'Unsupported type "URLSearchParams"');
31
+ return {
32
+ t: SerovalNodeType.URLSearchParams,
33
+ i: id,
34
+ s: current.toString(),
35
+ l: undefined,
36
+ c: undefined,
37
+ m: undefined,
38
+ d: undefined,
39
+ f: undefined,
40
+ a: undefined,
41
+ };
42
+ }
package/src/types.ts CHANGED
@@ -34,12 +34,17 @@ export type BigIntTypedArrayValue =
34
34
  | BigInt64Array
35
35
  | BigUint64Array;
36
36
 
37
+ export type WebAPIValue =
38
+ | URL
39
+ | URLSearchParams;
40
+
37
41
  export type SemiPrimitiveValue =
38
42
  | RegExp
39
43
  | Date
40
44
  | TypedArrayValue
41
45
  | BigIntTypedArrayValue
42
- | bigint;
46
+ | bigint
47
+ | WebAPIValue;
43
48
 
44
49
  export type CommonServerValue =
45
50
  | PrimitiveValue