seroval 0.3.0 → 0.4.0-alpha.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.
@@ -90,38 +90,6 @@ function quote(str) {
90
90
  return `"${result}"`;
91
91
  }
92
92
 
93
- // src/serialize-primitive.ts
94
- function serializePrimitive(value) {
95
- if (value === true) {
96
- return "!0";
97
- }
98
- if (value === false) {
99
- return "!1";
100
- }
101
- if (value === void 0) {
102
- return "void 0";
103
- }
104
- if (value === null) {
105
- return "null";
106
- }
107
- if (typeof value === "bigint") {
108
- return `${value}n`;
109
- }
110
- if (typeof value === "string") {
111
- return quote(value);
112
- }
113
- if (Object.is(value, -0)) {
114
- return "-0";
115
- }
116
- if (Object.is(value, Infinity)) {
117
- return "1/0";
118
- }
119
- if (Object.is(value, -Infinity)) {
120
- return "-1/0";
121
- }
122
- return String(value);
123
- }
124
-
125
93
  // src/get-identifier.ts
126
94
  var REF_START_CHARS = "hjkmoquxzABCDEFGHIJKLNPQRTUVWXYZ$_";
127
95
  var REF_START_CHARS_LEN = REF_START_CHARS.length;
@@ -139,15 +107,221 @@ function getIdentifier(index) {
139
107
  return ref;
140
108
  }
141
109
 
110
+ // src/assert.ts
111
+ function assert(cond, error) {
112
+ if (!cond) {
113
+ throw new Error(error);
114
+ }
115
+ }
116
+
117
+ // src/compat.ts
118
+ function compareVersion(left, right) {
119
+ let diff = left[0] - right[0];
120
+ if (diff === 0) {
121
+ diff = left[1] - right[1];
122
+ }
123
+ if (diff === 0) {
124
+ diff = left[2] - right[2];
125
+ }
126
+ return diff;
127
+ }
128
+ var VERSION_TABLE = {
129
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError#browser_compatibility
130
+ "aggregate-error": {
131
+ es: [2021, 0, 0],
132
+ chrome: [85, 0, 0],
133
+ edge: [85, 0, 0],
134
+ firefox: [79, 0, 0],
135
+ opera: [71, 0, 0],
136
+ safari: [14, 0, 0],
137
+ ios: [14, 0, 0],
138
+ samsung: [14, 0, 0],
139
+ deno: [1, 2, 0],
140
+ node: [15, 0, 0]
141
+ },
142
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/values#browser_compatibility
143
+ "array-values": {
144
+ es: [6, 0, 0],
145
+ chrome: [66, 0, 0],
146
+ edge: [14, 0, 0],
147
+ firefox: [60, 0, 0],
148
+ opera: [53, 0, 0],
149
+ safari: [9, 0, 0],
150
+ ios: [9, 0, 0],
151
+ samsung: [9, 0, 0],
152
+ deno: [1, 0, 0],
153
+ node: [10, 9, 0]
154
+ },
155
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#browser_compatibility
156
+ "arrow-function": {
157
+ es: [6, 0, 0],
158
+ chrome: [45, 0, 0],
159
+ edge: [12, 0, 0],
160
+ firefox: [24, 0, 0],
161
+ opera: [32, 0, 0],
162
+ safari: [10, 0, 0],
163
+ ios: [10, 0, 0],
164
+ samsung: [5, 0, 0],
165
+ deno: [1, 0, 0],
166
+ node: [4, 0, 0]
167
+ },
168
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#browser_compatibility
169
+ bigint: {
170
+ es: [2020, 0, 0],
171
+ chrome: [67, 0, 0],
172
+ edge: [79, 0, 0],
173
+ firefox: [68, 0, 0],
174
+ opera: [54, 0, 0],
175
+ safari: [14, 0, 0],
176
+ ios: [14, 0, 0],
177
+ samsung: [9, 0, 0],
178
+ deno: [1, 0, 0],
179
+ node: [10, 4, 0]
180
+ },
181
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#browser_compatibility
182
+ map: {
183
+ es: [6, 0, 0],
184
+ chrome: [38, 0, 0],
185
+ edge: [12, 0, 0],
186
+ firefox: [13, 0, 0],
187
+ opera: [25, 0, 0],
188
+ safari: [8, 0, 0],
189
+ ios: [8, 0, 0],
190
+ samsung: [3, 0, 0],
191
+ deno: [1, 0, 0],
192
+ node: [0, 12, 0]
193
+ },
194
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#browser_compatibility
195
+ "method-shorthand": {
196
+ es: [6, 0, 0],
197
+ chrome: [39, 0, 0],
198
+ edge: [12, 0, 0],
199
+ firefox: [34, 0, 0],
200
+ opera: [26, 0, 0],
201
+ safari: [9, 0, 0],
202
+ ios: [9, 0, 0],
203
+ samsung: [4, 0, 0],
204
+ deno: [1, 0, 0],
205
+ node: [4, 0, 0]
206
+ },
207
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#browser_compatibility
208
+ "object-assign": {
209
+ es: [6, 0, 0],
210
+ chrome: [45, 0, 0],
211
+ edge: [12, 0, 0],
212
+ firefox: [34, 0, 0],
213
+ opera: [32, 0, 0],
214
+ safari: [9, 0, 0],
215
+ ios: [9, 0, 0],
216
+ samsung: [5, 0, 0],
217
+ deno: [1, 0, 0],
218
+ node: [4, 0, 0]
219
+ },
220
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#browser_compatibility
221
+ promise: {
222
+ es: [6, 0, 0],
223
+ chrome: [32, 0, 0],
224
+ edge: [12, 0, 0],
225
+ firefox: [29, 0, 0],
226
+ opera: [19, 0, 0],
227
+ safari: [8, 0, 0],
228
+ ios: [8, 0, 0],
229
+ samsung: [2, 0, 0],
230
+ deno: [1, 0, 0],
231
+ node: [0, 12, 0]
232
+ },
233
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#browser_compatibility
234
+ set: {
235
+ es: [6, 0, 0],
236
+ chrome: [38, 0, 0],
237
+ edge: [12, 0, 0],
238
+ firefox: [13, 0, 0],
239
+ opera: [25, 0, 0],
240
+ safari: [8, 0, 0],
241
+ ios: [8, 0, 0],
242
+ samsung: [3, 0, 0],
243
+ deno: [1, 0, 0],
244
+ node: [0, 12, 0]
245
+ },
246
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator#browser_compatibility
247
+ "symbol-iterator": {
248
+ es: [6, 0, 0],
249
+ chrome: [43, 0, 0],
250
+ edge: [12, 0, 0],
251
+ firefox: [36, 0, 0],
252
+ opera: [30, 0, 0],
253
+ safari: [10, 0, 0],
254
+ ios: [10, 0, 0],
255
+ samsung: [4, 0, 0],
256
+ deno: [1, 0, 0],
257
+ node: [0, 12, 0]
258
+ },
259
+ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#browser_compatibility
260
+ "typed-arrays": {
261
+ es: [6, 0, 0],
262
+ chrome: [7, 0, 0],
263
+ edge: [12, 0, 0],
264
+ firefox: [4, 0, 0],
265
+ opera: [11, 6, 0],
266
+ safari: [5, 1, 0],
267
+ ios: [4, 2, 0],
268
+ samsung: [1, 0, 0],
269
+ deno: [1, 0, 0],
270
+ node: [0, 10, 0]
271
+ }
272
+ };
273
+ var TARGET_REGEX = /^(es|chrome|edge|safari|firefox|opera|ios|samsung|deno|node)([0-9]+(\.[0-9]+(\.[0-9]+)?)?)$/i;
274
+ function parseTarget(target) {
275
+ const result = TARGET_REGEX.exec(target);
276
+ assert(result, `Invalid target "${target}"`);
277
+ const [, platform, version] = result;
278
+ const [major, minor = "0", patch = "0"] = version.split(".");
279
+ return [platform, [Number(major), Number(minor), Number(patch)]];
280
+ }
281
+ function getTargetVersions(targets) {
282
+ if (Array.isArray(targets)) {
283
+ const versions = [];
284
+ for (const target of targets) {
285
+ versions.push(parseTarget(target));
286
+ }
287
+ return versions;
288
+ }
289
+ return [parseTarget(targets)];
290
+ }
291
+ function isFeatureSupported(key, targets) {
292
+ const base = VERSION_TABLE[key];
293
+ let flag = true;
294
+ for (const [platform, version] of targets) {
295
+ const baseVersion = base[platform];
296
+ flag = flag && !!baseVersion && compareVersion(baseVersion, version) <= 0;
297
+ }
298
+ return flag;
299
+ }
300
+ function parseTargets(targets) {
301
+ const parsed = getTargetVersions(targets);
302
+ const flags = /* @__PURE__ */ new Set();
303
+ for (const key in VERSION_TABLE) {
304
+ if (isFeatureSupported(key, parsed)) {
305
+ flags.add(key);
306
+ }
307
+ }
308
+ return flags;
309
+ }
310
+
142
311
  // src/tree.ts
