seroval 0.4.1 → 0.5.1

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.
@@ -1,23 +1,121 @@
1
1
  import assert from '../assert';
2
2
  import { Feature } from '../compat';
3
3
  import { ParserContext } from '../context';
4
+ import quote from '../quote';
4
5
  import { BigIntTypedArrayValue, TypedArrayValue } from '../types';
6
+ import { INV_SYMBOL_REF, WellKnownSymbols } from './symbols';
5
7
  import {
6
8
  SerovalBigIntNode,
7
9
  SerovalBigIntTypedArrayNode,
10
+ SerovalBooleanNode,
8
11
  SerovalDateNode,
12
+ SerovalInfinityNode,
13
+ SerovalNaNNode,
14
+ SerovalNegativeInfinityNode,
15
+ SerovalNegativeZeroNode,
9
16
  SerovalNodeType,
10
- SerovalPrimitiveNode,
17
+ SerovalNullNode,
18
+ SerovalNumberNode,
11
19
  SerovalReferenceNode,
12
20
  SerovalRegExpNode,
21
+ SerovalStringNode,
13
22
  SerovalTypedArrayNode,
23
+ SerovalUndefinedNode,
24
+ SerovalWKSymbolNode,
14
25
  } from './types';
15
26
 
16
- export function createPrimitiveNode(
17
- value: string | number | null,
18
- ): SerovalPrimitiveNode {
27
+ export const TRUE_NODE: SerovalBooleanNode = {
28
+ t: SerovalNodeType.Boolean,
29
+ i: undefined,
30
+ s: true,
31
+ l: undefined,
32
+ c: undefined,
33
+ m: undefined,
34
+ d: undefined,
35
+ a: undefined,
36
+ f: undefined,
37
+ };
38
+ export const FALSE_NODE: SerovalBooleanNode = {
39
+ t: SerovalNodeType.Boolean,
40
+ i: undefined,
41
+ s: false,
42
+ l: undefined,
43
+ c: undefined,
44
+ m: undefined,
45
+ d: undefined,
46
+ a: undefined,
47
+ f: undefined,
48
+ };
49
+ export const UNDEFINED_NODE: SerovalUndefinedNode = {
50
+ t: SerovalNodeType.Undefined,
51
+ i: undefined,
52
+ s: undefined,
53
+ l: undefined,
54
+ c: undefined,
55
+ m: undefined,
56
+ d: undefined,
57
+ a: undefined,
58
+ f: undefined,
59
+ };
60
+ export const NULL_NODE: SerovalNullNode = {
61
+ t: SerovalNodeType.Null,
62
+ i: undefined,
63
+ s: undefined,
64
+ l: undefined,
65
+ c: undefined,
66
+ m: undefined,
67
+ d: undefined,
68
+ a: undefined,
69
+ f: undefined,
70
+ };
71
+ export const NEG_ZERO_NODE: SerovalNegativeZeroNode = {
72
+ t: SerovalNodeType.NegativeZero,
73
+ i: undefined,
74
+ s: undefined,
75
+ l: undefined,
76
+ c: undefined,
77
+ m: undefined,
78
+ d: undefined,
79
+ a: undefined,
80
+ f: undefined,
81
+ };
82
+ export const INFINITY_NODE: SerovalInfinityNode = {
83
+ t: SerovalNodeType.Infinity,
84
+ i: undefined,
85
+ s: undefined,
86
+ l: undefined,
87
+ c: undefined,
88
+ m: undefined,
89
+ d: undefined,
90
+ a: undefined,
91
+ f: undefined,
92
+ };
93
+ export const NEG_INFINITY_NODE: SerovalNegativeInfinityNode = {
94
+ t: SerovalNodeType.NegativeInfinity,
95
+ i: undefined,
96
+ s: undefined,
97
+ l: undefined,
98
+ c: undefined,
99
+ m: undefined,
100
+ d: undefined,
101
+ a: undefined,
102
+ f: undefined,
103
+ };
104
+ export const NAN_NODE: SerovalNaNNode = {
105
+ t: SerovalNodeType.NaN,
106
+ i: undefined,
107
+ s: undefined,
108
+ l: undefined,
109
+ c: undefined,
110
+ m: undefined,
111
+ d: undefined,
112
+ a: undefined,
113
+ f: undefined,
114
+ };
115
+
116
+ export function createNumberNode(value: number): SerovalNumberNode {
19
117
  return {
20
- t: SerovalNodeType.Primitive,
118
+ t: SerovalNodeType.Number,
21
119
  i: undefined,
22
120
  s: value,
23
121
  l: undefined,
@@ -25,17 +123,23 @@ export function createPrimitiveNode(
25
123
  m: undefined,
26
124
  d: undefined,
27
125
  a: undefined,
28
- n: undefined,
126
+ f: undefined,
29
127
  };
30
128
  }
31
129
 
32
- export const TRUE_NODE = createPrimitiveNode('!0');
33
- export const FALSE_NODE = createPrimitiveNode('!1');
34
- export const UNDEFINED_NODE = createPrimitiveNode('void 0');
35
- export const NULL_NODE = createPrimitiveNode(null);
36
- export const NEG_ZERO_NODE = createPrimitiveNode('-0');
37
- export const INFINITY_NODE = createPrimitiveNode('1/0');
38
- export const NEG_INFINITY_NODE = createPrimitiveNode('-1/0');
130
+ export function createStringNode(value: string): SerovalStringNode {
131
+ return {
132
+ t: SerovalNodeType.String,
133
+ i: undefined,
134
+ s: quote(value),
135
+ l: undefined,
136
+ c: undefined,
137
+ m: undefined,
138
+ d: undefined,
139
+ a: undefined,
140
+ f: undefined,
141
+ };
142
+ }
39
143
 
40
144
  export function createBigIntNode(
41
145
  ctx: ParserContext,
@@ -45,13 +149,13 @@ export function createBigIntNode(
45
149
  return {
46
150
  t: SerovalNodeType.BigInt,
47
151
  i: undefined,
48
- s: current.toString() + 'n',
152
+ s: '' + current,
49
153
  l: undefined,
50
154
  c: undefined,
51
155
  m: undefined,
52
156
  d: undefined,
53
157
  a: undefined,
54
- n: undefined,
158
+ f: undefined,
55
159
  };
56
160
  }
57
161
 
@@ -65,7 +169,7 @@ export function createReferenceNode(id: number): SerovalReferenceNode {
65
169
  m: undefined,
66
170
  d: undefined,
67
171
  a: undefined,
68
- n: undefined,
172
+ f: undefined,
69
173
  };
70
174
  }
71
175
 
@@ -78,7 +182,7 @@ export function createDateNode(id: number, current: Date): SerovalDateNode {
78
182
  c: undefined,
79
183
  m: undefined,
80
184
  d: undefined,
81
- n: undefined,
185
+ f: undefined,
82
186
  a: undefined,
83
187
  };
84
188
  }
@@ -87,13 +191,13 @@ export function createRegExpNode(id: number, current: RegExp): SerovalRegExpNode
87
191
  return {
88
192
  t: SerovalNodeType.RegExp,
89
193
  i: id,
90
- s: String(current),
194
+ s: undefined,
91
195
  l: undefined,
92
- c: undefined,
93
- m: undefined,
196
+ c: current.source,
197
+ m: current.flags,
94
198
  d: undefined,
95
199
  a: undefined,
96
- n: undefined,
200
+ f: undefined,
97
201
  };
98
202
  }
