seroval 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- default: () => serialize
23
+ default: () => src_default,
24
+ deserialize: () => deserialize,
25
+ serialize: () => serialize,
26
+ serializeAsync: () => serializeAsync
24
27
  });
25
28
  module.exports = __toCommonJS(src_exports);
26
29
 
@@ -60,73 +63,26 @@ function getIdentifier(index) {
60
63
  return ref;
61
64
  }
62
65
 
63
- // src/quote.ts
64
- function quote(str) {
65
- let result = "";
66
- let lastPos = 0;
67
- for (let i = 0, len = str.length; i < len; i++) {
68
- let replacement;
69
- switch (str[i]) {
70
- case '"':
71
- replacement = '\\"';
72
- break;
73
- case "\\":
74
- replacement = "\\\\";
75
- break;
76
- case "<":
77
- replacement = "\\x3C";
78
- break;
79
- case "\n":
80
- replacement = "\\n";
81
- break;
82
- case "\r":
83
- replacement = "\\r";
84
- break;
85
- case "\u2028":
86
- replacement = "\\u2028";
87
- break;
88
- case "\u2029":
89
- replacement = "\\u2029";
90
- break;
91
- default:
92
- continue;
93
- }
94
- result += str.slice(lastPos, i) + replacement;
95
- lastPos = i + 1;
96
- }
97
- if (lastPos === 0) {
98
- result = str;
99
- } else {
100
- result += str.slice(lastPos);
101
- }
102
- return `"${result}"`;
103
- }
104
-
105
- // src/index.ts
66
+ // src/context.ts
106
67
  var EMPTY_SET = "new Set";
107
68
  var EMPTY_MAP = "new Map";
108
69
  var EMPTY_ARRAY = "[]";