143
- function createSerializationContext() {
312
+ var DEFAULT_OPTIONS = {
313
+ target: "es2023"
314
+ };
315
+ function createSerializationContext(options = {}) {
316
+ const result = Object.assign({}, DEFAULT_OPTIONS, options || {});
144
317
  return {
145
318
  markedRefs: [],
146
319
  stack: [],
147
320
  refs: /* @__PURE__ */ new Map(),
148
321
  vars: [],
149
322
  assignments: [],
150
- validRefs: /* @__PURE__ */ new Map()
323
+ validRefs: /* @__PURE__ */ new Map(),
324
+ features: parseTargets(result.target)
151
325
  };
152
326
  }
153
327
  function getAssignmentExpression(assignment) {
@@ -162,12 +336,12 @@ function getAssignmentExpression(assignment) {
162
336
  return "";
163
337
  }
164
338
  }
165
- function mergeAssignments(ctx) {
339
+ function mergeAssignments(assignments) {
166
340
  const newAssignments = [];
167
- let current = ctx.assignments[0];
341
+ let current = assignments[0];
168
342
  let prev = current;
169
- for (let i = 1, len = ctx.assignments.length; i < len; i += 1) {
170
- const item = ctx.assignments[i];
343
+ for (let i = 1, len = assignments.length; i < len; i++) {
344
+ const item = assignments[i];
171
345
  if (item.type === prev.type) {
172
346
  if (item.type === "index" && item.value === prev.value) {
173
347
  current = {
@@ -201,15 +375,19 @@ function mergeAssignments(ctx) {
201
375
  newAssignments.push(current);
202
376
  return newAssignments;
203
377
  }
204
- function resolvePatches(ctx) {
205
- if (ctx.assignments.length) {
378
+ function resolveAssignments(assignments) {
379
+ if (assignments.length) {
206
380
  let result = "";
207
- for (const assignment of mergeAssignments(ctx)) {
208
- result += `${getAssignmentExpression(assignment)},`;
381
+ const merged = mergeAssignments(assignments);
382
+ for (let i = 0, len = merged.length; i < len; i++) {
383
+ result += `${getAssignmentExpression(merged[i])},`;
209
384
  }
210
385
  return result;
211
386
  }
212
- return "";
387
+ return void 0;
388
+ }
389
+ function resolvePatches(ctx) {
390
+ return resolveAssignments(ctx.assignments);
213
391
  }
214
392
  function markRef(ctx, current) {
215
393
  ctx.markedRefs[current] = true;
@@ -304,12 +482,6 @@ function getErrorConstructor(error) {
304
482
  }
305
483
  return "Error";
306
484
  }
307
- var EXCLUDED_ERROR_KEYS = {
308
- name: true,
309
- cause: true,
310
- stack: true,
311
- message: true
312
- };
313
485
  function getErrorOptions(error) {
314
486
  let options;
315
487
  const constructor = getErrorConstructor(error);
@@ -320,7 +492,7 @@ function getErrorOptions(error) {
320
492
  }
321
493
  const names = Object.getOwnPropertyNames(error);
322
494
  for (const name of names) {
323
- if (!(name in EXCLUDED_ERROR_KEYS)) {
495
+ if (name !== "name" && name !== "message") {
324
496
  options = options || {};
325
497
  options[name] = error[name];
326
498
  }
@@ -352,7 +524,7 @@ function generateRef(ctx, current) {
352
524
  ctx.refs.set(current, id);
353
525
  return id;
354
526
  }
355
- function generateSemiPrimitiveValue(current, id) {
527
+ function generateSemiPrimitiveValue(ctx, current, id) {
356
528
  if (constructorCheck(current, Date)) {
357
529
  return [2 /* Date */, current, id];
358
530
  }
@@ -360,41 +532,81 @@ function generateSemiPrimitiveValue(current, id) {
360
532
  return [3 /* RegExp */, current, id];
361
533
  }
362
534
  if (constructorCheck(current, Int8Array)) {
363
- return [13 /* TypedArray */, { constructor: "Int8Array", array: current }, id];
535
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int8Array"');
536
+ return [13 /* TypedArray */, ["Int8Array", current], id];
364
537
  }
365
538
  if (constructorCheck(current, Int16Array)) {
366
- return [13 /* TypedArray */, { constructor: "Int16Array", array: current }, id];
539
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int16Array"');
540
+ return [13 /* TypedArray */, ["Int16Array", current], id];
367
541
  }
368
542
  if (constructorCheck(current, Int32Array)) {
369
- return [13 /* TypedArray */, { constructor: "Int32Array", array: current }, id];
543
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int32Array"');
544
+ return [13 /* TypedArray */, ["Int32Array", current], id];
370
545
  }
371
546
  if (constructorCheck(current, Uint8Array)) {
372
- return [13 /* TypedArray */, { constructor: "Uint8Array", array: current }, id];
547
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint8Array"');
548
+ return [13 /* TypedArray */, ["Uint8Array", current], id];
373
549
  }
374
550
  if (constructorCheck(current, Uint16Array)) {
375
- return [13 /* TypedArray */, { constructor: "Uint16Array", array: current }, id];
551
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint16Array"');
552
+ return [13 /* TypedArray */, ["Uint16Array", current], id];
376
553
  }
377
554
  if (constructorCheck(current, Uint32Array)) {
378
- return [13 /* TypedArray */, { constructor: "Uint32Array", array: current }, id];
555
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint32Array"');
556
+ return [13 /* TypedArray */, ["Uint32Array", current], id];
379
557
  }
380
558
  if (constructorCheck(current, Uint8ClampedArray)) {
381
- return [13 /* TypedArray */, { constructor: "Uint8ClampedArray", array: current }, id];
559
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint8ClampedArray"');
560
+ return [13 /* TypedArray */, ["Uint8ClampedArray", current], id];
382
561
  }
383
562
  if (constructorCheck(current, Float32Array)) {
384
- return [13 /* TypedArray */, { constructor: "Float32Array", array: current }, id];
563
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Float32Array"');
564
+ return [13 /* TypedArray */, ["Float32Array", current], id];
385
565
  }
386
566
  if (constructorCheck(current, Float64Array)) {
387
- return [13 /* TypedArray */, { constructor: "Float64Array", array: current }, id];
567
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Float64Array"');
568
+ return [13 /* TypedArray */, ["Float64Array", current], id];
388
569
  }
389
570
  if (constructorCheck(current, BigInt64Array)) {
390
- return [13 /* TypedArray */, { constructor: "BigInt64Array", array: current }, id];
571
+ assert(
572
+ ctx.features.has("typed-arrays") && ctx.features.has("bigint"),
573
+ 'Unsupported value type "BigInt64Array"'
574
+ );
575
+ return [13 /* TypedArray */, ["BigInt64Array", current], id];
391
576
  }
392
577
  if (constructorCheck(current, BigUint64Array)) {
393
- return [13 /* TypedArray */, { constructor: "BigUint64Array", array: current }, id];
578
+ assert(
579
+ ctx.features.has("typed-arrays") && ctx.features.has("bigint"),
580
+ 'Unsupported value type "BigUint64Array"'
581
+ );
582
+ return [13 /* TypedArray */, ["BigUint64Array", current], id];
394
583
  }
395
584
  return void 0;
396
585
  }
397
586
  function generateTreeSync(ctx, current) {
587
+ function serializeProperties(properties) {
588
+ const keyNodes = [];
589
+ const valueNodes = [];
590
+ const deferredKeys = [];
591
+ const deferredValues = [];
592
+ const keys = Object.keys(properties);
593
+ let deferredSize = 0;
594
+ for (const key of keys) {
595
+ if (isIterable(properties[key])) {
596
+ deferredKeys.push(key);
597
+ deferredValues.push(properties[key]);
598
+ deferredSize++;
599
+ } else {
600
+ keyNodes.push(key);
601
+ valueNodes.push(generateTreeSync(ctx, properties[key]));
602
+ }
603
+ }
604
+ for (let i = 0; i < deferredSize; i++) {
605
+ keyNodes.push(deferredKeys[i]);
606
+ valueNodes.push(generateTreeSync(ctx, deferredValues[i]));
607
+ }
608
+ return [keyNodes, valueNodes, keys.length];
609
+ }
398
610
  if (isPrimitive(current)) {
399
611
  return [0 /* Primitive */, current];
400
612
  }
@@ -402,11 +614,12 @@ function generateTreeSync(ctx, current) {
402
614
  if (Array.isArray(id)) {
403
615
  return id;
404
616
  }
405
- const semiPrimitive = generateSemiPrimitiveValue(current, id);
617
+ const semiPrimitive = generateSemiPrimitiveValue(ctx, current, id);
406
618
  if (semiPrimitive) {
407
619
  return semiPrimitive;
408
620
  }
409
621
  if (constructorCheck(current, Set)) {
622
+ assert(ctx.features.has("set"), 'Unsupported type "Set"');
410
623
  const nodes = [];
411
624
  const deferred = [];
412
625
  for (const item of current.keys()) {
@@ -416,95 +629,112 @@ function generateTreeSync(ctx, current) {
416
629
  nodes.push(generateTreeSync(ctx, item));
417
630
  }
418
631
  }
419
- for (const item of deferred) {
420
- nodes.push(generateTreeSync(ctx, item));
632
+ for (let i = 0, len = deferred.length; i < len; i++) {
633
+ nodes.push(generateTreeSync(ctx, deferred[i]));
421
634
  }
422
635
  return [4 /* Set */, nodes, id];
423
636
  }
424
637
  if (constructorCheck(current, Map)) {
425
- const nodes = [];
426
- const deferred = [];
638
+ assert(ctx.features.has("map"), 'Unsupported type "Map"');
639
+ const keyNodes = [];
640
+ const valueNodes = [];
641
+ const deferredKey = [];
642
+ const deferredValue = [];
643
+ let deferredSize = 0;
427
644
  for (const [key, value] of current.entries()) {
428
645
  if (isIterable(key) || isIterable(value)) {
429
- deferred.push([key, value]);
646
+ deferredKey.push(key);
647
+ deferredValue.push(value);
648
+ deferredSize++;
430
649
  } else {
431
- const keyNode = generateTreeSync(ctx, key);
432
- const valueNode = generateTreeSync(ctx, value);
433
- nodes.push([keyNode, valueNode]);
650
+ keyNodes.push(generateTreeSync(ctx, key));
651
+ valueNodes.push(generateTreeSync(ctx, value));
434
652
  }
435
653
  }
436
- for (const [key, value] of deferred) {
437
- const keyNode = generateTreeSync(ctx, key);
438
- const valueNode = generateTreeSync(ctx, value);
439
- nodes.push([keyNode, valueNode]);
654
+ for (let i = 0; i < deferredSize; i++) {
655
+ keyNodes.push(generateTreeSync(ctx, deferredKey[i]));
656
+ valueNodes.push(generateTreeSync(ctx, deferredValue[i]));
440
657
  }
441
- return [5 /* Map */, nodes, id];
658
+ return [5 /* Map */, [keyNodes, valueNodes, current.size], id];
442
659
  }
443
660
  if (Array.isArray(current)) {
444
- const nodes = new Array(current.length);
445
- const deferred = new Array(current.length);
446
- for (const key in current) {
447
- const item = current[key];
448
- if (isIterable(item)) {
449
- deferred[key] = item;
450
- } else {
451
- nodes[key] = generateTreeSync(ctx, item);
661
+ const size = current.length;
662
+ const nodes = new Array(size);
663
+ const deferred = new Array(size);
664
+ for (let i = 0; i < size; i++) {
665
+ if (i in current) {
666
+ if (isIterable(current[i])) {
667
+ deferred[i] = current[i];
668
+ } else {
669
+ nodes[i] = generateTreeSync(ctx, current[i]);
670
+ }
452
671
  }
453
672
  }
454
- for (const key in deferred) {
455
- nodes[key] = generateTreeSync(ctx, deferred[key]);
673
+ for (let i = 0; i < size; i++) {
674
+ if (i in deferred) {
675
+ nodes[i] = generateTreeSync(ctx, deferred[i]);
676
+ }
456
677
  }
457
678
  return [6 /* Array */, nodes, id];
458
679
  }
459
- if (current instanceof AggregateError) {
680
+ if (current instanceof AggregateError && ctx.features.has("aggregate-error")) {
460
681
  const options = getErrorOptions(current);
461
- return [11 /* AggregateError */, {
462
- message: current.message,
463
- options: options ? generateTreeSync(ctx, options) : void 0,
464
- cause: "cause" in current ? generateTreeSync(ctx, { cause: current.cause }) : void 0,
465
- errors: generateTreeSync(ctx, current.errors)
466
- }, id];
682
+ const optionsNode = options ? serializeProperties(options) : void 0;
683
+ const errorsNode = generateTreeSync(ctx, current.errors);
684
+ return [11 /* AggregateError */, [current.message, optionsNode, errorsNode], id];
467
685
  }
468
686
  if (current instanceof Error) {
469
687
  const options = getErrorOptions(current);
470
- return [10 /* Error */, {
471
- constructor: getErrorConstructor(current),
472
- message: current.message,
473
- options: options ? generateTreeSync(ctx, options) : void 0,
474
- cause: "cause" in current ? generateTreeSync(ctx, { cause: current.cause }) : void 0
475
- }, id];
688
+ const optionsNode = options ? serializeProperties(options) : void 0;
689
+ return [
690
+ 10 /* Error */,
691
+ [getErrorConstructor(current), current.message, optionsNode],
692
+ id
693
+ ];
476
694
  }
477
695
  if (isIterable(current)) {
696
+ assert(ctx.features.has("symbol-iterator"), 'Unsupported type "Iterable"');
478
697
  const options = getIterableOptions(current);
479
- return [12 /* Iterable */, {
698
+ return [12 /* Iterable */, [
480
699
  // Parse options first before the items
481
- options: options ? generateTreeSync(ctx, options) : void 0,
482
- items: generateTreeSync(ctx, Array.from(current))
483
- }, id];
700
+ options ? serializeProperties(options) : void 0,
701
+ generateTreeSync(ctx, Array.from(current))
702
+ ], id];
484
703
  }
485
704
  const empty = current.constructor == null;
486
705
  if (current.constructor === Object || empty) {
487
- const nodes = {};
488
- const deferred = {};
489
- for (const [key, item] of Object.entries(current)) {
490
- if (isIterable(item)) {
491
- deferred[key] = item;
492
- } else {
493
- nodes[key] = generateTreeSync(ctx, item);
494
- }
495
- }
496
- for (const [key, item] of Object.entries(deferred)) {
497
- nodes[key] = generateTreeSync(ctx, item);
498
- }
499
706
  return [
500
707
  empty ? 8 /* NullConstructor */ : 7 /* Object */,
501
- nodes,
708
+ serializeProperties(current),
502
709
  id
503
710
  ];
504
711
  }
505
712
  throw new Error("Unsupported value");
506
713
  }
507
714
  async function generateTreeAsync(ctx, current) {
715
+ async function serializeProperties(properties) {
716
+ const keyNodes = [];
717
+ const valueNodes = [];
718
+ const deferredKeys = [];
719
+ const deferredValues = [];
720
+ const keys = Object.keys(properties);
721
+ let deferredSize = 0;
722
+ for (const key of keys) {
723
+ if (isIterable(properties[key])) {
724
+ deferredKeys.push(key);
725
+ deferredValues.push(properties[key]);
726
+ deferredSize++;
727
+ } else {
728
+ keyNodes.push(key);
729
+ valueNodes.push(await generateTreeAsync(ctx, properties[key]));
730
+ }
731
+ }
732
+ for (let i = 0; i < deferredSize; i++) {
733
+ keyNodes.push(deferredKeys[i]);
734
+ valueNodes.push(await generateTreeAsync(ctx, deferredValues[i]));
735
+ }
736
+ return [keyNodes, valueNodes, keys.length];
737
+ }
508
738
  if (isPrimitive(current)) {
509
739
  return [0 /* Primitive */, current];
510
740
  }
@@ -512,11 +742,12 @@ async function generateTreeAsync(ctx, current) {
512
742
  if (Array.isArray(id)) {
513
743
  return id;
514
744
  }
515
- const semiPrimitive = generateSemiPrimitiveValue(current, id);
745
+ const semiPrimitive = generateSemiPrimitiveValue(ctx, current, id);
516
746
  if (semiPrimitive) {
517
747
  return semiPrimitive;
518
748
  }
519
749
  if (isPromise(current)) {
750
+ assert(ctx.features.has("promise"), 'Unsupported type "Promise"');
520
751
  return current.then(async (value) => [
521
752
  9 /* Promise */,
522
753
  await generateTreeAsync(ctx, value),
@@ -524,6 +755,7 @@ async function generateTreeAsync(ctx, current) {
524
755
  ]);
525
756
  }
526
757
  if (constructorCheck(current, Set)) {
758
+ assert(ctx.features.has("set"), 'Unsupported type "Set"');
527
759
  const nodes = [];
528
760
  const deferred = [];
529
761
  for (const item of current.keys()) {
@@ -533,97 +765,177 @@ async function generateTreeAsync(ctx, current) {
533
765
  nodes.push(await generateTreeAsync(ctx, item));
534
766
  }
535
767
  }
536
- for (const item of deferred) {
537
- nodes.push(await generateTreeAsync(ctx, item));
768
+ for (let i = 0, len = deferred.length; i < len; i++) {
769
+ nodes.push(await generateTreeAsync(ctx, deferred[i]));
538
770
  }
539
771
  return [4 /* Set */, nodes, id];
540
772
  }
541
773
  if (constructorCheck(current, Map)) {
542
- const nodes = [];
543
- const deferred = [];
774
+ assert(ctx.features.has("map"), 'Unsupported type "Map"');
775
+ const keyNodes = [];
776
+ const valueNodes = [];
777
+ const deferredKey = [];
778
+ const deferredValue = [];
779
+ let deferredSize = 0;
544
780
  for (const [key, value] of current.entries()) {
545
781
  if (isIterable(key) || isIterable(value)) {
546
- deferred.push([key, value]);
782
+ deferredKey.push(key);
783
+ deferredValue.push(value);
784
+ deferredSize++;
547
785
  } else {
548
- const keyNode = await generateTreeAsync(ctx, key);
549
- const valueNode = await generateTreeAsync(ctx, value);
550
- nodes.push([keyNode, valueNode]);
786
+ keyNodes.push(await generateTreeAsync(ctx, key));
787
+ valueNodes.push(await generateTreeAsync(ctx, value));
551
788
  }
552
789
  }
553
- for (const [key, value] of deferred) {
554
- const keyNode = await generateTreeAsync(ctx, key);
555
- const valueNode = await generateTreeAsync(ctx, value);
556
- nodes.push([keyNode, valueNode]);
790
+ for (let i = 0; i < deferredSize; i++) {
791
+ keyNodes.push(await generateTreeAsync(ctx, deferredKey[i]));
792
+ valueNodes.push(await generateTreeAsync(ctx, deferredValue[i]));
557
793
  }
558
- return [5 /* Map */, nodes, id];
794
+ return [5 /* Map */, [keyNodes, valueNodes, current.size], id];
559
795
  }
560
796
  if (Array.isArray(current)) {
561
- const nodes = new Array(current.length);
562
- const deferred = new Array(current.length);
563
- for (const key in current) {
564
- const item = current[key];
565
- if (isIterable(item)) {
566
- deferred[key] = item;
567
- } else {
568
- nodes[key] = await generateTreeAsync(ctx, item);
797
+ const size = current.length;
798
+ const nodes = new Array(size);
799
+ const deferred = new Array(size);
800
+ for (let i = 0; i < size; i++) {
801
+ const item = current[i];
802
+ if (i in current) {
803
+ if (isIterable(item)) {
804
+ deferred[i] = item;
805
+ } else {
806
+ nodes[i] = await generateTreeAsync(ctx, item);
807
+ }
569
808
  }
570
809
  }
571
- for (const key in deferred) {
572
- nodes[key] = await generateTreeAsync(ctx, deferred[key]);
810
+ for (let i = 0; i < size; i++) {
811
+ if (i in deferred) {
812
+ nodes[i] = await generateTreeAsync(ctx, deferred[i]);
813
+ }
573
814
  }
574
815
  return [6 /* Array */, nodes, id];
575
816
  }
576
817
  if (current instanceof AggregateError) {
577
818
  const options = getErrorOptions(current);
578
- return [11 /* AggregateError */, {
579
- message: current.message,
580
- options: options ? generateTreeSync(ctx, options) : void 0,
581
- cause: "cause" in current ? await generateTreeAsync(ctx, { cause: current.cause }) : void 0,
582
- errors: await generateTreeAsync(ctx, current.errors)
583
- }, id];
819
+ const optionsNode = options ? await serializeProperties(options) : void 0;
820
+ const errorsNode = await generateTreeAsync(ctx, current.errors);
821
+ return [11 /* AggregateError */, [current.message, optionsNode, errorsNode], id];
584
822
  }
585
823
  if (current instanceof Error) {
586
824
  const options = getErrorOptions(current);
587
- return [10 /* Error */, {
588
- constructor: getErrorConstructor(current),
589
- message: current.message,
590
- options: options ? await generateTreeAsync(ctx, options) : void 0,
591
- cause: "cause" in current ? await generateTreeAsync(ctx, { cause: current.cause }) : void 0
592
- }, id];
825
+ const optionsNode = options ? await serializeProperties(options) : void 0;
826
+ return [
827
+ 10 /* Error */,
828
+ [getErrorConstructor(current), current.message, optionsNode],
829
+ id
830
+ ];
593
831
  }
594
832
  if (isIterable(current)) {
833
+ assert(ctx.features.has("symbol-iterator"), 'Unsupported type "Iterable"');
595
834
  const options = getIterableOptions(current);
596
- return [12 /* Iterable */, {
597
- options: options ? await generateTreeAsync(ctx, options) : void 0,
598
- items: await generateTreeAsync(ctx, Array.from(current))
599
- }, id];
835
+ return [12 /* Iterable */, [
836
+ options ? await serializeProperties(options) : void 0,
837
+ await generateTreeAsync(ctx, Array.from(current))
838
+ ], id];
600
839
  }
601
840
  const empty = current.constructor == null;
602
841
  if (current.constructor === Object || empty) {
603
- const nodes = {};
604
- const deferred = {};
605
- for (const [key, item] of Object.entries(current)) {
606
- if (isIterable(item)) {
607
- deferred[key] = item;
608
- } else {
609
- nodes[key] = await generateTreeAsync(ctx, item);
610
- }
611
- }
612
- for (const [key, item] of Object.entries(deferred)) {
613
- nodes[key] = await generateTreeAsync(ctx, item);
614
- }
615
842
  return [
616
843
  empty ? 8 /* NullConstructor */ : 7 /* Object */,
617
- nodes,
844
+ await serializeProperties(current),
618
845
  id
619
846
  ];
620
847
  }
621
848
  throw new Error("Unsupported value");
622
849
  }
850
+ function serializePrimitive(ctx, value) {
851
+ if (value === true) {
852
+ return "!0";
853
+ }
854
+ if (value === false) {
855
+ return "!1";
856
+ }
857
+ if (value === void 0) {
858
+ return "void 0";
859
+ }
860
+ if (value === null) {
861
+ return "null";
862
+ }
863
+ if (typeof value === "bigint") {
864
+ assert(ctx.features.has("bigint"), 'Unsupported type "BigInt"');
865
+ return `${value}n`;
866
+ }
867
+ if (typeof value === "string") {
868
+ return quote(value);
869
+ }
870
+ if (Object.is(value, -0)) {
871
+ return "-0";
872
+ }
873
+ if (Object.is(value, Infinity)) {
874
+ return "1/0";
875
+ }
876
+ if (Object.is(value, -Infinity)) {
877
+ return "-1/0";
878
+ }
879
+ return String(value);
880
+ }
623
881
  function serializeTree(ctx, [type, value, id]) {
882
+ function serializeAssignments(targetRef, [keys, values, size]) {
883
+ ctx.stack.push(targetRef);
884
+ const mainAssignments = [];
885
+ for (let i = 0; i < size; i++) {
886
+ const parentStack = ctx.stack;
887
+ ctx.stack = [];
888
+ const refParam = serializeTree(ctx, values[i]);
889
+ ctx.stack = parentStack;
890
+ const key = keys[i];
891
+ const check = Number(key);
892
+ const parentAssignment = ctx.assignments;
893
+ ctx.assignments = mainAssignments;
894
+ if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
895
+ if (!Number.isNaN(check)) {
896
+ createObjectComputedAssign(ctx, targetRef, key, refParam);
897
+ } else {
898
+ createObjectIdentifierAssign(ctx, targetRef, key, refParam);
899
+ }
900
+ } else {
901
+ createObjectComputedAssign(ctx, targetRef, quote(key), refParam);
902
+ }
903
+ ctx.assignments = parentAssignment;
904
+ }
905
+ ctx.stack.pop();
906
+ return resolveAssignments(mainAssignments);
907
+ }
908
+ function serializeObject(sourceID, [keys, values, size]) {
909
+ let result = "";
910
+ ctx.stack.push(sourceID);
911
+ for (let i = 0; i < size; i++) {
912
+ const key = keys[i];
913
+ const val = values[i];
914
+ const check = Number(key);
915
+ if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
916
+ if (isReferenceInStack(ctx, val)) {
917
+ const refParam = getRefParam(ctx, val[1]);
918
+ if (!Number.isNaN(check)) {
919
+ createObjectComputedAssign(ctx, sourceID, key, refParam);
920
+ } else {
921
+ createObjectIdentifierAssign(ctx, sourceID, key, refParam);
922
+ }
923
+ } else {
924
+ result += `${key}:${serializeTree(ctx, val)},`;
925
+ }
926
+ } else if (isReferenceInStack(ctx, val)) {
927
+ const refParam = getRefParam(ctx, val[1]);
928
+ createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
929
+ } else {
930
+ result += `${quote(key)}:${serializeTree(ctx, val)},`;
931
+ }
932
+ }
933
+ ctx.stack.pop();
934
+ return `{${result.substring(0, result.length - 1)}}`;
935
+ }
624
936
  switch (type) {
625
937
  case 0 /* Primitive */:
626
- return serializePrimitive(value);
938
+ return serializePrimitive(ctx, value);
627
939
  case 1 /* Reference */:
628
940
  return getRefParam(ctx, value);
629
941
  case 9 /* Promise */: {
@@ -643,38 +955,46 @@ function serializeTree(ctx, [type, value, id]) {
643
955
  case 3 /* RegExp */:
644
956
  return assignRef(ctx, id, String(value));
645
957
  case 13 /* TypedArray */: {
646
- const values = [...value.array].map(serializePrimitive).join(",");
647
- let args = `[${values}]`;
648
- if (value.array.byteOffset !== 0) {
649
- args += `,${value.array.byteOffset}`;
958
+ let values = "";
959
+ for (let i = 0, len = value[1].length; i < len; i++) {
960
+ values += `${serializePrimitive(ctx, value[1][i])},`;
650
961
  }
651
- return assignRef(ctx, id, `new ${value.constructor}(${args})`);
962
+ let args = values ? `[${values.substring(0, values.length - 1)}]` : "[]";
963
+ if (value[1].byteOffset !== 0) {
964
+ args += `,${value[1].byteOffset}`;
965
+ }
966
+ return assignRef(ctx, id, `new ${value[0]}(${args})`);
652
967
  }
653
968
  case 4 /* Set */: {
654
969
  let serialized = "new Set";
655
- if (value.length) {
656
- const values = [];
970
+ const size = value.length;
971
+ if (size) {
972
+ let result = "";
657
973
  ctx.stack.push(id);
658
- for (const item of value) {
974
+ for (let i = 0; i < size; i++) {
975
+ const item = value[i];
659
976
  if (isReferenceInStack(ctx, item)) {
660
977
  createSetAdd(ctx, id, getRefParam(ctx, item[1]));
661
978
  } else {
662
- values.push(serializeTree(ctx, item));
979
+ result += `${serializeTree(ctx, item)},`;
663
980
  }
664
981
  }
665
982
  ctx.stack.pop();
666
- if (values.length) {
667
- serialized += `([${values.join(",")}])`;
983
+ if (result) {
984
+ serialized += `([${result.substring(0, result.length - 1)}])`;
668
985
  }
669
986
  }
670
987
  return assignRef(ctx, id, serialized);
671
988
  }
672
989
  case 5 /* Map */: {
673
990
  let serialized = "new Map";
674
- if (value.length) {
675
- const values = [];
991
+ const size = value[2];
992
+ if (size) {
993
+ let result = "";
676
994
  ctx.stack.push(id);
677
- for (const [key, val] of value) {
995
+ for (let i = 0; i < size; i++) {
996
+ const key = value[0][i];
997
+ const val = value[1][i];
678
998
  if (isReferenceInStack(ctx, key)) {
679
999
  const keyRef = getRefParam(ctx, key[1]);
680
1000
  if (isReferenceInStack(ctx, val)) {
@@ -693,20 +1013,21 @@ function serializeTree(ctx, [type, value, id]) {
693
1013
  createMapSet(ctx, id, serializeTree(ctx, key), valueRef);
694
1014
  ctx.stack = parent;
695
1015
  } else {
696
- values.push(`[${serializeTree(ctx, key)},${serializeTree(ctx, val)}]`);
1016
+ result += `[${serializeTree(ctx, key)},${serializeTree(ctx, val)}],`;
697
1017
  }
698
1018
  }
699
1019
  ctx.stack.pop();
700
- if (values.length) {
701
- serialized += `([${values.join(",")}])`;
1020
+ if (result) {
1021
+ serialized += `([${result.substring(0, result.length - 1)}])`;
702
1022
  }
703
1023
  }
704
1024
  return assignRef(ctx, id, serialized);
705
1025
  }
706
1026
  case 6 /* Array */: {
1027
+ const size = value.length;
707
1028
  let values = "";
708
1029
  ctx.stack.push(id);
709
- for (let i = 0, len = value.length; i < len; i++) {
1030
+ for (let i = 0; i < size; i++) {
710
1031
  const item = value[i];
711
1032
  if (i in value) {
712
1033
  if (isReferenceInStack(ctx, item)) {
@@ -714,7 +1035,7 @@ function serializeTree(ctx, [type, value, id]) {
714
1035
  values += ",";
715
1036
  } else {
716
1037
  values += serializeTree(ctx, item);
717
- if (i < value.length - 1) {
1038
+ if (i < size - 1) {
718
1039
  values += ",";
719
1040
  }
720
1041
  }
@@ -726,74 +1047,93 @@ function serializeTree(ctx, [type, value, id]) {
726
1047
  return assignRef(ctx, id, `[${values}]`);
727
1048
  }
728
1049
  case 11 /* AggregateError */: {
729
- const args = [serializeTree(ctx, value.errors), quote(value.message)];
730
- if (value.cause) {
731
- args.push(serializeTree(ctx, value.cause));
732
- }
733
- let serialized = `new AggregateError(${args.join(",")})`;
734
- if (value.options) {
735
- const options = serializeTree(ctx, value.options);
736
- serialized = `Object.assign(${serialized},${options})`;
1050
+ ctx.stack.push(id);
1051
+ let serialized = `new AggregateError(${serializeTree(ctx, value[2])},${quote(value[0])})`;
1052
+ ctx.stack.pop();
1053
+ if (value[1]) {
1054
+ if (ctx.features.has("object-assign")) {
1055
+ const options = serializeObject(id, value[1]);
1056
+ serialized = `Object.assign(${serialized},${options})`;
1057
+ } else {
1058
+ markRef(ctx, id);
1059
+ const assignments = serializeAssignments(id, value[1]);
1060
+ if (assignments) {
1061
+ const ref = getRefParam(ctx, id);
1062
+ return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
1063
+ }
1064
+ }
737
1065
  }
738
1066
  return assignRef(ctx, id, serialized);
739
1067
  }
740
1068
  case 10 /* Error */: {
741
- const args = [quote(value.message)];
742
- if (value.cause) {
743
- args.push(serializeTree(ctx, value.cause));
744
- }
745
- let serialized = `new ${value.constructor}(${args.join(",")})`;
746
- if (value.options) {
747
- const options = serializeTree(ctx, value.options);
748
- serialized = `Object.assign(${serialized},${options})`;
1069
+ let serialized = `new ${value[0]}(${quote(value[1])})`;
1070
+ if (value[2]) {
1071
+ if (ctx.features.has("object-assign")) {
1072
+ const options = serializeObject(id, value[2]);
1073
+ serialized = `Object.assign(${serialized},${options})`;
1074
+ } else {
1075
+ markRef(ctx, id);
1076
+ const assignments = serializeAssignments(id, value[2]);
1077
+ if (assignments) {
1078
+ const ref = getRefParam(ctx, id);
1079
+ return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
1080
+ }
1081
+ }
749
1082
  }
750
1083
  return assignRef(ctx, id, serialized);
751
1084
  }
752
1085
  case 12 /* Iterable */: {
753
1086
  const parent = ctx.stack;
754
1087
  ctx.stack = [];
755
- const values = serializeTree(ctx, value.items);
1088
+ const values = serializeTree(ctx, value[1]);
756
1089
  ctx.stack = parent;
757
- let serialized = `{[Symbol.iterator]:()=>${values}.values()}`;
758
- if (value.options) {
759
- ctx.stack.push(id);
760
- const options = serializeTree(ctx, value.options);
761
- ctx.stack.pop();
762
- serialized = `Object.assign(${serialized},${options})`;
1090
+ let serialized;
1091
+ if (ctx.features.has("array-values")) {
1092
+ serialized = `${values}.values()`;
1093
+ } else {
1094
+ serialized = `${values}[Symbol.iterator]()`;
763
1095
  }
764
- return assignRef(ctx, id, serialized);
765
- }
766
- case 8 /* NullConstructor */:
767
- case 7 /* Object */: {
768
- const values = [];
769
- ctx.stack.push(id);
770
- for (const [key, val] of Object.entries(value)) {
771
- const check = Number(key);
772
- if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
773
- if (isReferenceInStack(ctx, val)) {
774
- const refParam = getRefParam(ctx, val[1]);
775
- if (!Number.isNaN(check)) {
776
- createObjectComputedAssign(ctx, id, key, refParam);
777
- } else {
778
- createObjectIdentifierAssign(ctx, id, key, refParam);
779
- }
780
- } else {
781
- values.push(`${key}:${serializeTree(ctx, val)}`);
782
- }
783
- } else if (isReferenceInStack(ctx, val)) {
784
- const refParam = getRefParam(ctx, val[1]);
785
- createObjectComputedAssign(ctx, id, quote(key), refParam);
1096
+ if (ctx.features.has("arrow-function")) {
1097
+ serialized = `{[Symbol.iterator]:()=>${serialized}}`;
1098
+ } else if (ctx.features.has("method-shorthand")) {
1099
+ serialized = `{[Symbol.iterator](){return ${serialized}}}`;
1100
+ } else {
1101
+ serialized = `{[Symbol.iterator]:function(){return ${serialized}}}`;
1102
+ }
1103
+ if (value[0]) {
1104
+ if (ctx.features.has("object-assign")) {
1105
+ const options = serializeObject(id, value[0]);
1106
+ serialized = `Object.assign(${serialized},${options})`;
786
1107
  } else {
787
- values.push(`${quote(key)}:${serializeTree(ctx, val)}`);
1108
+ markRef(ctx, id);
1109
+ const assignments = serializeAssignments(id, value[0]);
1110
+ if (assignments) {
1111
+ const ref = getRefParam(ctx, id);
1112
+ return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
1113
+ }
788
1114
  }
789
1115
  }
790
- ctx.stack.pop();
791
- let serialized = `{${values.join(",")}}`;
792
- if (type === 8 /* NullConstructor */) {
793
- serialized = `Object.assign(Object.create(null),${serialized})`;
1116
+ return assignRef(ctx, id, serialized);
1117
+ }
1118
+ case 8 /* NullConstructor */: {
1119
+ let serialized = "Object.create(null)";
1120
+ if (ctx.features.has("object-assign")) {
1121
+ const fields = serializeObject(id, value);
1122
+ if (fields !== "{}") {
1123
+ serialized = `Object.assign(${serialized},${fields})`;
1124
+ }
1125
+ } else {
1126
+ markRef(ctx, id);
1127
+ const assignments = serializeAssignments(id, value);
1128
+ if (assignments) {
1129
+ const ref = getRefParam(ctx, id);
1130
+ return `(${assignRef(ctx, id, serialized)},${assignments}${ref})`;
1131
+ }
794
1132
  }
795
1133
  return assignRef(ctx, id, serialized);
796
1134
  }
1135
+ case 7 /* Object */:
1136
+ return assignRef(ctx, id, serializeObject(id, value));
797
1137
  default:
798
1138
  throw new Error("Unsupported type");
799
1139
  }
@@ -802,33 +1142,42 @@ function serializeTree(ctx, [type, value, id]) {
802
1142
  // src/index.ts
803
1143
  function finalize(ctx, source, result) {
804
1144
  if (ctx.vars.length) {
805
- const index = getRefParam(ctx, createRef(ctx, source));
806
1145
  const patches = resolvePatches(ctx);
807
- const params = ctx.vars.length > 1 ? `(${ctx.vars.join(",")})` : ctx.vars[0];
808
- if (result.startsWith(`${index}=`)) {
809
- return `(${params}=>(${result},${patches}${index}))()`;
1146
+ let body = result;
1147
+ if (patches) {
1148
+ const index = getRefParam(ctx, createRef(ctx, source));
1149
+ if (result.startsWith(`${index}=`)) {
1150
+ body = `${result},${patches}${index}`;
1151
+ } else {
1152
+ body = `${index}=${result},${patches}${index}`;
1153
+ }
1154
+ }
1155
+ let params = ctx.vars.length > 1 ? ctx.vars.join(",") : ctx.vars[0];
1156
+ if (ctx.features.has("arrow-function")) {
1157
+ params = ctx.vars.length > 1 || ctx.vars.length === 0 ? `(${params})` : params;
1158
+ return `(${params}=>(${body}))()`;
810
1159
  }
811
- return `(${params}=>(${index}=${result},${patches}${index}))()`;
1160
+ return `(function(${params}){return ${body}})()`;
812
1161
  }
813
1162
  if (source.constructor === Object) {
814
1163
  return `(${result})`;
815
1164
  }
816
1165
  return result;
817
1166
  }
818
- function serialize(source) {
1167
+ function serialize(source, options) {
1168
+ const ctx = createSerializationContext(options);
819
1169
  if (isPrimitive(source)) {
820
- return serializePrimitive(source);
1170
+ return serializePrimitive(ctx, source);
821
1171
  }
822
- const ctx = createSerializationContext();
823
1172
  const tree = generateTreeSync(ctx, source);
824
1173
  const result = serializeTree(ctx, tree);
825
1174
  return finalize(ctx, source, result);
826
1175
  }
827
- async function serializeAsync(source) {
1176
+ async function serializeAsync(source, options) {
1177
+ const ctx = createSerializationContext(options);
828
1178
  if (isPrimitive(source)) {
829
- return serializePrimitive(source);
1179
+ return serializePrimitive(ctx, source);
830
1180
  }
831
- const ctx = createSerializationContext();
832
1181
  const tree = await generateTreeAsync(ctx, source);
833
1182
  const result = serializeTree(ctx, tree);
834
1183
  return finalize(ctx, source, result);