99
203
 
@@ -104,16 +208,21 @@ export function createTypedArrayNode(
104
208
  ): SerovalTypedArrayNode {
105
209
  const constructor = current.constructor.name;
106
210
  assert(ctx.features & Feature.TypedArray, `Unsupported value type "${constructor}"`);
211
+ const len = current.length;
212
+ const values = new Array<string>(len);
213
+ for (let i = 0; i < len; i++) {
214
+ values[i] = '' + current[i];
215
+ }
107
216
  return {
108
217
  t: SerovalNodeType.TypedArray,
109
218
  i: id,
110
- s: current.toString(),
219
+ s: values,
111
220
  l: current.byteOffset,
112
221
  c: constructor,
113
222
  m: undefined,
114
223
  d: undefined,
115
224
  a: undefined,
116
- n: undefined,
225
+ f: undefined,
117
226
  };
118
227
  }
119
228
 
@@ -129,22 +238,36 @@ export function createBigIntTypedArrayNode(
129
238
  (ctx.features & BIGINT_FLAG) === BIGINT_FLAG,
130
239
  `Unsupported value type "${constructor}"`,
131
240
  );
132
- let result = '';
133
- for (let i = 0, len = current.length; i < len; i++) {
134
- if (i !== 0) {
135
- result += ',';
136
- }
137
- result += current[i].toString() + 'n';
241
+ const len = current.length;
242
+ const values = new Array<string>(len);
243
+ for (let i = 0; i < len; i++) {
244
+ values[i] = '' + current[i];
138
245
  }
139
246
  return {
140
247
  t: SerovalNodeType.BigIntTypedArray,
141
248
  i: id,
142
- s: result,
143
- l: (current as BigInt64Array).byteOffset,
249
+ s: values,
250
+ l: current.byteOffset,
144
251
  c: constructor,
145
252
  m: undefined,
146
253
  d: undefined,
147
254
  a: undefined,
148
- n: undefined,
255
+ f: undefined,
256
+ };
257
+ }
258
+
259
+ export function createWKSymbolNode(
260
+ current: WellKnownSymbols,
261
+ ): SerovalWKSymbolNode {
262
+ return {
263
+ t: SerovalNodeType.WKSymbol,
264
+ i: undefined,
265
+ s: INV_SYMBOL_REF[current],
266
+ l: undefined,
267
+ c: undefined,
268
+ m: undefined,
269
+ d: undefined,
270
+ a: undefined,
271
+ f: undefined,
149
272
  };
150
273
  }
