seroval 0.5.0 → 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.
@@ -3,6 +3,7 @@ import { Feature } from '../compat';
3
3
  import { ParserContext } from '../context';
4
4
  import quote from '../quote';
5
5
  import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
6
+ import { getReferenceID } from './reference';
6
7
  import { INV_SYMBOL_REF, WellKnownSymbols } from './symbols';
7
8
  import {
8
9
  SerovalBigIntNode,
@@ -16,12 +17,13 @@ import {
16
17
  SerovalNodeType,
17
18
  SerovalNullNode,
18
19
  SerovalNumberNode,
19
- SerovalReferenceNode,
20
+ SerovalIndexedValueNode,
20
21
  SerovalRegExpNode,
21
22
  SerovalStringNode,
22
23
  SerovalTypedArrayNode,
23
24
  SerovalUndefinedNode,
24
25
  SerovalWKSymbolNode,
26
+ SerovalReferenceNode,
25
27
  } from './types';
26
28
 
27
29
  export const TRUE_NODE: SerovalBooleanNode = {
@@ -33,7 +35,7 @@ export const TRUE_NODE: SerovalBooleanNode = {
33
35
  m: undefined,
34
36
  d: undefined,
35
37
  a: undefined,
36
- n: undefined,
38
+ f: undefined,
37
39
  };
38
40
  export const FALSE_NODE: SerovalBooleanNode = {
39
41
  t: SerovalNodeType.Boolean,
@@ -44,7 +46,7 @@ export const FALSE_NODE: SerovalBooleanNode = {
44
46
  m: undefined,
45
47
  d: undefined,
46
48
  a: undefined,
47
- n: undefined,
49
+ f: undefined,
48
50
  };
49
51
  export const UNDEFINED_NODE: SerovalUndefinedNode = {
50
52
  t: SerovalNodeType.Undefined,
@@ -55,7 +57,7 @@ export const UNDEFINED_NODE: SerovalUndefinedNode = {
55
57
  m: undefined,
56
58
  d: undefined,
57
59
  a: undefined,
58
- n: undefined,
60
+ f: undefined,
59
61
  };
60
62
  export const NULL_NODE: SerovalNullNode = {
61
63
  t: SerovalNodeType.Null,
@@ -66,7 +68,7 @@ export const NULL_NODE: SerovalNullNode = {
66
68
  m: undefined,
67
69
  d: undefined,
68
70
  a: undefined,
69
- n: undefined,
71
+ f: undefined,
70
72
  };
71
73
  export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
72
74
  t: SerovalNodeType.NegativeZero,
@@ -77,7 +79,7 @@ export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
77
79
  m: undefined,
78
80
  d: undefined,
79
81
  a: undefined,
80
- n: undefined,
82
+ f: undefined,
81
83
  };
82
84
  export const INFINITY_NODE: SerovalInfinityNode = {
83
85
  t: SerovalNodeType.Infinity,
@@ -88,7 +90,7 @@ export const INFINITY_NODE: SerovalInfinityNode = {
88
90
  m: undefined,
89
91
  d: undefined,
90
92
  a: undefined,
91
- n: undefined,
93
+ f: undefined,
92
94
  };
93
95
  export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
94
96
  t: SerovalNodeType.NegativeInfinity,
@@ -99,7 +101,7 @@ export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
99
101
  m: undefined,
100
102
  d: undefined,
101
103
  a: undefined,
102
- n: undefined,
104
+ f: undefined,
103
105
  };
104
106
  export const NAN_NODE: SerovalNaNNode = {
105
107
  t: SerovalNodeType.NaN,
@@ -110,7 +112,7 @@ export const NAN_NODE: SerovalNaNNode = {
110
112
  m: undefined,
111
113
  d: undefined,
112
114
  a: undefined,
113
- n: undefined,
115
+ f: undefined,
114
116
  };
115
117
 
116
118
  export function createNumberNode(value: number): SerovalNumberNode {
@@ -123,7 +125,7 @@ export function createNumberNode(value: number): SerovalNumberNode {
123
125
  m: undefined,
124
126
  d: undefined,
125
127
  a: undefined,
126
- n: undefined,
128
+ f: undefined,
127
129
  };
128
130
  }
129
131
 
@@ -137,7 +139,7 @@ export function createStringNode(value: string): SerovalStringNode {
137
139
  m: undefined,
138
140
  d: undefined,
139
141
  a: undefined,
140
- n: undefined,
142
+ f: undefined,
141
143
  };
142
144
  }
143
145
 
@@ -149,19 +151,19 @@ export function createBigIntNode(
149
151
  return {
150
152
  t: SerovalNodeType.BigInt,
151
153
  i: undefined,
152
- s: current.toString(),
154
+ s: '' + current,
153
155
  l: undefined,
154
156
  c: undefined,
155
157
  m: undefined,
156
158
  d: undefined,
157
159
  a: undefined,
158
- n: undefined,
160
+ f: undefined,
159
161
  };
160
162
  }
161
163
 
162
- export function createReferenceNode(id: number): SerovalReferenceNode {
164
+ export function createIndexedValueNode(id: number): SerovalIndexedValueNode {
163
165
  return {
164
- t: SerovalNodeType.Reference,
166
+ t: SerovalNodeType.IndexedValue,
165
167
  i: id,
166
168
  s: undefined,
167
169
  l: undefined,
@@ -169,7 +171,7 @@ export function createReferenceNode(id: number): SerovalReferenceNode {
169
171
  m: undefined,
170
172
  d: undefined,
171
173
  a: undefined,
172
- n: undefined,
174
+ f: undefined,
173
175
  };
174
176
  }
175
177
 
@@ -182,7 +184,7 @@ export function createDateNode(id: number, current: Date): SerovalDateNode {
182
184
  c: undefined,
183
185
  m: undefined,
184
186
  d: undefined,
185
- n: undefined,
187
+ f: undefined,
186
188
  a: undefined,
187
189
  };
188
190
  }
@@ -197,7 +199,7 @@ export function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode
197
199
  m: current.flags,
198
200
  d: undefined,
199
201
  a: undefined,
200
- n: undefined,
202
+ f: undefined,
201
203
  };
202
204
  }
203
205
 
@@ -211,7 +213,7 @@ export function createTypedArrayNode(
211
213
  const len = current.length;
212
214
  const values = new Array<string>(len);
213
215
  for (let i = 0; i < len; i++) {
214
- values[i] = current[i].toString();
216
+ values[i] = '' + current[i];
215
217
  }
216
218
  return {
217
219
  t: SerovalNodeType.TypedArray,
@@ -222,7 +224,7 @@ export function createTypedArrayNode(
222
224
  m: undefined,
223
225
  d: undefined,
224
226
  a: undefined,
225
- n: undefined,
227
+ f: undefined,
226
228
  };
227
229
  }
228
230
 
@@ -241,24 +243,27 @@ export function createBigIntTypedArrayNode(
241
243
  const len = current.length;
242
244
  const values = new Array<string>(len);
243
245
  for (let i = 0; i < len; i++) {
244
- values[i] = current[i].toString();
246
+ values[i] = '' + current[i];
245
247
  }
246
248
  return {
247
249
  t: SerovalNodeType.BigIntTypedArray,
248
250
  i: id,
249
251
  s: values,
250
- l: (current as BigInt64Array).byteOffset,
252
+ l: current.byteOffset,
251
253
  c: constructor,
252
254
  m: undefined,
253
255
  d: undefined,
254
256
  a: undefined,
255
- n: undefined,
257
+ f: undefined,
256
258
  };
257
259
  }
258
260
 
259
261
  export function createWKSymbolNode(
262
+ ctx: ParserContext,
260
263
  current: WellKnownSymbols,
261
264
  ): SerovalWKSymbolNode {
265
+ assert(ctx.features & Feature.Symbol, 'Unsupported type "symbol"');
266
+ assert(current in INV_SYMBOL_REF, 'seroval only supports well-known symbols');
262
267
  return {
263
268
  t: SerovalNodeType.WKSymbol,
264
269
  i: undefined,
@@ -268,6 +273,23 @@ export function createWKSymbolNode(
268
273
  m: undefined,
269
274
  d: undefined,
270
275
  a: undefined,
271
- n: undefined,
276
+ f: undefined,
277
+ };
278
+ }
279
+
280
+ export function createReferenceNode<T>(
281
+ id: number,
282
+ ref: T,
283
+ ): SerovalReferenceNode {
284
+ return {
285
+ t: SerovalNodeType.Reference,
286
+ i: id,
287
+ s: quote(getReferenceID(ref)),
288
+ l: undefined,
289
+ c: undefined,
290
+ m: undefined,
291
+ d: undefined,
292
+ a: undefined,
293
+ f: undefined,
272
294
  };
273
295
  }
@@ -0,0 +1,61 @@
1
+ /* eslint-disable no-restricted-globals */
2
+ import assert from '../assert';
3
+
4
+ const REFERENCE = new Map<unknown, string>();
5
+ const INV_REFERENCE = new Map<string, unknown>();
6
+
7
+ export function createReference<T>(id: string, value: T): T {
8
+ REFERENCE.set(value, id);
9
+ INV_REFERENCE.set(id, value);
10
+ return value;
11
+ }
12
+
13
+ export function hasReferenceID<T>(value: T): boolean {
14
+ return REFERENCE.has(value);
15
+ }
16
+
17
+ export function hasReference(id: string): boolean {
18
+ return INV_REFERENCE.has(id);
19
+ }
20
+
21
+ export function getReferenceID<T>(value: T): string {
22
+ assert(hasReferenceID(value), 'Missing reference id');
23
+ return REFERENCE.get(value) as string;
24
+ }
25
+
26
+ export function getReference<T>(id: string): T {
27
+ assert(hasReference(id), 'Missing reference for id:' + id);
28
+ return INV_REFERENCE.get(id) as T;
29
+ }
30
+
31
+ export const GLOBAL_KEY = '__SEROVAL__';
32
+
33
+ if (typeof globalThis !== undefined) {
34
+ Object.defineProperty(globalThis, GLOBAL_KEY, {
35
+ value: INV_REFERENCE,
36
+ configurable: true,
37
+ writable: false,
38
+ enumerable: false,
39
+ });
40
+ } else if (typeof window !== undefined) {
41
+ Object.defineProperty(window, GLOBAL_KEY, {
42
+ value: INV_REFERENCE,
43
+ configurable: true,
44
+ writable: false,
45
+ enumerable: false,
46
+ });
47
+ } else if (typeof self !== undefined) {
48
+ Object.defineProperty(self, GLOBAL_KEY, {
49
+ value: INV_REFERENCE,
50
+ configurable: true,
51
+ writable: false,
52
+ enumerable: false,
53
+ });
54
+ } else if (typeof global !== undefined) {
55
+ Object.defineProperty(global, GLOBAL_KEY, {
56
+ value: INV_REFERENCE,
57
+ configurable: true,
58
+ writable: false,
59
+ enumerable: false,
60
+ });
61
+ }
@@ -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';
@@ -48,35 +49,55 @@ function mergeAssignments(assignments: Assignment[]) {
48
49
  for (let i = 1, len = assignments.length; i < len; i++) {
49
50
  item = assignments[i];
50
51
  if (item.t === prev.t) {
51
- if (item.t === 'index' && item.v === prev.v) {
52
- // Merge if the right-hand value is the same
53
- // saves at least 2 chars
54
- current = {
55
- t: 'index',
56
- s: item.s,
57
- k: undefined,
58
- v: getAssignmentExpression(current),
59
- };
60
- } else if (item.t === 'map' && item.s === prev.s) {
61
- // Maps has chaining methods, merge if source is the same
62
- current = {
63
- t: 'map',
64
- s: getAssignmentExpression(current),
65
- k: item.k,
66
- v: item.v,
67
- };
68
- } else if (item.t === 'set' && item.s === prev.s) {
69
- // Sets has chaining methods too
70
- current = {
71
- t: 'set',
72
- s: getAssignmentExpression(current),
73
- k: undefined,
74
- v: item.v,
75
- };
76
- } else {
77
- // Different assignment, push current
78
- newAssignments.push(current);
79
- current = item;
52
+ switch (item.t) {
53
+ case 'index':
54
+ if (item.v === prev.v) {
55
+ // Merge if the right-hand value is the same
56
+ // saves at least 2 chars
57
+ current = {
58
+ t: 'index',
59
+ s: item.s,
60
+ k: undefined,
61
+ v: getAssignmentExpression(current),
62
+ };
63
+ } else {
64
+ // Different assignment, push current
65
+ newAssignments.push(current);
66
+ current = item;
67
+ }
68
+ break;
69
+ case 'map':
70
+ if (item.s === prev.s) {
71
+ // Maps has chaining methods, merge if source is the same
72
+ current = {
73
+ t: 'map',
74
+ s: getAssignmentExpression(current),
75
+ k: item.k,
76
+ v: item.v,
77
+ };
78
+ } else {
79
+ // Different assignment, push current
80
+ newAssignments.push(current);
81
+ current = item;
82
+ }
83
+ break;
84
+ case 'set':
85
+ if (item.s === prev.s) {
86
+ // Sets has chaining methods too
87
+ current = {
88
+ t: 'set',
89
+ s: getAssignmentExpression(current),
90
+ k: undefined,
91
+ v: item.v,
92
+ };
93
+ } else {
94
+ // Different assignment, push current
95
+ newAssignments.push(current);
96
+ current = item;
97
+ }
98
+ break;
99
+ default:
100
+ break;
80
101
  }
81
102
  } else {
82
103
  newAssignments.push(current);
@@ -161,7 +182,7 @@ function createArrayAssign(
161
182
  value: string,
162
183
  ) {
163
184
  markRef(ctx, ref);
164
- createAssignment(ctx, getRefParam(ctx, ref) + '[' + index.toString() + ']', value);
185
+ createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
165
186
  }
166
187
 
167
188
  function createObjectAssign(
@@ -174,7 +195,7 @@ function createObjectAssign(
174
195
  createAssignment(ctx, getRefParam(ctx, ref) + '.' + key, value);
175
196
  }
176
197
 
177
- function assignRef(
198
+ function assignIndexedValue(
178
199
  ctx: SerializationContext,
179
200
  index: number,
180
201
  value: string,
@@ -185,11 +206,11 @@ function assignRef(
185
206
  return value;
186
207
  }
187
208
 
188
- function isReferenceInStack(
209
+ function isIndexedValueInStack(
189
210
  ctx: SerializationContext,
190
211
  node: SerovalNode,
191
- ): node is SerovalReferenceNode {
192
- 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);
193
214
  }
194
215
 
195
216
  function serializeNodeList(
@@ -212,7 +233,7 @@ function serializeNodeList(
212
233
  // Check if index is a hole
213
234
  if (item) {
214
235
  // Check if item is a parent
215
- if (isReferenceInStack(ctx, item)) {
236
+ if (isIndexedValueInStack(ctx, item)) {
216
237
  createArrayAssign(ctx, node.i, i, getRefParam(ctx, item.i));
217
238
  isHoley = true;
218
239
  } else {
@@ -223,10 +244,7 @@ function serializeNodeList(
223
244
  isHoley = true;
224
245
  }
225
246
  }
226
- if (isHoley) {
227
- values += ',';
228
- }
229
- return '[' + values + ']';
247
+ return '[' + values + (isHoley ? ',]' : ']');
230
248
  }
231
249
 
232
250
  function serializeArray(
@@ -236,7 +254,7 @@ function serializeArray(
236
254
  ctx.stack.push(node.i);
237
255
  const result = serializeNodeList(ctx, node);
238
256
  ctx.stack.pop();
239
- return assignRef(ctx, node.i, result);
257
+ return assignIndexedValue(ctx, node.i, result);
240
258
  }
241
259
 
242
260
  function serializeProperties(
@@ -262,7 +280,7 @@ function serializeProperties(
262
280
  // Test if key is a valid number or JS identifier
263
281
  // so that we don't have to serialize the key and wrap with brackets
264
282
  isIdentifier = check >= 0 || isValidIdentifier(key);
265
- if (isReferenceInStack(ctx, val)) {
283
+ if (isIndexedValueInStack(ctx, val)) {
266
284
  refParam = getRefParam(ctx, val.i);
267
285
  if (isIdentifier && Number.isNaN(check)) {
268
286
  createObjectAssign(ctx, sourceID, key, refParam);
@@ -270,11 +288,9 @@ function serializeProperties(
270
288
  createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
271
289
  }
272
290
  } else {
273
- if (hasPrev) {
274
- result += ',';
275
- }
276
- result += isIdentifier ? key : ('"' + quote(key) + '"');
277
- result += ':' + serializeTree(ctx, val);
291
+ result += (hasPrev ? ',' : '')
292
+ + (isIdentifier ? key : ('"' + quote(key) + '"'))
293
+ + ':' + serializeTree(ctx, val);
278
294
  hasPrev = true;
279
295
  }
280
296
  }
@@ -344,12 +360,11 @@ function serializeDictionary(
344
360
  markRef(ctx, i);
345
361
  const assignments = serializeAssignments(ctx, i, d);
346
362
  if (assignments) {
347
- const ref = getRefParam(ctx, i);
348
- return '(' + assignRef(ctx, i, init) + ',' + assignments + ref + ')';
363
+ return '(' + assignIndexedValue(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
349
364
  }
350
365
  }
351
366
  }
352
- return assignRef(ctx, i, init);
367
+ return assignIndexedValue(ctx, i, init);
353
368
  }
354
369
 
355
370
  function serializeNullConstructor(
@@ -363,7 +378,7 @@ function serializeObject(
363
378
  ctx: SerializationContext,
364
379
  node: SerovalObjectNode,
365
380
  ) {
366
- return assignRef(ctx, node.i, serializeProperties(ctx, node.i, node.d));
381
+ return assignIndexedValue(ctx, node.i, serializeProperties(ctx, node.i, node.d));
367
382
  }
368
383
 
369
384
  function serializeSet(
@@ -379,14 +394,11 @@ function serializeSet(
379
394
  let hasPrev = false;
380
395
  for (let i = 0; i < size; i++) {
381
396
  item = node.a[i];
382
- if (isReferenceInStack(ctx, item)) {
397
+ if (isIndexedValueInStack(ctx, item)) {
383
398
  createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
384
399
  } else {
385
400
  // Push directly
386
- if (hasPrev) {
387
- result += ',';
388
- }
389
- result += serializeTree(ctx, item);
401
+ result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
390
402
  hasPrev = true;
391
403
  }
392
404
  }
@@ -395,7 +407,7 @@ function serializeSet(
395
407
  serialized += '([' + result + '])';
396
408
  }
397
409
  }
398
- return assignRef(ctx, node.i, serialized);
410
+ return assignIndexedValue(ctx, node.i, serialized);
399
411
  }
400
412
 
401
413
  function serializeMap(
@@ -416,11 +428,11 @@ function serializeMap(
416
428
  // Check if key is a parent
417
429
  key = node.d.k[i];
418
430
  val = node.d.v[i];
419
- if (isReferenceInStack(ctx, key)) {
431
+ if (isIndexedValueInStack(ctx, key)) {
420
432
  // Create reference for the map instance
421
433
  keyRef = getRefParam(ctx, key.i);
422
434
  // Check if value is a parent
423
- if (isReferenceInStack(ctx, val)) {
435
+ if (isIndexedValueInStack(ctx, val)) {
424
436
  valueRef = getRefParam(ctx, val.i);
425
437
  // Register an assignment since
426
438
  // both key and value are a parent of this
@@ -437,7 +449,7 @@ function serializeMap(
437
449
  createMapSet(ctx, node.i, keyRef, serializeTree(ctx, val));
438
450
  ctx.stack = parent;
439
451
  }
440
- } else if (isReferenceInStack(ctx, val)) {
452
+ } else if (isIndexedValueInStack(ctx, val)) {
441
453
  // Create ref for the Map instance
442
454
  valueRef = getRefParam(ctx, val.i);
443
455
  // Reset stack for the key serialization
@@ -446,10 +458,7 @@ function serializeMap(
446
458
  createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
447
459
  ctx.stack = parent;
448
460
  } else {
449
- if (hasPrev) {
450
- result += ',';
451
- }
452
- result += '[' + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
461
+ result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
453
462
  hasPrev = true;
454
463
  }
455
464
  }
@@ -461,7 +470,7 @@ function serializeMap(
461
470
  serialized += '([' + result + '])';
462
471
  }
463
472
  }
464
- return assignRef(ctx, node.i, serialized);
473
+ return assignIndexedValue(ctx, node.i, serialized);
465
474
  }
466
475
 
467
476
  function serializeAggregateError(
@@ -492,12 +501,12 @@ function serializePromise(
492
501
  ) {
493
502
  let serialized: string;
494
503
  // Check if resolved value is a parent expression
495
- if (isReferenceInStack(ctx, node.n)) {
504
+ if (isIndexedValueInStack(ctx, node.f)) {
496
505
  // A Promise trick, reference the value
497
506
  // inside the `then` expression so that
498
507
  // the Promise evaluates after the parent
499
508
  // has initialized
500
- const ref = getRefParam(ctx, node.n.i);
509
+ const ref = getRefParam(ctx, node.f.i);
501
510
  if (ctx.features & Feature.ArrowFunction) {
502
511
  serialized = 'Promise.resolve().then(()=>' + ref + ')';
503
512
  } else {
@@ -505,12 +514,12 @@ function serializePromise(
505
514
  }
506
515
  } else {
507
516
  ctx.stack.push(node.i);
508
- const result = serializeTree(ctx, node.n);
517
+ const result = serializeTree(ctx, node.f);
509
518
  ctx.stack.pop();
510
519
  // just inline the value/reference here
511
520
  serialized = 'Promise.resolve(' + result + ')';
512
521
  }
513
- return assignRef(ctx, node.i, serialized);
522
+ return assignIndexedValue(ctx, node.i, serialized);
514
523
  }
515
524
 
516
525
  function serializeTypedArray(
@@ -518,20 +527,12 @@ function serializeTypedArray(
518
527
  node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
519
528
  ) {
520
529
  let result = '';
530
+ const isBigInt = node.t === SerovalNodeType.BigIntTypedArray;
521
531
  for (let i = 0, len = node.s.length; i < len; i++) {
522
- if (i !== 0) {
523
- result += ',';
524
- }
525
- result += node.s[i];
526
- if (node.t === SerovalNodeType.BigIntTypedArray) {
527
- result += 'n';
528
- }
529
- }
530
- let args = '[' + result + ']';
531
- if (node.l !== 0) {
532
- args += ',' + node.l.toString();
532
+ result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
533
533
  }
534
- return assignRef(ctx, node.i, 'new ' + node.c + '(' + args + ')');
534
+ const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
535
+ return assignIndexedValue(ctx, node.i, 'new ' + node.c + '(' + args + ')');
535
536
  }
536
537
 
537
538
  function serializeIterable(
@@ -564,13 +565,13 @@ export default function serializeTree(
564
565
  ): string {
565
566
  switch (node.t) {
566
567
  case SerovalNodeType.Number:
567
- return String(node.s);
568
+ return '' + node.s;
568
569
  case SerovalNodeType.String:
569
570
  return '"' + node.s + '"';
570
571
  case SerovalNodeType.Boolean:
571
572
  return node.s ? '!0' : '!1';
572
573
  case SerovalNodeType.Undefined:
573
- return 'undefined';
574
+ return 'void 0';
574
575
  case SerovalNodeType.Null:
575
576
  return 'null';
576
577
  case SerovalNodeType.NegativeZero:
@@ -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
  }