seroval 0.2.1 → 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.
@@ -27,23 +27,67 @@ __export(src_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(src_exports);
29
29
 
30
- // src/array.ts
31
- function forEach(arr, callback) {
32
- for (let i = 0, len = arr.length; i < len; i++) {
33
- if (callback(arr[i], i)) {
34
- break;
35
- }
30
+ // src/checks.ts
31
+ function isPrimitive(current) {
32
+ if (!current || current === true) {
33
+ return true;
36
34
  }
35
+ const type = typeof current;
36
+ return type === "number" || type === "string" || type === "bigint";
37
+ }
38
+ function isPromise(obj) {
39
+ return !!obj && (typeof obj === "object" || typeof obj === "function") && "then" in obj && typeof obj.then === "function";
40
+ }
41
+ function constructorCheck(value, constructor) {
42
+ return value.constructor === constructor;
37
43
  }
38
- function join(arr, joiner) {
44
+ function isIterableBuiltin(obj) {
45
+ return Array.isArray(obj) || constructorCheck(obj, Set) || constructorCheck(obj, Map);
46
+ }
47
+ function isIterable(obj) {
48
+ return !!obj && typeof obj === "object" && !isIterableBuiltin(obj) && Symbol.iterator in obj && typeof obj[Symbol.iterator] === "function";
49
+ }
50
+
51
+ // src/quote.ts
52
+ function quote(str) {
39
53
  let result = "";
40
- forEach(arr, (value, index) => {
41
- result += value;
42
- if (index < arr.length - 1) {
43
- result += joiner;
54
+ let lastPos = 0;
55
+ for (let i = 0, len = str.length; i < len; i++) {
56
+ let replacement;
57
+ switch (str[i]) {
58
+ case '"':
59
+ replacement = '\\"';
60
+ break;
61
+ case "\\":
62
+ replacement = "\\\\";
63
+ break;
64
+ case "<":
65
+ replacement = "\\x3C";
66
+ break;
67
+ case "\n":
68
+ replacement = "\\n";
69
+ break;
70
+ case "\r":
71
+ replacement = "\\r";
72
+ break;
73
+ case "\u2028":
74
+ replacement = "\\u2028";
75
+ break;
76
+ case "\u2029":
77
+ replacement = "\\u2029";
78
+ break;
79
+ default:
80
+ continue;
44
81
  }
45
- });
46
- return result;
82
+ result += str.slice(lastPos, i) + replacement;
83
+ lastPos = i + 1;
84
+ }
85
+ if (lastPos === 0) {
86
+ result = str;
87
+ } else {
88
+ result += str.slice(lastPos);
89
+ }
90
+ return `"${result}"`;
47
91
  }
48
92
 
49
93
  // src/get-identifier.ts
@@ -63,583 +107,1079 @@ function getIdentifier(index) {
63
107
  return ref;
64
108
  }
65
109
 
66
- // src/context.ts
67
- var EMPTY_SET = "new Set";
68
- var EMPTY_MAP = "new Map";
69
- var EMPTY_ARRAY = "[]";
70
- function createSerializationContext() {
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
+
311
+ // src/tree.ts
312
+ var DEFAULT_OPTIONS = {
313
+ target: "es2023"
314
+ };
315
+ function createSerializationContext(options = {}) {
316
+ const result = Object.assign({}, DEFAULT_OPTIONS, options || {});
71
317
  return {
72
- refCount: /* @__PURE__ */ new Map(),
73
- stack: /* @__PURE__ */ new Set(),
318
+ markedRefs: [],
319
+ stack: [],
74
320
  refs: /* @__PURE__ */ new Map(),
75
- assignedRefs: /* @__PURE__ */ new Set(),
76
321
  vars: [],
77
322
  assignments: [],
78
- mapSets: [],
79
- setAdds: []
323
+ validRefs: /* @__PURE__ */ new Map(),
324
+ features: parseTargets(result.target)
80
325
  };
81
326
  }
82
- function resolveAssignments(ctx) {
83
- if (ctx.assignments.length) {
84
- const result = {};
85
- forEach(ctx.assignments, ([source, value]) => {
86
- if (value in result) {
87
- result[value] = `${source}=${result[value]}`;
88
- } else {
89
- result[value] = `${source}=${value}`;
90
- }
91
- });
92
- return `${join(Object.values(result), ",")},`;
327
+ function getAssignmentExpression(assignment) {
328
+ switch (assignment.type) {
329
+ case "index":
330
+ return `${assignment.source}=${assignment.value}`;
331
+ case "map":
332
+ return `${assignment.source}.set(${assignment.key},${assignment.value})`;
333
+ case "set":
334
+ return `${assignment.source}.add(${assignment.value})`;
335
+ default:
336
+ return "";
93
337
  }
94
- return "";
95
338
  }
96
- function resolveMapSets(ctx) {
97
- if (ctx.mapSets.length) {
98
- const result = {};
99
- forEach(ctx.mapSets, ([source, key, value]) => {
100
- if (source in result) {
101
- result[source] = `${result[source]}.set(${key},${value})`;
339
+ function mergeAssignments(assignments) {
340
+ const newAssignments = [];
341
+ let current = assignments[0];
342
+ let prev = current;
343
+ for (let i = 1, len = assignments.length; i < len; i++) {
344
+ const item = assignments[i];
345
+ if (item.type === prev.type) {
346
+ if (item.type === "index" && item.value === prev.value) {
347
+ current = {
348
+ type: "index",
349
+ source: item.source,
350
+ value: getAssignmentExpression(current)
351
+ };
352
+ } else if (item.type === "map" && item.source === prev.source) {
353
+ current = {
354
+ type: "map",
355
+ source: getAssignmentExpression(current),
356
+ key: item.key,
357
+ value: item.value
358
+ };
359
+ } else if (item.type === "set" && item.source === prev.source) {
360
+ current = {
361
+ type: "set",
362
+ source: getAssignmentExpression(current),
363
+ value: item.value
364
+ };
102
365
  } else {
103
- result[source] = `${source}.set(${key},${value})`;
366
+ newAssignments.push(current);
367
+ current = item;
104
368
  }
105
- });
106
- return `${join(Object.values(result), ",")},`;
369
+ } else {
370
+ newAssignments.push(current);
371
+ current = item;
372
+ }
373
+ prev = item;
107
374
  }
108
- return "";
375
+ newAssignments.push(current);
376
+ return newAssignments;
109
377
  }
110
- function resolveSetAdds(ctx) {
111
- if (ctx.setAdds.length) {
112
- const result = {};
113
- forEach(ctx.setAdds, ([source, value]) => {
114
- if (source in result) {
115
- result[source] = `${result[source]}.add(${value})`;
116
- } else {
117
- result[source] = `${source}.add(${value})`;
118
- }
119
- });
120
- return `${join(Object.values(result), ",")},`;
378
+ function resolveAssignments(assignments) {
379
+ if (assignments.length) {
380
+ let result = "";
381
+ const merged = mergeAssignments(assignments);
382
+ for (let i = 0, len = merged.length; i < len; i++) {
383
+ result += `${getAssignmentExpression(merged[i])},`;
384
+ }
385
+ return result;
121
386
  }
122
- return "";
387
+ return void 0;
123
388
  }
124
389
  function resolvePatches(ctx) {
125
- return `${resolveAssignments(ctx)}${resolveMapSets(ctx)}${resolveSetAdds(ctx)}`;
390
+ return resolveAssignments(ctx.assignments);
126
391
  }
127
- function insertRef(ctx, current) {
128
- const count = ctx.refCount.get(current) || 0;
129
- ctx.refCount.set(current, count + 1);
130
- return count === 0;
392
+ function markRef(ctx, current) {
393
+ ctx.markedRefs[current] = true;
131
394
  }
132
- function constructorCheck(value, constructor) {
133
- return value.constructor === constructor;
134
- }
135
- function createRef(ctx, value) {
136
- const current = ctx.refs.get(value);
395
+ function createRef(ctx, index) {
396
+ const current = ctx.refs.get(index);
137
397
  if (current != null) {
138
398
  return current;
139
399
  }
140
400
  const id = ctx.refs.size;
141
- ctx.refs.set(value, id);
401
+ ctx.refs.set(index, id);
402
+ return id;
403
+ }
404
+ function createValidRef(ctx, index) {
405
+ const current = ctx.validRefs.get(index);
406
+ if (current != null) {
407
+ return current;
408
+ }
409
+ const id = ctx.validRefs.size;
410
+ ctx.validRefs.set(index, id);
142
411
  return id;
143
412
  }
144
413
  function getRefParam(ctx, index) {
145
- if (ctx.vars[index]) {
146
- return ctx.vars[index];
414
+ const actualIndex = createValidRef(ctx, index);
415
+ if (ctx.vars[actualIndex]) {
416
+ return ctx.vars[actualIndex];
147
417
  }
148
- const result = getIdentifier(index);
149
- ctx.vars[index] = result;
418
+ const result = getIdentifier(actualIndex);
419
+ ctx.vars[actualIndex] = result;
150
420
  return result;
151
421
  }
152
422
  function assignRef(ctx, index, value) {
153
- return `${getRefParam(ctx, index)}=${value}`;
423
+ if (ctx.markedRefs[index]) {
424
+ return `${getRefParam(ctx, index)}=${value}`;
425
+ }
426
+ return value;
154
427
  }
155
428
  function createAssignment(ctx, source, value) {
156
- ctx.assignments.push([source, value]);
429
+ ctx.assignments.push({
430
+ type: "index",
431
+ source,
432
+ value
433
+ });
157
434
  }
158
435
  function createSetAdd(ctx, ref, value) {
159
- ctx.setAdds.push([getRefParam(ctx, ref), value]);
436
+ markRef(ctx, ref);
437
+ ctx.assignments.push({
438
+ type: "set",
439
+ source: getRefParam(ctx, ref),
440
+ value
441
+ });
160
442
  }
161
443
  function createMapSet(ctx, ref, key, value) {
162
- ctx.mapSets.push([getRefParam(ctx, ref), key, value]);
444
+ markRef(ctx, ref);
445
+ ctx.assignments.push({
446
+ type: "map",
447
+ source: getRefParam(ctx, ref),
448
+ key,
449
+ value
450
+ });
163
451
  }
164
452
  function createArrayAssign(ctx, ref, index, value) {
453
+ markRef(ctx, ref);
165
454
  createAssignment(ctx, `${getRefParam(ctx, ref)}[${index}]`, value);
166
455
  }
167
456
  function createObjectIdentifierAssign(ctx, ref, key, value) {
457
+ markRef(ctx, ref);
168
458
  createAssignment(ctx, `${getRefParam(ctx, ref)}.${key}`, value);
169
459
  }
170
460
  function createObjectComputedAssign(ctx, ref, key, value) {
461
+ markRef(ctx, ref);
171
462
  createAssignment(ctx, `${getRefParam(ctx, ref)}[${key}]`, value);
172
463
  }
173
-
174
- // src/is-primitive.ts
175
- function isPrimitive(current) {
176
- if (!current || current === true) {
177
- return true;
464
+ function getErrorConstructor(error) {
465
+ if (error instanceof EvalError) {
466
+ return "EvalError";
178
467
  }
179
- const type = typeof current;
180
- const classConst = current.constructor;
181
- return type === "number" || type === "string" || type === "bigint" || classConst === Date || classConst === RegExp;
468
+ if (error instanceof RangeError) {
469
+ return "RangeError";
470
+ }
471
+ if (error instanceof ReferenceError) {
472
+ return "ReferenceError";
473
+ }
474
+ if (error instanceof SyntaxError) {
475
+ return "SyntaxError";
476
+ }
477
+ if (error instanceof TypeError) {
478
+ return "TypeError";
479
+ }
480
+ if (error instanceof URIError) {
481
+ return "URIError";
482
+ }
483
+ return "Error";
182
484
  }
183
-
184
- // src/is-promise.ts
185
- function isPromise(obj) {
186
- return !!obj && (typeof obj === "object" || typeof obj === "function") && "then" in obj && typeof obj.then === "function";
485
+ function getErrorOptions(error) {
486
+ let options;
487
+ const constructor = getErrorConstructor(error);
488
+ if (error.name !== constructor) {
489
+ options = { name: error.name };
490
+ } else if (error.constructor.name !== constructor) {
491
+ options = { name: error.constructor.name };
492
+ }
493
+ const names = Object.getOwnPropertyNames(error);
494
+ for (const name of names) {
495
+ if (name !== "name" && name !== "message") {
496
+ options = options || {};
497
+ options[name] = error[name];
498
+ }
499
+ }
500
+ return options;
187
501
  }
188
-
189
- // src/quote.ts
190
- function quote(str) {
191
- let result = "";
192
- let lastPos = 0;
193
- for (let i = 0, len = str.length; i < len; i++) {
194
- let replacement;
195
- switch (str[i]) {
196
- case '"':
197
- replacement = '\\"';
198
- break;
199
- case "\\":
200
- replacement = "\\\\";
201
- break;
202
- case "<":
203
- replacement = "\\x3C";
204
- break;
205
- case "\n":
206
- replacement = "\\n";
207
- break;
208
- case "\r":
209
- replacement = "\\r";
210
- break;
211
- case "\u2028":
212
- replacement = "\\u2028";
213
- break;
214
- case "\u2029":
215
- replacement = "\\u2029";
216
- break;
217
- default:
218
- continue;
502
+ function getIterableOptions(obj) {
503
+ const names = Object.getOwnPropertyNames(obj);
504
+ if (names.length) {
505
+ const options = {};
506
+ for (const name of names) {
507
+ options[name] = obj[name];
219
508
  }
220
- result += str.slice(lastPos, i) + replacement;
221
- lastPos = i + 1;
509
+ return options;
222
510
  }
223
- if (lastPos === 0) {
224
- result = str;
225
- } else {
226
- result += str.slice(lastPos);
511
+ return void 0;
512
+ }
513
+ function isReferenceInStack(ctx, node) {
514
+ return node[0] === 1 /* Reference */ && ctx.stack.includes(node[1]);
515
+ }
516
+ function generateRef(ctx, current) {
517
+ const ref = ctx.refs.has(current);
518
+ if (ref) {
519
+ const refID = ctx.refs.get(current) || 0;
520
+ markRef(ctx, refID);
521
+ return [1 /* Reference */, refID];
227
522
  }
228
- return `"${result}"`;
523
+ const id = ctx.refs.size;
524
+ ctx.refs.set(current, id);
525
+ return id;
229
526
  }
230
-
231
- // src/serialize-primitive.ts
232
- function serializePrimitive(value) {
233
- if (value === true) {
234
- return "!0";
527
+ function generateSemiPrimitiveValue(ctx, current, id) {
528
+ if (constructorCheck(current, Date)) {
529
+ return [2 /* Date */, current, id];
235
530
  }
236
- if (value === false) {
237
- return "!1";
531
+ if (constructorCheck(current, RegExp)) {
532
+ return [3 /* RegExp */, current, id];
238
533
  }
239
- if (value === void 0) {
240
- return "void 0";
534
+ if (constructorCheck(current, Int8Array)) {
535
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int8Array"');
536
+ return [13 /* TypedArray */, ["Int8Array", current], id];
241
537
  }
242
- if (value === null) {
243
- return "null";
538
+ if (constructorCheck(current, Int16Array)) {
539
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int16Array"');
540
+ return [13 /* TypedArray */, ["Int16Array", current], id];
244
541
  }
245
- if (Object.is(value, -0)) {
246
- return "-0";
542
+ if (constructorCheck(current, Int32Array)) {
543
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Int32Array"');
544
+ return [13 /* TypedArray */, ["Int32Array", current], id];
247
545
  }
248
- if (typeof value === "bigint") {
249
- return `BigInt("${value}")`;
546
+ if (constructorCheck(current, Uint8Array)) {
547
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint8Array"');
548
+ return [13 /* TypedArray */, ["Uint8Array", current], id];
250
549
  }
251
- if (typeof value === "string") {
252
- return quote(value);
550
+ if (constructorCheck(current, Uint16Array)) {
551
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint16Array"');
552
+ return [13 /* TypedArray */, ["Uint16Array", current], id];
253
553
  }
254
- if (value.constructor === Date) {
255
- return `new Date("${value.toISOString()}")`;
554
+ if (constructorCheck(current, Uint32Array)) {
555
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint32Array"');
556
+ return [13 /* TypedArray */, ["Uint32Array", current], id];
256
557
  }
257
- return String(value);
558
+ if (constructorCheck(current, Uint8ClampedArray)) {
559
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Uint8ClampedArray"');
560
+ return [13 /* TypedArray */, ["Uint8ClampedArray", current], id];
561
+ }
562
+ if (constructorCheck(current, Float32Array)) {
563
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Float32Array"');
564
+ return [13 /* TypedArray */, ["Float32Array", current], id];
565
+ }
566
+ if (constructorCheck(current, Float64Array)) {
567
+ assert(ctx.features.has("typed-arrays"), 'Unsupported value type "Float64Array"');
568
+ return [13 /* TypedArray */, ["Float64Array", current], id];
569
+ }
570
+ if (constructorCheck(current, BigInt64Array)) {
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];
576
+ }
577
+ if (constructorCheck(current, BigUint64Array)) {
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];
583
+ }
584
+ return void 0;
258
585
  }
259
-
260
- // src/async.ts
261
- async function lookupRefsAsync(ctx, current) {
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
+ }
262
610
  if (isPrimitive(current)) {
263
- return;
611
+ return [0 /* Primitive */, current];
264
612
  }
265
- if (isPromise(current)) {
266
- if (insertRef(ctx, current)) {
267
- await current.then((value) => lookupRefsAsync(ctx, value));
268
- }
269
- } else if (Array.isArray(current)) {
270
- if (insertRef(ctx, current)) {
271
- for (const value of current) {
272
- await lookupRefsAsync(ctx, value);
613
+ const id = generateRef(ctx, current);
614
+ if (Array.isArray(id)) {
615
+ return id;
616
+ }
617
+ const semiPrimitive = generateSemiPrimitiveValue(ctx, current, id);
618
+ if (semiPrimitive) {
619
+ return semiPrimitive;
620
+ }
621
+ if (constructorCheck(current, Set)) {
622
+ assert(ctx.features.has("set"), 'Unsupported type "Set"');
623
+ const nodes = [];
624
+ const deferred = [];
625
+ for (const item of current.keys()) {
626
+ if (isIterable(item)) {
627
+ deferred.push(item);
628
+ } else {
629
+ nodes.push(generateTreeSync(ctx, item));
273
630
  }
274
631
  }
275
- } else if (constructorCheck(current, Set)) {
276
- if (insertRef(ctx, current)) {
277
- for (const item of current.keys()) {
278
- await lookupRefsAsync(ctx, item);
632
+ for (let i = 0, len = deferred.length; i < len; i++) {
633
+ nodes.push(generateTreeSync(ctx, deferred[i]));
634
+ }
635
+ return [4 /* Set */, nodes, id];
636
+ }
637
+ if (constructorCheck(current, Map)) {
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;
644
+ for (const [key, value] of current.entries()) {
645
+ if (isIterable(key) || isIterable(value)) {
646
+ deferredKey.push(key);
647
+ deferredValue.push(value);
648
+ deferredSize++;
649
+ } else {
650
+ keyNodes.push(generateTreeSync(ctx, key));
651
+ valueNodes.push(generateTreeSync(ctx, value));
279
652
  }
280
653
  }
281
- } else if (constructorCheck(current, Map)) {
282
- if (insertRef(ctx, current)) {
283
- for (const [key, value] of current.entries()) {
284
- await lookupRefsAsync(ctx, key);
285
- await lookupRefsAsync(ctx, value);
654
+ for (let i = 0; i < deferredSize; i++) {
655
+ keyNodes.push(generateTreeSync(ctx, deferredKey[i]));
656
+ valueNodes.push(generateTreeSync(ctx, deferredValue[i]));
657
+ }
658
+ return [5 /* Map */, [keyNodes, valueNodes, current.size], id];
659
+ }
660
+ if (Array.isArray(current)) {
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
+ }
286
671
  }
287
672
  }
288
- } else if ((current.constructor === Object || current.constructor == null) && insertRef(ctx, current)) {
289
- for (const value of Object.values(current)) {
290
- await lookupRefsAsync(ctx, value);
673
+ for (let i = 0; i < size; i++) {
674
+ if (i in deferred) {
675
+ nodes[i] = generateTreeSync(ctx, deferred[i]);
676
+ }
291
677
  }
678
+ return [6 /* Array */, nodes, id];
292
679
  }
293
- }
294
- async function traverseAsync(ctx, current) {
295
- if (isPrimitive(current)) {
296
- return serializePrimitive(current);
680
+ if (current instanceof AggregateError && ctx.features.has("aggregate-error")) {
681
+ const options = getErrorOptions(current);
682
+ const optionsNode = options ? serializeProperties(options) : void 0;
683
+ const errorsNode = generateTreeSync(ctx, current.errors);
684
+ return [11 /* AggregateError */, [current.message, optionsNode, errorsNode], id];
297
685
  }
298
- let refResult = ctx.refs.get(current);
299
- if (refResult != null) {
300
- if (ctx.assignedRefs.has(refResult)) {
301
- return getRefParam(ctx, refResult);
302
- }
303
- ctx.assignedRefs.add(refResult);
686
+ if (current instanceof Error) {
687
+ const options = getErrorOptions(current);
688
+ const optionsNode = options ? serializeProperties(options) : void 0;
689
+ return [
690
+ 10 /* Error */,
691
+ [getErrorConstructor(current), current.message, optionsNode],
692
+ id
693
+ ];
304
694
  }
305
- function getCurrentRef() {
306
- if (refResult == null) {
307
- refResult = createRef(ctx, current);
308
- }
309
- return refResult;
695
+ if (isIterable(current)) {
696
+ assert(ctx.features.has("symbol-iterator"), 'Unsupported type "Iterable"');
697
+ const options = getIterableOptions(current);
698
+ return [12 /* Iterable */, [
699
+ // Parse options first before the items
700
+ options ? serializeProperties(options) : void 0,
701
+ generateTreeSync(ctx, Array.from(current))
702
+ ], id];
310
703
  }
311
- function processRef(value) {
312
- if (refResult != null) {
313
- return assignRef(ctx, refResult, value);
314
- }
315
- return value;
704
+ const empty = current.constructor == null;
705
+ if (current.constructor === Object || empty) {
706
+ return [
707
+ empty ? 8 /* NullConstructor */ : 7 /* Object */,
708
+ serializeProperties(current),
709
+ id
710
+ ];
316
711
  }
317
- if (isPromise(current)) {
318
- return current.then(async (value) => {
319
- ctx.stack.add(current);
320
- let result;
321
- if (ctx.stack.has(value)) {
322
- const refParam = getRefParam(ctx, createRef(ctx, value));
323
- result = `Promise.resolve().then(()=>${refParam})`;
712
+ throw new Error("Unsupported value");
713
+ }
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++;
324
727
  } else {
325
- result = `Promise.resolve(${await traverseAsync(ctx, value)})`;
728
+ keyNodes.push(key);
729
+ valueNodes.push(await generateTreeAsync(ctx, properties[key]));
326
730
  }
327
- ctx.stack.delete(current);
328
- return processRef(result);
329
- });
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
+ }
738
+ if (isPrimitive(current)) {
739
+ return [0 /* Primitive */, current];
740
+ }
741
+ const id = generateRef(ctx, current);
742
+ if (Array.isArray(id)) {
743
+ return id;
744
+ }
745
+ const semiPrimitive = generateSemiPrimitiveValue(ctx, current, id);
746
+ if (semiPrimitive) {
747
+ return semiPrimitive;
748
+ }
749
+ if (isPromise(current)) {
750
+ assert(ctx.features.has("promise"), 'Unsupported type "Promise"');
751
+ return current.then(async (value) => [
752
+ 9 /* Promise */,
753
+ await generateTreeAsync(ctx, value),
754
+ id
755
+ ]);
330
756
  }
331
757
  if (constructorCheck(current, Set)) {
332
- if (current.size) {
333
- const values = [];
334
- ctx.stack.add(current);
335
- for (const value of current.keys()) {
336
- if (ctx.stack.has(value)) {
337
- createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
338
- } else {
339
- values.push(await traverseAsync(ctx, value));
340
- }
758
+ assert(ctx.features.has("set"), 'Unsupported type "Set"');
759
+ const nodes = [];
760
+ const deferred = [];
761
+ for (const item of current.keys()) {
762
+ if (isIterable(item)) {
763
+ deferred.push(item);
764
+ } else {
765
+ nodes.push(await generateTreeAsync(ctx, item));
341
766
  }
342
- ctx.stack.delete(current);
343
- return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
344
767
  }
345
- return EMPTY_SET;
768
+ for (let i = 0, len = deferred.length; i < len; i++) {
769
+ nodes.push(await generateTreeAsync(ctx, deferred[i]));
770
+ }
771
+ return [4 /* Set */, nodes, id];
346
772
  }
347
773
  if (constructorCheck(current, Map)) {
348
- if (current.size) {
349
- const values = [];
350
- ctx.stack.add(current);
351
- for (const [key, value] of current.entries()) {
352
- if (ctx.stack.has(key)) {
353
- const ref = getCurrentRef();
354
- const keyRef = getRefParam(ctx, createRef(ctx, key));
355
- if (ctx.stack.has(value)) {
356
- const valueRef = getRefParam(ctx, createRef(ctx, value));
357
- createMapSet(ctx, ref, keyRef, valueRef);
358
- } else {
359
- const valueResult = await traverseAsync(ctx, value);
360
- createMapSet(ctx, ref, keyRef, valueResult);
361
- }
362
- } else if (ctx.stack.has(value)) {
363
- const valueRef = getRefParam(ctx, createRef(ctx, value));
364
- const keyResult = await traverseAsync(ctx, key);
365
- createMapSet(ctx, getCurrentRef(), keyResult, valueRef);
366
- } else {
367
- const keyResult = await traverseAsync(ctx, key);
368
- const valueResult = await traverseAsync(ctx, value);
369
- values.push(`[${keyResult},${valueResult}]`);
370
- }
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;
780
+ for (const [key, value] of current.entries()) {
781
+ if (isIterable(key) || isIterable(value)) {
782
+ deferredKey.push(key);
783
+ deferredValue.push(value);
784
+ deferredSize++;
785
+ } else {
786
+ keyNodes.push(await generateTreeAsync(ctx, key));
787
+ valueNodes.push(await generateTreeAsync(ctx, value));
371
788
  }
372
- ctx.stack.delete(current);
373
- return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
374
789
  }
375
- return EMPTY_MAP;
790
+ for (let i = 0; i < deferredSize; i++) {
791
+ keyNodes.push(await generateTreeAsync(ctx, deferredKey[i]));
792
+ valueNodes.push(await generateTreeAsync(ctx, deferredValue[i]));
793
+ }
794
+ return [5 /* Map */, [keyNodes, valueNodes, current.size], id];
376
795
  }
377
796
  if (Array.isArray(current)) {
378
- if (current.length) {
379
- let values = "";
380
- ctx.stack.add(current);
381
- for (let i = 0, len = current.length; i < len; i += 1) {
382
- if (i in current) {
383
- const item = current[i];
384
- if (ctx.stack.has(item)) {
385
- const refParam = getRefParam(ctx, createRef(ctx, item));
386
- createArrayAssign(ctx, getCurrentRef(), i, refParam);
387
- values += ",";
388
- } else {
389
- values += await traverseAsync(ctx, item);
390
- if (i < current.length - 1) {
391
- values += ",";
392
- }
393
- }
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;
394
805
  } else {
395
- values += ",";
806
+ nodes[i] = await generateTreeAsync(ctx, item);
396
807
  }
397
808
  }
398
- ctx.stack.delete(current);
399
- return processRef(`[${values}]`);
400
809
  }
401
- return EMPTY_ARRAY;
810
+ for (let i = 0; i < size; i++) {
811
+ if (i in deferred) {
812
+ nodes[i] = await generateTreeAsync(ctx, deferred[i]);
813
+ }
814
+ }
815
+ return [6 /* Array */, nodes, id];
816
+ }
817
+ if (current instanceof AggregateError) {
818
+ const options = getErrorOptions(current);
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];
822
+ }
823
+ if (current instanceof Error) {
824
+ const options = getErrorOptions(current);
825
+ const optionsNode = options ? await serializeProperties(options) : void 0;
826
+ return [
827
+ 10 /* Error */,
828
+ [getErrorConstructor(current), current.message, optionsNode],
829
+ id
830
+ ];
831
+ }
832
+ if (isIterable(current)) {
833
+ assert(ctx.features.has("symbol-iterator"), 'Unsupported type "Iterable"');
834
+ const options = getIterableOptions(current);
835
+ return [12 /* Iterable */, [
836
+ options ? await serializeProperties(options) : void 0,
837
+ await generateTreeAsync(ctx, Array.from(current))
838
+ ], id];
402
839
  }
403
840
  const empty = current.constructor == null;
404
841
  if (current.constructor === Object || empty) {
405
- const values = [];
406
- ctx.stack.add(current);
407
- for (const [key, value2] of Object.entries(current)) {
842
+ return [
843
+ empty ? 8 /* NullConstructor */ : 7 /* Object */,
844
+ await serializeProperties(current),
845
+ id
846
+ ];
847
+ }
848
+ throw new Error("Unsupported value");
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
+ }
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];
408
891
  const check = Number(key);
892
+ const parentAssignment = ctx.assignments;
893
+ ctx.assignments = mainAssignments;
409
894
  if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
410
- if (ctx.stack.has(value2)) {
411
- const ref = getCurrentRef();
412
- const refParam = getRefParam(ctx, createRef(ctx, value2));
413
- if (Number.isNaN(check)) {
414
- createObjectIdentifierAssign(ctx, ref, key, refParam);
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);
415
920
  } else {
416
- createObjectComputedAssign(ctx, ref, key, refParam);
921
+ createObjectIdentifierAssign(ctx, sourceID, key, refParam);
417
922
  }
418
923
  } else {
419
- const valueResult = await traverseAsync(ctx, value2);
420
- values.push(`${key}:${valueResult}`);
924
+ result += `${key}:${serializeTree(ctx, val)},`;
421
925
  }
422
- } else if (ctx.stack.has(value2)) {
423
- const refParam = getRefParam(ctx, createRef(ctx, value2));
424
- createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
926
+ } else if (isReferenceInStack(ctx, val)) {
927
+ const refParam = getRefParam(ctx, val[1]);
928
+ createObjectComputedAssign(ctx, sourceID, quote(key), refParam);
425
929
  } else {
426
- const valueResult = await traverseAsync(ctx, value2);
427
- values.push(`${quote(key)}:${valueResult}`);
930
+ result += `${quote(key)}:${serializeTree(ctx, val)},`;
428
931
  }
429
932
  }
430
- ctx.stack.delete(current);
431
- const value = `{${join(values, ",")}}`;
432
- if (empty) {
433
- return processRef(`Object.assign(Object.create(null),${value})`);
434
- }
435
- return processRef(value);
436
- }
437
- throw new Error("Unserializable value");
438
- }
439
-
440
- // src/sync.ts
441
- function lookupRefs(ctx, current) {
442
- if (isPrimitive(current)) {
443
- return;
933
+ ctx.stack.pop();
934
+ return `{${result.substring(0, result.length - 1)}}`;
444
935
  }
445
- if (Array.isArray(current)) {
446
- if (insertRef(ctx, current)) {
447
- forEach(current, (value) => {
448
- lookupRefs(ctx, value);
449
- });
450
- }
451
- } else if (constructorCheck(current, Set)) {
452
- if (insertRef(ctx, current)) {
453
- for (const item of current.keys()) {
454
- lookupRefs(ctx, item);
936
+ switch (type) {
937
+ case 0 /* Primitive */:
938
+ return serializePrimitive(ctx, value);
939
+ case 1 /* Reference */:
940
+ return getRefParam(ctx, value);
941
+ case 9 /* Promise */: {
942
+ let serialized;
943
+ if (isReferenceInStack(ctx, value)) {
944
+ serialized = `Promise.resolve().then(()=>${getRefParam(ctx, value[1])})`;
945
+ } else {
946
+ ctx.stack.push(id);
947
+ const result = serializeTree(ctx, value);
948
+ ctx.stack.pop();
949
+ serialized = `Promise.resolve(${result})`;
455
950
  }
951
+ return assignRef(ctx, id, serialized);
456
952
  }
457
- } else if (constructorCheck(current, Map)) {
458
- if (insertRef(ctx, current)) {
459
- for (const [key, value] of current.entries()) {
460
- lookupRefs(ctx, key);
461
- lookupRefs(ctx, value);
953
+ case 2 /* Date */:
954
+ return assignRef(ctx, id, `new Date("${value.toISOString()}")`);
955
+ case 3 /* RegExp */:
956
+ return assignRef(ctx, id, String(value));
957
+ case 13 /* TypedArray */: {
958
+ let values = "";
959
+ for (let i = 0, len = value[1].length; i < len; i++) {
960
+ values += `${serializePrimitive(ctx, value[1][i])},`;
462
961
  }
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})`);
463
967
  }
464
- } else if ((current.constructor === Object || current.constructor == null) && insertRef(ctx, current)) {
465
- forEach(Object.values(current), (value) => {
466
- lookupRefs(ctx, value);
467
- });
468
- }
469
- }
470
- function traverseSync(ctx, current) {
471
- if (isPrimitive(current)) {
472
- return serializePrimitive(current);
473
- }
474
- let refResult = ctx.refs.get(current);
475
- if (refResult != null) {
476
- if (ctx.assignedRefs.has(refResult)) {
477
- return getRefParam(ctx, refResult);
478
- }
479
- ctx.assignedRefs.add(refResult);
480
- }
481
- function getCurrentRef() {
482
- if (refResult == null) {
483
- refResult = createRef(ctx, current);
484
- }
485
- return refResult;
486
- }
487
- function processRef(value) {
488
- if (refResult != null) {
489
- return assignRef(ctx, refResult, value);
490
- }
491
- return value;
492
- }
493
- if (constructorCheck(current, Set)) {
494
- if (current.size) {
495
- const values = [];
496
- ctx.stack.add(current);
497
- for (const value of current.keys()) {
498
- if (ctx.stack.has(value)) {
499
- createSetAdd(ctx, getCurrentRef(), getRefParam(ctx, createRef(ctx, value)));
500
- } else {
501
- values.push(traverseSync(ctx, value));
968
+ case 4 /* Set */: {
969
+ let serialized = "new Set";
970
+ const size = value.length;
971
+ if (size) {
972
+ let result = "";
973
+ ctx.stack.push(id);
974
+ for (let i = 0; i < size; i++) {
975
+ const item = value[i];
976
+ if (isReferenceInStack(ctx, item)) {
977
+ createSetAdd(ctx, id, getRefParam(ctx, item[1]));
978
+ } else {
979
+ result += `${serializeTree(ctx, item)},`;
980
+ }
981
+ }
982
+ ctx.stack.pop();
983
+ if (result) {
984
+ serialized += `([${result.substring(0, result.length - 1)}])`;
502
985
  }
503
986
  }
504
- ctx.stack.delete(current);
505
- return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
987
+ return assignRef(ctx, id, serialized);
506
988
  }
507
- return EMPTY_SET;
508
- }
509
- if (constructorCheck(current, Map)) {
510
- if (current.size) {
511
- const values = [];
512
- ctx.stack.add(current);
513
- for (const [key, value] of current.entries()) {
514
- if (ctx.stack.has(key)) {
515
- const ref = getCurrentRef();
516
- const keyRef = getRefParam(ctx, createRef(ctx, key));
517
- if (ctx.stack.has(value)) {
518
- const valueRef = getRefParam(ctx, createRef(ctx, value));
519
- createMapSet(ctx, ref, keyRef, valueRef);
989
+ case 5 /* Map */: {
990
+ let serialized = "new Map";
991
+ const size = value[2];
992
+ if (size) {
993
+ let result = "";
994
+ ctx.stack.push(id);
995
+ for (let i = 0; i < size; i++) {
996
+ const key = value[0][i];
997
+ const val = value[1][i];
998
+ if (isReferenceInStack(ctx, key)) {
999
+ const keyRef = getRefParam(ctx, key[1]);
1000
+ if (isReferenceInStack(ctx, val)) {
1001
+ const valueRef = getRefParam(ctx, val[1]);
1002
+ createMapSet(ctx, id, keyRef, valueRef);
1003
+ } else {
1004
+ const parent = ctx.stack;
1005
+ ctx.stack = [];
1006
+ createMapSet(ctx, id, keyRef, serializeTree(ctx, val));
1007
+ ctx.stack = parent;
1008
+ }
1009
+ } else if (isReferenceInStack(ctx, val)) {
1010
+ const valueRef = getRefParam(ctx, val[1]);
1011
+ const parent = ctx.stack;
1012
+ ctx.stack = [];
1013
+ createMapSet(ctx, id, serializeTree(ctx, key), valueRef);
1014
+ ctx.stack = parent;
520
1015
  } else {
521
- createMapSet(ctx, ref, keyRef, traverseSync(ctx, value));
1016
+ result += `[${serializeTree(ctx, key)},${serializeTree(ctx, val)}],`;
522
1017
  }
523
- } else if (ctx.stack.has(value)) {
524
- const valueRef = getRefParam(ctx, createRef(ctx, value));
525
- createMapSet(ctx, getCurrentRef(), traverseSync(ctx, key), valueRef);
526
- } else {
527
- values.push(`[${traverseSync(ctx, key)},${traverseSync(ctx, value)}]`);
1018
+ }
1019
+ ctx.stack.pop();
1020
+ if (result) {
1021
+ serialized += `([${result.substring(0, result.length - 1)}])`;
528
1022
  }
529
1023
  }
530
- ctx.stack.delete(current);
531
- return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
1024
+ return assignRef(ctx, id, serialized);
532
1025
  }
533
- return EMPTY_MAP;
534
- }
535
- if (Array.isArray(current)) {
536
- if (current.length) {
1026
+ case 6 /* Array */: {
1027
+ const size = value.length;
537
1028
  let values = "";
538
- ctx.stack.add(current);
539
- forEach(current, (item, i) => {
540
- if (i in current) {
541
- if (ctx.stack.has(item)) {
542
- const refParam = getRefParam(ctx, createRef(ctx, item));
543
- createArrayAssign(ctx, getCurrentRef(), i, refParam);
1029
+ ctx.stack.push(id);
1030
+ for (let i = 0; i < size; i++) {
1031
+ const item = value[i];
1032
+ if (i in value) {
1033
+ if (isReferenceInStack(ctx, item)) {
1034
+ createArrayAssign(ctx, id, i, getRefParam(ctx, item[1]));
544
1035
  values += ",";
545
1036
  } else {
546
- values += traverseSync(ctx, item);
547
- if (i < current.length - 1) {
1037
+ values += serializeTree(ctx, item);
1038
+ if (i < size - 1) {
548
1039
  values += ",";
549
1040
  }
550
1041
  }
551
1042
  } else {
552
1043
  values += ",";
553
1044
  }
554
- });
555
- ctx.stack.delete(current);
556
- return processRef(`[${values}]`);
1045
+ }
1046
+ ctx.stack.pop();
1047
+ return assignRef(ctx, id, `[${values}]`);
557
1048
  }
558
- return EMPTY_ARRAY;
559
- }
560
- const empty = current.constructor == null;
561
- if (current.constructor === Object || empty) {
562
- const values = [];
563
- ctx.stack.add(current);
564
- forEach(Object.entries(current), ([key, value2]) => {
565
- const check = Number(key);
566
- if (check >= 0 || Number.isNaN(check) && /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
567
- if (ctx.stack.has(value2)) {
568
- const ref = getCurrentRef();
569
- const refParam = getRefParam(ctx, createRef(ctx, value2));
570
- if (!Number.isNaN(check)) {
571
- createObjectComputedAssign(ctx, ref, key, refParam);
572
- } else {
573
- createObjectIdentifierAssign(ctx, ref, key, refParam);
1049
+ case 11 /* AggregateError */: {
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})`;
574
1063
  }
1064
+ }
1065
+ }
1066
+ return assignRef(ctx, id, serialized);
1067
+ }
1068
+ case 10 /* Error */: {
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})`;
575
1074
  } else {
576
- values.push(`${key}:${traverseSync(ctx, value2)}`);
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
+ }
577
1081
  }
578
- } else if (ctx.stack.has(value2)) {
579
- const refParam = getRefParam(ctx, createRef(ctx, value2));
580
- createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
1082
+ }
1083
+ return assignRef(ctx, id, serialized);
1084
+ }
1085
+ case 12 /* Iterable */: {
1086
+ const parent = ctx.stack;
1087
+ ctx.stack = [];
1088
+ const values = serializeTree(ctx, value[1]);
1089
+ ctx.stack = parent;
1090
+ let serialized;
1091
+ if (ctx.features.has("array-values")) {
1092
+ serialized = `${values}.values()`;
581
1093
  } else {
582
- values.push(`${quote(key)}:${traverseSync(ctx, value2)}`);
1094
+ serialized = `${values}[Symbol.iterator]()`;
583
1095
  }
584
- });
585
- ctx.stack.delete(current);
586
- const value = `{${join(values, ",")}}`;
587
- if (empty) {
588
- return processRef(`Object.assign(Object.create(null),${value})`);
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})`;
1107
+ } else {
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
+ }
1114
+ }
1115
+ }
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
+ }
1132
+ }
1133
+ return assignRef(ctx, id, serialized);
589
1134
  }
590
- return processRef(value);
1135
+ case 7 /* Object */:
1136
+ return assignRef(ctx, id, serializeObject(id, value));
1137
+ default:
1138
+ throw new Error("Unsupported type");
591
1139
  }
592
- throw new Error("Unserializable value");
593
1140
  }
594
1141
 
595
1142
  // src/index.ts
596
1143
  function finalize(ctx, source, result) {
597
1144
  if (ctx.vars.length) {
598
- const index = getRefParam(ctx, createRef(ctx, source));
599
1145
  const patches = resolvePatches(ctx);
600
- const params = ctx.vars.length > 1 ? `(${join(ctx.vars, ",")})` : ctx.vars[0];
601
- if (result.startsWith(`${index}=`)) {
602
- 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
+ }
603
1154
  }
604
- return `(${params}=>(${index}=${result},${patches}${index}))()`;
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}))()`;
1159
+ }
1160
+ return `(function(${params}){return ${body}})()`;
605
1161
  }
606
1162
  if (source.constructor === Object) {
607
1163
  return `(${result})`;
608
1164
  }
609
1165
  return result;
610
1166
  }
611
- function serialize(source) {
1167
+ function serialize(source, options) {
1168
+ const ctx = createSerializationContext(options);
612
1169
  if (isPrimitive(source)) {
613
- return serializePrimitive(source);
614
- }
615
- const ctx = createSerializationContext();
616
- lookupRefs(ctx, source);
617
- for (const [key, value] of ctx.refCount.entries()) {
618
- if (value > 1) {
619
- createRef(ctx, key);
620
- }
621
- }
622
- const result = traverseSync(ctx, source);
623
- if (typeof result !== "string") {
624
- throw new Error("Unreachable error");
1170
+ return serializePrimitive(ctx, source);
625
1171
  }
1172
+ const tree = generateTreeSync(ctx, source);
1173
+ const result = serializeTree(ctx, tree);
626
1174
  return finalize(ctx, source, result);
627
1175
  }
628
- async function serializeAsync(source) {
1176
+ async function serializeAsync(source, options) {
1177
+ const ctx = createSerializationContext(options);
629
1178
  if (isPrimitive(source)) {
630
- return serializePrimitive(source);
631
- }
632
- const ctx = createSerializationContext();
633
- await lookupRefsAsync(ctx, source);
634
- for (const [key, value] of ctx.refCount.entries()) {
635
- if (value > 1) {
636
- createRef(ctx, key);
637
- }
638
- }
639
- const result = await traverseAsync(ctx, source);
640
- if (typeof result !== "string") {
641
- throw new Error("Unreachable error");
1179
+ return serializePrimitive(ctx, source);
642
1180
  }
1181
+ const tree = await generateTreeAsync(ctx, source);
1182
+ const result = serializeTree(ctx, tree);
643
1183
  return finalize(ctx, source, result);
644
1184
  }
645
1185
  function deserialize(source) {