@@ -7,6 +7,8 @@ import {
7
7
  markRef,
8
8
  } from '../context';
9
9
  import quote from '../quote';
10
+ import { isValidIdentifier } from './shared';
11
+ import { SYMBOL_STRING } from './symbols';
10
12
  import {
11
13
  SerovalAggregateErrorNode,
12
14
  SerovalArrayNode,
@@ -17,6 +19,7 @@ import {
17
19
  SerovalNode,
18
20
  SerovalNodeType,
19
21
  SerovalNullConstructorNode,
22
+ SerovalObjectNode,
20
23
  SerovalObjectRecordNode,
21
24
  SerovalPromiseNode,
22
25
  SerovalReferenceNode,
@@ -45,35 +48,55 @@ function mergeAssignments(assignments: Assignment[]) {
45
48
  for (let i = 1, len = assignments.length; i < len; i++) {
46
49
  item = assignments[i];
47
50
  if (item.t === prev.t) {
48
- if (item.t === 'index' && item.v === prev.v) {
49
- // Merge if the right-hand value is the same
50
- // saves at least 2 chars
51
- current = {
52
- t: 'index',
53
- s: item.s,
54
- k: undefined,
55
- v: getAssignmentExpression(current),
56
- };
57
- } else if (item.t === 'map' && item.s === prev.s) {
58
- // Maps has chaining methods, merge if source is the same
59
- current = {
60
- t: 'map',
61
- s: getAssignmentExpression(current),
62
- k: item.k,
63
- v: item.v,
64
- };
65
- } else if (item.t === 'set' && item.s === prev.s) {
66
- // Sets has chaining methods too
67
- current = {
68
- t: 'set',
69
- s: getAssignmentExpression(current),
70
- k: undefined,
71
- v: item.v,
72
- };
73
- } else {
74
- // Different assignment, push current
75
- newAssignments.push(current);
76
- current = item;
51
+ switch (item.t) {
52
+ case 'index':
53
+ if (item.v === prev.v) {
54
+ // Merge if the right-hand value is the same
55
+ // saves at least 2 chars
56
+ current = {
57
+ t: 'index',
58
+ s: item.s,
59
+ k: undefined,
60
+ v: getAssignmentExpression(current),
61
+ };
62
+ } else {
63
+ // Different assignment, push current
64
+ newAssignments.push(current);
65
+ current = item;
66
+ }
67
+ break;
68
+ case 'map':
69
+ if (item.s === prev.s) {
70
+ // Maps has chaining methods, merge if source is the same
71
+ current = {
72
+ t: 'map',
73
+ s: getAssignmentExpression(current),
74
+ k: item.k,
75
+ v: item.v,
76
+ };
77
+ } else {
78
+ // Different assignment, push current
79
+ newAssignments.push(current);
80
+ current = item;
81
+ }
82
+ break;
83
+ case 'set':
84
+ if (item.s === prev.s) {
85
+ // Sets has chaining methods too
86
+ current = {
87
+ t: 'set',
88
+ s: getAssignmentExpression(current),
89
+ k: undefined,
90
+ v: item.v,
91
+ };
92
+ } else {
93
+ // Different assignment, push current
94
+ newAssignments.push(current);
95
+ current = item;
96
+ }
97
+ break;
98
+ default:
99
+ break;
77
100
  }
78
101
  } else {
79
102
  newAssignments.push(current);
@@ -158,7 +181,7 @@ function createArrayAssign(
158
181
  value: string,
159
182
  ) {
160
183
  markRef(ctx, ref);
161
- createAssignment(ctx, getRefParam(ctx, ref) + '[' + index.toString() + ']', value);
184
+ createAssignment(ctx, getRefParam(ctx, ref) + '[' + index + ']', value);
162
185
  }
163
186
 
164
187
  function createObjectAssign(
@@ -189,16 +212,14 @@ function isReferenceInStack(
189
212
  return node.t === SerovalNodeType.Reference && ctx.stack.includes(node.i);
190
213
  }
191
214
 
192
- const IDENTIFIER_CHECK = /^([$A-Z_][0-9A-Z_$]*)$/i;
193
-
194
215
  function serializeNodeList(
195
216
  ctx: SerializationContext,
196
- node: SerovalArrayNode | SerovalIterableNode,
217
+ node: SerovalArrayNode | SerovalIterableNode | SerovalAggregateErrorNode,
197
218
  ) {
198
219
  // This is different than Map and Set
199
220
  // because we also need to serialize
200
221
  // the holes of the Array
201
- const size = node.a.length;
222
+ const size = node.l;
202
223
  let values = '';
203
224
  let item: SerovalNode;
204
225
  let isHoley = false;
@@ -222,10 +243,7 @@ function serializeNodeList(
222
243
  isHoley = true;
223
244
  }
224
245
  }
225
- if (isHoley) {
226
- values += ',';
227
- }
228
- return '[' + values + ']';
246
+ return '[' + values + (isHoley ? ',]' : ']');
229
247
  }
230
248
 
231
249
  function serializeArray(
@@ -238,7 +256,7 @@ function serializeArray(
238
256
  return assignRef(ctx, node.i, result);
239
257
  }
240
258
 
241
- function serializeObject(
259
+ function serializeProperties(
242
260
  ctx: SerializationContext,
243
261
  sourceID: number,
244
262
  node: SerovalObjectRecordNode,
@@ -260,20 +278,18 @@ function serializeObject(
260
278
  check = Number(key);
261
279
  // Test if key is a valid number or JS identifier
262
280
  // so that we don't have to serialize the key and wrap with brackets
263
- isIdentifier = check >= 0 || IDENTIFIER_CHECK.test(key);
281
+ isIdentifier = check >= 0 || isValidIdentifier(key);
264
282
  if (isReferenceInStack(ctx, val)) {
265
283
  refParam = getRefParam(ctx, val.i);
266
284
  if (isIdentifier && Number.isNaN(check)) {
267
285
  createObjectAssign(ctx, sourceID, key, refParam);
268
286
  } else {
269
- createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
287
+ createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
270
288
  }
271
289
  } else {
272
- if (hasPrev) {
273
- result += ',';
274
- }
275
- result += isIdentifier ? key : quote(key);
276
- result += ':' + serializeTree(ctx, val);
290
+ result += (hasPrev ? ',' : '')
291
+ + (isIdentifier ? key : ('"' + quote(key) + '"'))
292
+ + ':' + serializeTree(ctx, val);
277
293
  hasPrev = true;
278
294
  }
279
295
  }
@@ -287,7 +303,7 @@ function serializeWithObjectAssign(
287
303
  id: number,
288
304
  serialized: string,
289
305
  ) {
290
- const fields = serializeObject(ctx, id, value);
306
+ const fields = serializeProperties(ctx, id, value);
291
307
  if (fields !== '{}') {
292
308
  return 'Object.assign(' + serialized + ',' + fields + ')';
293
309
  }
@@ -318,11 +334,11 @@ function serializeAssignments(
318
334
  ctx.assignments = mainAssignments;
319
335
  // Test if key is a valid number or JS identifier
320
336
  // so that we don't have to serialize the key and wrap with brackets
321
- isIdentifier = check >= 0 || IDENTIFIER_CHECK.test(key);
337
+ isIdentifier = check >= 0 || isValidIdentifier(key);
322
338
  if (isIdentifier && Number.isNaN(check)) {
323
339
  createObjectAssign(ctx, sourceID, key, refParam);
324
340
  } else {
325
- createArrayAssign(ctx, sourceID, isIdentifier ? key : quote(key), refParam);
341
+ createArrayAssign(ctx, sourceID, isIdentifier ? key : ('"' + quote(key) + '"'), refParam);
326
342
  }
327
343
  ctx.assignments = parentAssignment;
328
344
  }
@@ -343,8 +359,7 @@ function serializeDictionary(
343
359
  markRef(ctx, i);
344
360
  const assignments = serializeAssignments(ctx, i, d);
345
361
  if (assignments) {
346
- const ref = getRefParam(ctx, i);
347
- return '(' + assignRef(ctx, i, init) + ',' + assignments + ref + ')';
362
+ return '(' + assignRef(ctx, i, init) + ',' + assignments + getRefParam(ctx, i) + ')';
348
363
  }
349
364
  }
350
365
  }
@@ -358,12 +373,19 @@ function serializeNullConstructor(
358
373
  return serializeDictionary(ctx, node.i, node.d, 'Object.create(null)');
359
374
  }
360
375
 
376
+ function serializeObject(
377
+ ctx: SerializationContext,
378
+ node: SerovalObjectNode,
379
+ ) {
380
+ return assignRef(ctx, node.i, serializeProperties(ctx, node.i, node.d));
381
+ }
382
+
361
383
  function serializeSet(
362
384
  ctx: SerializationContext,
363
385
  node: SerovalSetNode,
364
386
  ) {
365
387
  let serialized = 'new Set';
366
- const size = node.a.length;
388
+ const size = node.l;
367
389
  if (size) {
368
390
  let result = '';
369
391
  ctx.stack.push(node.i);
@@ -375,10 +397,7 @@ function serializeSet(
375
397
  createSetAdd(ctx, node.i, getRefParam(ctx, item.i));
376
398
  } else {
377
399
  // Push directly
378
- if (hasPrev) {
379
- result += ',';
380
- }
381
- result += serializeTree(ctx, item);
400
+ result += (hasPrev ? ',' : '') + serializeTree(ctx, item);
382
401
  hasPrev = true;
383
402
  }
384
403
  }
@@ -438,10 +457,7 @@ function serializeMap(
438
457
  createMapSet(ctx, node.i, serializeTree(ctx, key), valueRef);
439
458
  ctx.stack = parent;
440
459
  } else {
441
- if (hasPrev) {
442
- result += ',';
443
- }
444
- result += '[' + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
460
+ result += (hasPrev ? ',[' : '[') + serializeTree(ctx, key) + ',' + serializeTree(ctx, val) + ']';
445
461
  hasPrev = true;
446
462
  }
447
463
  }
@@ -462,7 +478,7 @@ function serializeAggregateError(
462
478
  ) {
463
479
  // Serialize the required arguments
464
480
  ctx.stack.push(node.i);
465
- const serialized = 'new AggregateError(' + serializeTree(ctx, node.n) + ',' + quote(node.m) + ')';
481
+ const serialized = 'new AggregateError(' + serializeNodeList(ctx, node) + ',"' + quote(node.m) + '")';
466
482
  ctx.stack.pop();
467
483
  // `AggregateError` might've been extended
468
484
  // either through class or custom properties
@@ -474,7 +490,7 @@ function serializeError(
474
490
  ctx: SerializationContext,
475
491
  node: SerovalErrorNode,
476
492
  ) {
477
- const serialized = 'new ' + node.c + '(' + quote(node.m) + ')';
493
+ const serialized = 'new ' + node.c + '("' + quote(node.m) + '")';
478
494
  return serializeDictionary(ctx, node.i, node.d, serialized);
479
495
  }
480
496
 
@@ -484,12 +500,12 @@ function serializePromise(
484
500
  ) {
485
501
  let serialized: string;
486
502
  // Check if resolved value is a parent expression
487
- if (isReferenceInStack(ctx, node.n)) {
503
+ if (isReferenceInStack(ctx, node.f)) {
488
504
  // A Promise trick, reference the value
489
505
  // inside the `then` expression so that
490
506
  // the Promise evaluates after the parent
491
507
  // has initialized
492
- const ref = getRefParam(ctx, node.n.i);
508
+ const ref = getRefParam(ctx, node.f.i);
493
509
  if (ctx.features & Feature.ArrowFunction) {
494
510
  serialized = 'Promise.resolve().then(()=>' + ref + ')';
495
511
  } else {
@@ -497,7 +513,7 @@ function serializePromise(
497
513
  }
498
514
  } else {
499
515
  ctx.stack.push(node.i);
500
- const result = serializeTree(ctx, node.n);
516
+ const result = serializeTree(ctx, node.f);
501
517
  ctx.stack.pop();
502
518
  // just inline the value/reference here
503
519
  serialized = 'Promise.resolve(' + result + ')';
@@ -509,10 +525,12 @@ function serializeTypedArray(
509
525
  ctx: SerializationContext,
510
526
  node: SerovalTypedArrayNode | SerovalBigIntTypedArrayNode,
511
527
  ) {
512
- let args = '[' + node.s + ']';
513
- if (node.l !== 0) {
514
- args += ',' + node.l.toString();
528
+ let result = '';
529
+ const isBigInt = node.t === SerovalNodeType.BigIntTypedArray;
530
+ for (let i = 0, len = node.s.length; i < len; i++) {
531
+ result += (i !== 0 ? ',' : '') + node.s[i] + (isBigInt ? 'n' : '');
515
532
  }
533
+ const args = '[' + result + ']' + (node.l !== 0 ? (',' + node.l) : '');
516
534
  return assignRef(ctx, node.i, 'new ' + node.c + '(' + args + ')');
517
535
  }
518
536
 
@@ -545,22 +563,38 @@ export default function serializeTree(
545
563
  node: SerovalNode,
546
564
  ): string {
547
565
  switch (node.t) {
548
- case SerovalNodeType.Primitive:
549
- return String(node.s);
566
+ case SerovalNodeType.Number:
567
+ return '' + node.s;
568
+ case SerovalNodeType.String:
569
+ return '"' + node.s + '"';
570
+ case SerovalNodeType.Boolean:
571
+ return node.s ? '!0' : '!1';
572
+ case SerovalNodeType.Undefined:
573
+ return 'void 0';
574
+ case SerovalNodeType.Null:
575
+ return 'null';
576
+ case SerovalNodeType.NegativeZero:
577
+ return '-0';
578
+ case SerovalNodeType.Infinity:
579
+ return '1/0';
580
+ case SerovalNodeType.NegativeInfinity:
581
+ return '-1/0';
582
+ case SerovalNodeType.NaN:
583
+ return 'NaN';
550
584
  case SerovalNodeType.BigInt:
551
- return node.s;
585
+ return node.s + 'n';
552
586
  case SerovalNodeType.Reference:
553
587
  return getRefParam(ctx, node.i);
554
588
  case SerovalNodeType.Array:
555
589
  return serializeArray(ctx, node);
556
590
  case SerovalNodeType.Object:
557
- return assignRef(ctx, node.i, serializeObject(ctx, node.i, node.d));
591
+ return serializeObject(ctx, node);
558
592
  case SerovalNodeType.NullConstructor:
559
593
  return serializeNullConstructor(ctx, node);
560
594
  case SerovalNodeType.Date:
561
595
  return assignRef(ctx, node.i, 'new Date("' + node.s + '")');
562
596
  case SerovalNodeType.RegExp:
563
- return assignRef(ctx, node.i, node.s);
597
+ return assignRef(ctx, node.i, '/' + node.c + '/' + node.m);
564
598
  case SerovalNodeType.Set:
565
599
  return serializeSet(ctx, node);
566
600
  case SerovalNodeType.Map:
@@ -576,6 +610,8 @@ export default function serializeTree(
576
610
  return serializeIterable(ctx, node);
577
611
  case SerovalNodeType.Promise:
578
612
  return serializePromise(ctx, node);
613
+ case SerovalNodeType.WKSymbol:
614
+ return SYMBOL_STRING[node.s];
579
615
  default:
580
616
  throw new Error('Unsupported type');
581
617
  }