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