109
- var REF_COUNT = /* @__PURE__ */ new Map();
110
- var STACK = /* @__PURE__ */ new Set();
111
- var REFS = /* @__PURE__ */ new Map();
112
- var ASSIGNED_REFS = /* @__PURE__ */ new Set();
113
- var VARS = [];
114
- var ASSIGNMENTS = [];
115
- var MAP_SETS = [];
116
- var SET_ADDS = [];
117
- function reset() {
118
- ASSIGNMENTS = [];
119
- MAP_SETS = [];
120
- SET_ADDS = [];
121
- VARS = [];
122
- REF_COUNT.clear();
123
- REFS.clear();
124
- ASSIGNED_REFS.clear();
70
+ function createSerializationContext() {
71
+ return {
72
+ refCount: /* @__PURE__ */ new Map(),
73
+ stack: /* @__PURE__ */ new Set(),
74
+ refs: /* @__PURE__ */ new Map(),
75
+ assignedRefs: /* @__PURE__ */ new Set(),
76
+ vars: [],
77
+ assignments: [],
78
+ mapSets: [],
79
+ setAdds: []
80
+ };
125
81
  }
126
- function resolveAssignments() {
127
- if (ASSIGNMENTS.length) {
82
+ function resolveAssignments(ctx) {
83
+ if (ctx.assignments.length) {
128
84
  const result = {};
129
- forEach(ASSIGNMENTS, ([source, value]) => {
85
+ forEach(ctx.assignments, ([source, value]) => {
130
86
  if (value in result) {
131
87
  result[value] = `${source}=${result[value]}`;
132
88
  } else {
@@ -137,10 +93,10 @@ function resolveAssignments() {
137
93
  }
138
94
  return "";
139
95
  }
140
- function resolveMapSets() {
141
- if (MAP_SETS.length) {
96
+ function resolveMapSets(ctx) {
97
+ if (ctx.mapSets.length) {
142
98
  const result = {};
143
- forEach(MAP_SETS, ([source, key, value]) => {
99
+ forEach(ctx.mapSets, ([source, key, value]) => {
144
100
  if (source in result) {
145
101
  result[source] = `${result[source]}.set(${key},${value})`;
146
102
  } else {
@@ -151,10 +107,10 @@ function resolveMapSets() {
151
107
  }
152
108
  return "";
153
109
  }
154
- function resolveSetAdds() {
155
- if (SET_ADDS.length) {
110
+ function resolveSetAdds(ctx) {
111
+ if (ctx.setAdds.length) {
156
112
  const result = {};
157
- forEach(SET_ADDS, ([source, value]) => {
113
+ forEach(ctx.setAdds, ([source, value]) => {
158
114
  if (source in result) {
159
115
  result[source] = `${result[source]}.add(${value})`;
160
116
  } else {
@@ -165,88 +121,114 @@ function resolveSetAdds() {
165
121
  }
166
122
  return "";
167
123
  }
168
- function resolvePatches() {
169
- return `${resolveAssignments()}${resolveMapSets()}${resolveSetAdds()}`;
124
+ function resolvePatches(ctx) {
125
+ return `${resolveAssignments(ctx)}${resolveMapSets(ctx)}${resolveSetAdds(ctx)}`;
170
126
  }
171
- function insertRef(current) {
172
- const count = REF_COUNT.get(current) || 0;
173
- REF_COUNT.set(current, count + 1);
127
+ function insertRef(ctx, current) {
128
+ const count = ctx.refCount.get(current) || 0;
129
+ ctx.refCount.set(current, count + 1);
174
130
  return count === 0;
175
131
  }
176
132
  function constructorCheck(value, constructor) {
177
133
  return value.constructor === constructor;
178
134
  }
179
- function isPrimitive(current) {
180
- if (!current || current === true) {
181
- return true;
182
- }
183
- const type = typeof current;
184
- const classConst = current.constructor;
185
- return type === "number" || type === "string" || type === "bigint" || classConst === Date || classConst === RegExp;
186
- }
187
- function lookupRefs(current) {
188
- if (isPrimitive(current)) {
189
- return;
190
- }
191
- if (Array.isArray(current)) {
192
- if (insertRef(current)) {
193
- forEach(current, lookupRefs);
194
- }
195
- } else if (constructorCheck(current, Set)) {
196
- if (insertRef(current)) {
197
- for (const item of current.keys()) {
198
- lookupRefs(item);
199
- }
200
- }
201
- } else if (constructorCheck(current, Map)) {
202
- if (insertRef(current)) {
203
- for (const [key, value] of current.entries()) {
204
- lookupRefs(key);
205
- lookupRefs(value);
206
- }
207
- }
208
- } else if (current.constructor === Object && insertRef(current)) {
209
- forEach(Object.values(current), lookupRefs);
210
- }
211
- }
212
- function createRef(value) {
213
- const current = REFS.get(value);
135
+ function createRef(ctx, value) {
136
+ const current = ctx.refs.get(value);
214
137
  if (current != null) {
215
138
  return current;
216
139
  }
217
- const id = REFS.size;
218
- REFS.set(value, id);
140
+ const id = ctx.refs.size;
141
+ ctx.refs.set(value, id);
219
142
  return id;
220
143
  }
221
- function getRefParam(index) {
222
- if (VARS[index]) {
223
- return VARS[index];
144
+ function getRefParam(ctx, index) {
145
+ if (ctx.vars[index]) {
146
+ return ctx.vars[index];
224
147
  }
225
148
  const result = getIdentifier(index);
226
- VARS[index] = result;
149
+ ctx.vars[index] = result;
227
150
  return result;
228
151
  }
229
- function assignRef(index, value) {
230
- return `${getRefParam(index)}=${value}`;
152
+ function assignRef(ctx, index, value) {
153
+ return `${getRefParam(ctx, index)}=${value}`;
154
+ }
155
+ function createAssignment(ctx, source, value) {
156
+ ctx.assignments.push([source, value]);
231
157
  }
232
- function createAssignment(source, value) {
233
- ASSIGNMENTS.push([source, value]);
158
+ function createSetAdd(ctx, ref, value) {
159
+ ctx.setAdds.push([getRefParam(ctx, ref), value]);
234
160
  }
235
- function createSetAdd(ref, value) {
236
- SET_ADDS.push([getRefParam(ref), value]);
161
+ function createMapSet(ctx, ref, key, value) {
162
+ ctx.mapSets.push([getRefParam(ctx, ref), key, value]);
237
163
  }
238
- function createMapSet(ref, key, value) {
239
- MAP_SETS.push([getRefParam(ref), key, value]);
164
+ function createArrayAssign(ctx, ref, index, value) {
165
+ createAssignment(ctx, `${getRefParam(ctx, ref)}[${index}]`, value);
240
166
  }
241
- function createArrayAssign(ref, index, value) {
242
- createAssignment(`${getRefParam(ref)}[${index}]`, value);
167
+ function createObjectIdentifierAssign(ctx, ref, key, value) {
168
+ createAssignment(ctx, `${getRefParam(ctx, ref)}.${key}`, value);
243
169
  }
244
- function createObjectIdentifierAssign(ref, key, value) {
245
- createAssignment(`${getRefParam(ref)}.${key}`, value);
170
+ function createObjectComputedAssign(ctx, ref, key, value) {
171
+ createAssignment(ctx, `${getRefParam(ctx, ref)}[${key}]`, value);
246
172
  }
247
- function createObjectStringAssign(ref, key, value) {
248
- createAssignment(`${getRefParam(ref)}[${quote(key)}]`, value);
173
+
174
+ // src/is-primitive.ts
175
+ function isPrimitive(current) {
176
+ if (!current || current === true) {
177
+ return true;
178
+ }
179
+ const type = typeof current;
180
+ const classConst = current.constructor;
181
+ return type === "number" || type === "string" || type === "bigint" || classConst === Date || classConst === RegExp;
249
182
  }
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";
187
+ }
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;
219
+ }
220
+ result += str.slice(lastPos, i) + replacement;
221
+ lastPos = i + 1;
222
+ }
223
+ if (lastPos === 0) {
224
+ result = str;
225
+ } else {
226
+ result += str.slice(lastPos);
227
+ }
228
+ return `"${result}"`;
229
+ }
230
+
231
+ // src/serialize-primitive.ts
250
232
  function serializePrimitive(value) {
251
233
  if (value === true) {
252
234
  return "!0";
@@ -274,122 +256,294 @@ function serializePrimitive(value) {
274
256
  }
275
257
  return String(value);
276
258
  }
277
- function traverse(current) {
259
+
260
+ // src/async.ts
261
+ async function lookupRefsAsync(ctx, current) {
262
+ if (isPrimitive(current)) {
263
+ return;
264
+ }
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);
273
+ }
274
+ }
275
+ } else if (constructorCheck(current, Set)) {
276
+ if (insertRef(ctx, current)) {
277
+ for (const item of current.keys()) {
278
+ await lookupRefsAsync(ctx, item);
279
+ }
280
+ }
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);
286
+ }
287
+ }
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);
291
+ }
292
+ }
293
+ }
294
+ async function traverseAsync(ctx, current) {
278
295
  if (isPrimitive(current)) {
279
296
  return serializePrimitive(current);
280
297
  }
281
- let refResult = REFS.get(current);
298
+ let refResult = ctx.refs.get(current);
282
299
  if (refResult != null) {
283
- if (ASSIGNED_REFS.has(refResult)) {
284
- return { referred: getRefParam(refResult) };
300
+ if (ctx.assignedRefs.has(refResult)) {
301
+ return getRefParam(ctx, refResult);
285
302
  }
286
- ASSIGNED_REFS.add(refResult);
303
+ ctx.assignedRefs.add(refResult);
304
+ }
305
+ function getCurrentRef() {
306
+ if (refResult == null) {
307
+ refResult = createRef(ctx, current);
308
+ }
309
+ return refResult;
310
+ }
311
+ function processRef(value) {
312
+ if (refResult != null) {
313
+ return assignRef(ctx, refResult, value);
314
+ }
315
+ return value;
316
+ }
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})`;
324
+ } else {
325
+ result = `Promise.resolve(${await traverseAsync(ctx, value)})`;
326
+ }
327
+ ctx.stack.delete(current);
328
+ return processRef(result);
329
+ });
287
330
  }
288
331
  if (constructorCheck(current, Set)) {
289
332
  if (current.size) {
290
333
  const values = [];
291
- STACK.add(current);
292
- for (const value2 of current.keys()) {
293
- if (STACK.has(value2)) {
294
- if (refResult == null) {
295
- refResult = createRef(current);
296
- }
297
- createSetAdd(refResult, getRefParam(createRef(value2)));
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)));
298
338
  } else {
299
- const result = traverse(value2);
300
- if (typeof result === "string") {
301
- values.push(result);
302
- } else {
303
- values.push(result.referred);
304
- }
339
+ values.push(await traverseAsync(ctx, value));
305
340
  }
306
341
  }
307
- STACK.delete(current);
308
- const value = values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET;
309
- if (refResult != null) {
310
- return assignRef(refResult, value);
311
- }
312
- return value;
342
+ ctx.stack.delete(current);
343
+ return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
313
344
  }
314
345
  return EMPTY_SET;
315
346
  }
316
347
  if (constructorCheck(current, Map)) {
317
348
  if (current.size) {
318
349
  const values = [];
319
- STACK.add(current);
320
- for (const [key, value2] of current.entries()) {
321
- if (STACK.has(key)) {
322
- if (refResult == null) {
323
- refResult = createRef(current);
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);
324
361
  }
325
- const keyRef = getRefParam(createRef(key));
326
- if (STACK.has(value2)) {
327
- createMapSet(refResult, keyRef, getRefParam(createRef(value2)));
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
+ }
371
+ }
372
+ ctx.stack.delete(current);
373
+ return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
374
+ }
375
+ return EMPTY_MAP;
376
+ }
377
+ 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 += ",";
328
388
  } else {
329
- const valueResult = traverse(value2);
330
- if (typeof valueResult === "string") {
331
- createMapSet(refResult, keyRef, valueResult);
332
- } else {
333
- createMapSet(refResult, keyRef, valueResult.referred);
389
+ values += await traverseAsync(ctx, item);
390
+ if (i < current.length - 1) {
391
+ values += ",";
334
392
  }
335
393
  }
336
- } else if (STACK.has(value2)) {
337
- if (refResult == null) {
338
- refResult = createRef(current);
339
- }
340
- const valueRef = getRefParam(createRef(value2));
341
- const keyResult = traverse(key);
342
- if (typeof keyResult === "string") {
343
- createMapSet(refResult, keyResult, valueRef);
394
+ } else {
395
+ values += ",";
396
+ }
397
+ }
398
+ ctx.stack.delete(current);
399
+ return processRef(`[${values}]`);
400
+ }
401
+ return EMPTY_ARRAY;
402
+ }
403
+ const empty = current.constructor == null;
404
+ if (current.constructor === Object || empty) {
405
+ const values = [];
406
+ ctx.stack.add(current);
407
+ for (const [key, value2] of Object.entries(current)) {
408
+ const check = Number(key);
409
+ 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);
344
415
  } else {
345
- createMapSet(refResult, keyResult.referred, valueRef);
416
+ createObjectComputedAssign(ctx, ref, key, refParam);
346
417
  }
347
418
  } else {
348
- const keyResult = traverse(key);
349
- const valueResult = traverse(value2);
350
- if (typeof keyResult === "string") {
351
- if (typeof valueResult === "string") {
352
- values.push(`[${keyResult},${valueResult}]`);
353
- } else {
354
- values.push(`[${keyResult},${valueResult.referred}]`);
355
- }
419
+ const valueResult = await traverseAsync(ctx, value2);
420
+ values.push(`${key}:${valueResult}`);
421
+ }
422
+ } else if (ctx.stack.has(value2)) {
423
+ const refParam = getRefParam(ctx, createRef(ctx, value2));
424
+ createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
425
+ } else {
426
+ const valueResult = await traverseAsync(ctx, value2);
427
+ values.push(`${quote(key)}:${valueResult}`);
428
+ }
429
+ }
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;
444
+ }
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);
455
+ }
456
+ }
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);
462
+ }
463
+ }
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));
502
+ }
503
+ }
504
+ ctx.stack.delete(current);
505
+ return processRef(values.length ? `new Set([${join(values, ",")}])` : EMPTY_SET);
506
+ }
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);
356
520
  } else {
357
- if (typeof valueResult === "string") {
358
- values.push(`[${keyResult.referred},${valueResult}]`);
359
- } else {
360
- values.push(`[${keyResult.referred},${valueResult.referred}]`);
361
- }
521
+ createMapSet(ctx, ref, keyRef, traverseSync(ctx, value));
362
522
  }
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)}]`);
363
528
  }
364
529
  }
365
- STACK.delete(current);
366
- const value = values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP;
367
- if (refResult != null) {
368
- return assignRef(refResult, value);
369
- }
370
- return value;
530
+ ctx.stack.delete(current);
531
+ return processRef(values.length ? `new Map([${join(values, ",")}])` : EMPTY_MAP);
371
532
  }
372
533
  return EMPTY_MAP;
373
534
  }
374
535
  if (Array.isArray(current)) {
375
536
  if (current.length) {
376
537
  let values = "";
377
- STACK.add(current);
538
+ ctx.stack.add(current);
378
539
  forEach(current, (item, i) => {
379
540
  if (i in current) {
380
- if (STACK.has(item)) {
381
- if (refResult == null) {
382
- refResult = createRef(current);
383
- }
384
- createArrayAssign(refResult, i, getRefParam(createRef(item)));
541
+ if (ctx.stack.has(item)) {
542
+ const refParam = getRefParam(ctx, createRef(ctx, item));
543
+ createArrayAssign(ctx, getCurrentRef(), i, refParam);
385
544
  values += ",";
386
545
  } else {
387
- const result = traverse(item);
388
- if (typeof result === "string") {
389
- values += result;
390
- } else {
391
- values += result.referred;
392
- }
546
+ values += traverseSync(ctx, item);
393
547
  if (i < current.length - 1) {
394
548
  values += ",";
395
549
  }
@@ -398,84 +552,98 @@ function traverse(current) {
398
552
  values += ",";
399
553
  }
400
554
  });
401
- STACK.delete(current);
402
- const value = `[${values}]`;
403
- if (refResult != null) {
404
- return assignRef(refResult, value);
405
- }
406
- return value;
555
+ ctx.stack.delete(current);
556
+ return processRef(`[${values}]`);
407
557
  }
408
558
  return EMPTY_ARRAY;
409
559
  }
410
- if (current.constructor === Object) {
560
+ const empty = current.constructor == null;
561
+ if (current.constructor === Object || empty) {
411
562
  const values = [];
412
- STACK.add(current);
563
+ ctx.stack.add(current);
413
564
  forEach(Object.entries(current), ([key, value2]) => {
414
565
  const check = Number(key);
415
- if (Number.isNaN(check) || /^([$A-Z_][0-9A-Z_$]*)$/i.test(key)) {
416
- if (STACK.has(value2)) {
417
- if (refResult == null) {
418
- refResult = createRef(current);
419
- }
420
- createObjectIdentifierAssign(refResult, key, getRefParam(createRef(value2)));
421
- } else {
422
- const result = traverse(value2);
423
- if (typeof result === "string") {
424
- values.push(`${key}:${result}`);
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);
425
572
  } else {
426
- values.push(`${key}:${result.referred}`);
573
+ createObjectIdentifierAssign(ctx, ref, key, refParam);
427
574
  }
428
- }
429
- } else if (STACK.has(value2)) {
430
- if (refResult == null) {
431
- refResult = createRef(current);
432
- }
433
- createObjectStringAssign(refResult, key, getRefParam(createRef(value2)));
434
- } else {
435
- const result = traverse(value2);
436
- if (typeof result === "string") {
437
- values.push(`${quote(key)}:${result}`);
438
575
  } else {
439
- values.push(`${quote(key)}:${result.referred}`);
576
+ values.push(`${key}:${traverseSync(ctx, value2)}`);
440
577
  }
578
+ } else if (ctx.stack.has(value2)) {
579
+ const refParam = getRefParam(ctx, createRef(ctx, value2));
580
+ createObjectComputedAssign(ctx, getCurrentRef(), quote(key), refParam);
581
+ } else {
582
+ values.push(`${quote(key)}:${traverseSync(ctx, value2)}`);
441
583
  }
442
584
  });
443
- STACK.delete(current);
585
+ ctx.stack.delete(current);
444
586
  const value = `{${join(values, ",")}}`;
445
- if (refResult != null) {
446
- return assignRef(refResult, value);
587
+ if (empty) {
588
+ return processRef(`Object.assign(Object.create(null),${value})`);
447
589
  }
448
- return value;
590
+ return processRef(value);
449
591
  }
450
592
  throw new Error("Unserializable value");
451
593
  }
594
+
595
+ // src/index.ts
596
+ function finalize(ctx, source, result) {
597
+ if (ctx.vars.length) {
598
+ const index = getRefParam(ctx, createRef(ctx, source));
599
+ 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}))()`;
603
+ }
604
+ return `(${params}=>(${index}=${result},${patches}${index}))()`;
605
+ }
606
+ if (source.constructor === Object) {
607
+ return `(${result})`;
608
+ }
609
+ return result;
610
+ }
452
611
  function serialize(source) {
453
612
  if (isPrimitive(source)) {
454
613
  return serializePrimitive(source);
455
614
  }
456
- reset();
457
- lookupRefs(source);
458
- for (const [key, value] of REF_COUNT.entries()) {
615
+ const ctx = createSerializationContext();
616
+ lookupRefs(ctx, source);
617
+ for (const [key, value] of ctx.refCount.entries()) {
459
618
  if (value > 1) {
460
- createRef(key);
619
+ createRef(ctx, key);
461
620
  }
462
621
  }
463
- const result = traverse(source);
622
+ const result = traverseSync(ctx, source);
464
623
  if (typeof result !== "string") {
465
624
  throw new Error("Unreachable error");
466
625
  }
467
- if (VARS.length) {
468
- const index = getRefParam(createRef(source));
469
- const patches = resolvePatches();
470
- const params = VARS.length > 1 ? `(${join(VARS, ",")})` : VARS[0];
471
- if (result.startsWith(index)) {
472
- return `(${params}=>(${result},${patches}${index}))()`;
626
+ return finalize(ctx, source, result);
627
+ }
628
+ async function serializeAsync(source) {
629
+ 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);
473
637
  }
474
- return `(${params}=>(${index}=${result},${patches}${index}))()`;
475
638
  }
476
- if (source.constructor === Object) {
477
- return `(${result})`;
639
+ const result = await traverseAsync(ctx, source);
640
+ if (typeof result !== "string") {
641
+ throw new Error("Unreachable error");
478
642
  }
479
- return result;
643
+ return finalize(ctx, source, result);
644
+ }
645
+ function deserialize(source) {
646
+ return (0, eval)(source);
480
647
  }
648
+ var src_default = serialize;
481
649
  //# sourceMappingURL=index.cjs.map