seroval 1.6.12 → 1.7.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,12 +1,15 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/core/compat.ts
3
3
  /**
4
- * References
5
- * - https://compat-table.github.io/compat-table/es6/
6
- * - MDN
4
+ * Public feature bits for `disabledFeatures`. Stays a runtime `enum` so the
5
+ * published declaration is unchanged for consumers. Its values must match
6
+ * the internal bits (checked by test/feature.test.ts).
7
7
  */
8
8
  let Feature = /* @__PURE__ */ function(Feature) {
9
9
  Feature[Feature["AggregateError"] = 1] = "AggregateError";
10
+ /**
11
+ * @deprecated Has no effect. Output always uses arrow functions.
12
+ */
10
13
  Feature[Feature["ArrowFunction"] = 2] = "ArrowFunction";
11
14
  Feature[Feature["ErrorPrototypeStack"] = 4] = "ErrorPrototypeStack";
12
15
  Feature[Feature["ObjectAssign"] = 8] = "ObjectAssign";
@@ -32,35 +35,15 @@ const SYM_TO_STRING_TAG = Symbol.toStringTag;
32
35
  const SYM_UNSCOPABLES = Symbol.unscopables;
33
36
  //#endregion
34
37
  //#region src/core/constants.ts
35
- const SYMBOL_STRING = {
36
- [0]: "Symbol.asyncIterator",
37
- [1]: "Symbol.hasInstance",
38
- [2]: "Symbol.isConcatSpreadable",
39
- [3]: "Symbol.iterator",
40
- [4]: "Symbol.match",
41
- [5]: "Symbol.matchAll",
42
- [6]: "Symbol.replace",
43
- [7]: "Symbol.search",
44
- [8]: "Symbol.species",
45
- [9]: "Symbol.split",
46
- [10]: "Symbol.toPrimitive",
47
- [11]: "Symbol.toStringTag",
48
- [12]: "Symbol.unscopables"
49
- };
50
- const INV_SYMBOL_REF = {
51
- [SYM_ASYNC_ITERATOR]: 0,
52
- [SYM_HAS_INSTANCE]: 1,
53
- [SYM_IS_CONCAT_SPREADABLE]: 2,
54
- [SYM_ITERATOR]: 3,
55
- [SYM_MATCH]: 4,
56
- [SYM_MATCH_ALL]: 5,
57
- [SYM_REPLACE]: 6,
58
- [SYM_SEARCH]: 7,
59
- [SYM_SPECIES]: 8,
60
- [SYM_SPLIT]: 9,
61
- [SYM_TO_PRIMITIVE]: 10,
62
- [SYM_TO_STRING_TAG]: 11,
63
- [SYM_UNSCOPABLES]: 12
38
+ const TEMPORAL_TYPE_NAME = {
39
+ [0]: "Instant",
40
+ [1]: "Duration",
41
+ [2]: "PlainDate",
42
+ [3]: "PlainDateTime",
43
+ [4]: "PlainMonthDay",
44
+ [5]: "PlainTime",
45
+ [6]: "PlainYearMonth",
46
+ [7]: "ZonedDateTime"
64
47
  };
65
48
  const SYMBOL_REF = {
66
49
  [0]: SYM_ASYNC_ITERATOR,
@@ -77,6 +60,18 @@ const SYMBOL_REF = {
77
60
  [11]: SYM_TO_STRING_TAG,
78
61
  [12]: SYM_UNSCOPABLES
79
62
  };
63
+ function createSymbolStringTable() {
64
+ const result = {};
65
+ for (let i = 0; i <= 12; i++) result[i] = SYMBOL_REF[i].description;
66
+ return result;
67
+ }
68
+ const SYMBOL_STRING = /* @__PURE__ */ createSymbolStringTable();
69
+ function createInverseSymbolTable() {
70
+ const result = {};
71
+ for (let i = 0; i <= 12; i++) result[SYMBOL_REF[i]] = i;
72
+ return result;
73
+ }
74
+ const INV_SYMBOL_REF = /* @__PURE__ */ createInverseSymbolTable();
80
75
  const CONSTANT_STRING = {
81
76
  [2]: "!0",
82
77
  [3]: "!1",
@@ -93,19 +88,10 @@ const CONSTANT_VAL = {
93
88
  [1]: void 0,
94
89
  [0]: null,
95
90
  [4]: -0,
96
- [5]: Number.POSITIVE_INFINITY,
97
- [6]: Number.NEGATIVE_INFINITY,
91
+ [5]: Infinity,
92
+ [6]: -Infinity,
98
93
  [7]: NaN
99
94
  };
100
- const ERROR_CONSTRUCTOR_STRING = {
101
- [0]: "Error",
102
- [1]: "EvalError",
103
- [2]: "RangeError",
104
- [3]: "ReferenceError",
105
- [4]: "SyntaxError",
106
- [5]: "TypeError",
107
- [6]: "URIError"
108
- };
109
95
  const ERROR_CONSTRUCTOR = {
110
96
  [0]: Error,
111
97
  [1]: EvalError,
@@ -115,9 +101,20 @@ const ERROR_CONSTRUCTOR = {
115
101
  [5]: TypeError,
116
102
  [6]: URIError
117
103
  };
104
+ function createErrorConstructorStringTable() {
105
+ const result = {};
106
+ for (let i = 0; i <= 6; i++) result[i] = ERROR_CONSTRUCTOR[i].name;
107
+ return result;
108
+ }
109
+ const ERROR_CONSTRUCTOR_STRING = /* @__PURE__ */ createErrorConstructorStringTable();
118
110
  //#endregion
119
111
  //#region src/core/node.ts
120
112
  function createSerovalNode(t, i, s, c, m, p, e, a, f, b, o, l) {
113
+ if (c === void 0 && m === void 0 && p === void 0 && e === void 0 && a === void 0 && f === void 0 && b === void 0 && o === void 0 && l === void 0) return {
114
+ t,
115
+ i,
116
+ s
117
+ };
121
118
  return {
122
119
  t,
123
120
  i,
@@ -136,7 +133,7 @@ function createSerovalNode(t, i, s, c, m, p, e, a, f, b, o, l) {
136
133
  //#endregion
137
134
  //#region src/core/literals.ts
138
135
  function createConstantNode(value) {
139
- return createSerovalNode(2, void 0, value, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
136
+ return createSerovalNode(2, void 0, value);
140
137
  }
141
138
  const TRUE_NODE = /* @__PURE__ */ createConstantNode(2);
142
139
  const FALSE_NODE = /* @__PURE__ */ createConstantNode(3);
@@ -149,60 +146,109 @@ const NAN_NODE = /* @__PURE__ */ createConstantNode(7);
149
146
  //#endregion
150
147
  //#region src/core/string.ts
151
148
  const MIN_JSON_STRINGIFY_LENGTH = 64;
152
- const JSON_ESCAPE_DIFFERENCES = /[\x00-\x07\x0b\x0e-\x1f<\u2028\u2029\ud800-\udfff]/;
153
- function serializeChar(str) {
154
- switch (str) {
155
- case "\"": return "\\\"";
156
- case "\\": return "\\\\";
157
- case "\n": return "\\n";
158
- case "\r": return "\\r";
159
- case "\b": return "\\b";
160
- case " ": return "\\t";
161
- case "\f": return "\\f";
162
- case "<": return "\\x3C";
163
- case "\u2028": return "\\u2028";
164
- case "\u2029": return "\\u2029";
149
+ const NEEDS_ESCAPE = /["\\\n\r\b\t\f<\u2028\u2029]/;
150
+ const JSON_ESCAPE_DIFFERENCES = /[\x00-\x07\x0b\x0e-\x1f\ud800-\udfff]/;
151
+ const LESS_THAN = /</g;
152
+ const LINE_SEPARATOR = /\u2028/g;
153
+ const PARAGRAPH_SEPARATOR = /\u2029/g;
154
+ function escapeCharCode(code) {
155
+ switch (code) {
156
+ case 34: return "\\\"";
157
+ case 92: return "\\\\";
158
+ case 10: return "\\n";
159
+ case 13: return "\\r";
160
+ case 8: return "\\b";
161
+ case 9: return "\\t";
162
+ case 12: return "\\f";
163
+ case 60: return "\\x3C";
164
+ case 8232: return "\\u2028";
165
+ case 8233: return "\\u2029";
165
166
  default: return;
166
167
  }
167
168
  }
168
169
  function serializeString(str) {
169
- if (str.length >= MIN_JSON_STRINGIFY_LENGTH && !JSON_ESCAPE_DIFFERENCES.test(str)) return JSON.stringify(str).slice(1, -1);
170
+ if (!NEEDS_ESCAPE.test(str)) return str;
171
+ if (str.length >= MIN_JSON_STRINGIFY_LENGTH && !JSON_ESCAPE_DIFFERENCES.test(str)) {
172
+ let result = JSON.stringify(str).slice(1, -1);
173
+ if (result.includes("<")) result = result.replace(LESS_THAN, "\\x3C");
174
+ if (result.includes("\u2028")) result = result.replace(LINE_SEPARATOR, "\\u2028");
175
+ if (result.includes("\u2029")) result = result.replace(PARAGRAPH_SEPARATOR, "\\u2029");
176
+ return result;
177
+ }
170
178
  let result = "";
171
179
  let lastPos = 0;
172
180
  let replacement;
173
181
  for (let i = 0, len = str.length; i < len; i++) {
174
- replacement = serializeChar(str[i]);
182
+ replacement = escapeCharCode(str.charCodeAt(i));
175
183
  if (replacement) {
176
184
  result += str.slice(lastPos, i) + replacement;
177
185
  lastPos = i + 1;
178
186
  }
179
187
  }
180
- if (lastPos === 0) result = str;
181
- else result += str.slice(lastPos);
182
- return result;
183
- }
184
- function deserializeReplacer(str) {
185
- switch (str) {
186
- case "\\\\": return "\\";
187
- case "\\\"": return "\"";
188
- case "\\n": return "\n";
189
- case "\\r": return "\r";
190
- case "\\b": return "\b";
191
- case "\\t": return " ";
192
- case "\\f": return "\f";
193
- case "\\x3C": return "<";
194
- case "\\u2028": return "\u2028";
195
- case "\\u2029": return "\u2029";
196
- default: return str;
197
- }
188
+ return result + str.slice(lastPos);
198
189
  }
190
+ const JSON_COMPATIBLE = /^(?:[^"\\\x00-\x1f]|\\["\\nrbtf])*$/;
191
+ const ESCAPE_SEQUENCE = /(\\\\|\\"|\\n|\\r|\\b|\\t|\\f|\\u2028|\\u2029|\\x3C)/g;
199
192
  function deserializeString(str) {
200
- if (typeof str === "string" && !str.includes("\\")) return str;
201
- return str.replace(/(\\\\|\\"|\\n|\\r|\\b|\\t|\\f|\\u2028|\\u2029|\\x3C)/g, deserializeReplacer);
193
+ if (typeof str !== "string") return str.replace(ESCAPE_SEQUENCE, deserializeString);
194
+ let index = str.indexOf("\\");
195
+ if (index === -1) return str;
196
+ if (JSON_COMPATIBLE.test(str)) return JSON.parse("\"" + str + "\"");
197
+ let result = "";
198
+ let lastPos = 0;
199
+ const last = str.length - 1;
200
+ while (index !== -1 && index < last) {
201
+ let replacement;
202
+ let length = 2;
203
+ switch (str.charCodeAt(index + 1)) {
204
+ case 92:
205
+ replacement = "\\";
206
+ break;
207
+ case 34:
208
+ replacement = "\"";
209
+ break;
210
+ case 110:
211
+ replacement = "\n";
212
+ break;
213
+ case 114:
214
+ replacement = "\r";
215
+ break;
216
+ case 98:
217
+ replacement = "\b";
218
+ break;
219
+ case 116:
220
+ replacement = " ";
221
+ break;
222
+ case 102:
223
+ replacement = "\f";
224
+ break;
225
+ case 120:
226
+ if (str.startsWith("3C", index + 2)) {
227
+ replacement = "<";
228
+ length = 4;
229
+ }
230
+ break;
231
+ case 117: if (str.startsWith("2028", index + 2)) {
232
+ replacement = "\u2028";
233
+ length = 6;
234
+ } else if (str.startsWith("2029", index + 2)) {
235
+ replacement = "\u2029";
236
+ length = 6;
237
+ }
238
+ }
239
+ if (replacement) {
240
+ result += str.slice(lastPos, index) + replacement;
241
+ lastPos = index + length;
242
+ index = str.indexOf("\\", lastPos);
243
+ } else index = str.indexOf("\\", index + 1);
244
+ }
245
+ return result + str.slice(lastPos);
202
246
  }
203
247
  //#endregion
204
248
  //#region src/core/errors.ts
205
- const { toString: objectToString } = Object.prototype;
249
+ function objectToString(value) {
250
+ return Object.prototype.toString.call(value);
251
+ }
206
252
  function getErrorMessageDev(type, cause) {
207
253
  if (cause instanceof Error) return `Seroval caught an error during the ${type} process.
208
254
 
@@ -213,14 +259,13 @@ ${cause.message}
213
259
  - If you believe this is an error in Seroval, please submit an issue at https://github.com/lxsmnsyc/seroval/issues/new`;
214
260
  return `Seroval caught an error during the ${type} process.
215
261
 
216
- "${objectToString.call(cause)}"
262
+ "${objectToString(cause)}"
217
263
 
218
264
  For more information, please check the "cause" property of this error.`;
219
265
  }
220
- const getErrorMessage = (type, cause) => getErrorMessageDev(type, cause);
221
266
  var SerovalError = class extends Error {
222
267
  constructor(type, cause) {
223
- super(getErrorMessage(type, cause));
268
+ super(getErrorMessageDev(type, cause));
224
269
  this.cause = cause;
225
270
  }
226
271
  };
@@ -241,7 +286,7 @@ var SerovalDeserializationError = class extends SerovalError {
241
286
  };
242
287
  var SerovalUnsupportedTypeError = class extends Error {
243
288
  constructor(value) {
244
- super(`The value ${objectToString.call(value)} of type "${typeof value}" cannot be parsed/serialized.
289
+ super(`The value ${objectToString(value)} of type "${typeof value}" cannot be parsed/serialized.
245
290
 
246
291
  There are few workarounds for this problem:
247
292
  - Transform the value in a way that it can be serialized.
@@ -264,9 +309,13 @@ var SerovalMissingInstanceError = class extends Error {
264
309
  super("Missing \"" + tag + "\" instance.");
265
310
  }
266
311
  };
312
+ /**
313
+ * @deprecated Not thrown by seroval. A missing `createReference` key throws
314
+ * {@link SerovalMissingReferenceForIdError} instead.
315
+ */
267
316
  var SerovalMissingReferenceError = class extends Error {
268
317
  constructor(value) {
269
- super("Missing reference for the value \"" + objectToString.call(value) + "\" of type \"" + typeof value + "\"");
318
+ super("Missing reference for the value \"" + objectToString(value) + "\" of type \"" + typeof value + "\"");
270
319
  this.value = value;
271
320
  }
272
321
  };
@@ -295,103 +344,43 @@ var SerovalDepthLimitError = class extends Error {
295
344
  super("Depth limit of " + limit + " reached");
296
345
  }
297
346
  };
298
- //#endregion
299
- //#region src/core/keys.ts
300
- const REFERENCES_KEY = "__SEROVAL_REFS__";
301
- const GLOBAL_CONTEXT_R = `self.\$R`;
302
- function getCrossReferenceHeader(id) {
303
- if (id == null) return `${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||[]`;
304
- return `(${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||{})["${serializeString(id)}"]=[]`;
305
- }
306
- //#endregion
307
- //#region src/core/reference.ts
308
- const REFERENCE = /* @__PURE__ */ new Map();
309
- const INV_REFERENCE = /* @__PURE__ */ new Map();
310
- function createReference(id, value) {
311
- REFERENCE.set(value, id);
312
- INV_REFERENCE.set(id, value);
313
- return value;
314
- }
315
- function hasReferenceID(value) {
316
- return REFERENCE.has(value);
317
- }
318
- function hasReference(id) {
319
- return INV_REFERENCE.has(id);
320
- }
321
- function getReferenceID(value) {
322
- if (hasReferenceID(value)) return REFERENCE.get(value);
323
- throw new SerovalMissingReferenceError(value);
324
- }
325
- function getReference(id) {
326
- if (hasReference(id)) return INV_REFERENCE.get(id);
327
- throw new SerovalMissingReferenceForIdError(id);
328
- }
329
- if (typeof globalThis !== "undefined") Object.defineProperty(globalThis, REFERENCES_KEY, {
330
- value: INV_REFERENCE,
331
- configurable: true,
332
- writable: false,
333
- enumerable: false
334
- });
335
- else if (typeof window !== "undefined") Object.defineProperty(window, REFERENCES_KEY, {
336
- value: INV_REFERENCE,
337
- configurable: true,
338
- writable: false,
339
- enumerable: false
340
- });
341
- else if (typeof self !== "undefined") Object.defineProperty(self, REFERENCES_KEY, {
342
- value: INV_REFERENCE,
343
- configurable: true,
344
- writable: false,
345
- enumerable: false
346
- });
347
- else if (typeof global !== "undefined") Object.defineProperty(global, REFERENCES_KEY, {
348
- value: INV_REFERENCE,
349
- configurable: true,
350
- writable: false,
351
- enumerable: false
352
- });
347
+ var SerovalAbortedError = class extends Error {
348
+ constructor() {
349
+ super("Cross deserializer has been aborted.");
350
+ }
351
+ };
352
+ const LIVE_STREAM_ERROR_MESSAGES = {
353
+ consumed: "Live stream already has a consumer",
354
+ pending: "Live stream already has a pending event",
355
+ reading: "Live stream already has a pending read",
356
+ closed: "Live stream is closed"
357
+ };
358
+ var SerovalLiveStreamError = class extends Error {
359
+ constructor(reason) {
360
+ super(LIVE_STREAM_ERROR_MESSAGES[reason]);
361
+ this.reason = reason;
362
+ }
363
+ };
353
364
  //#endregion
354
365
  //#region src/core/utils/error.ts
355
366
  function getErrorConstructor(error) {
356
- if (error instanceof EvalError) return 1;
357
- if (error instanceof RangeError) return 2;
358
- if (error instanceof ReferenceError) return 3;
359
- if (error instanceof SyntaxError) return 4;
360
- if (error instanceof TypeError) return 5;
361
- if (error instanceof URIError) return 6;
367
+ for (let i = 1; i <= 6; i++) if (error instanceof ERROR_CONSTRUCTOR[i]) return i;
362
368
  return 0;
363
369
  }
364
- function getInitialErrorOptions(error) {
365
- const construct = ERROR_CONSTRUCTOR_STRING[getErrorConstructor(error)];
366
- if (error.name !== construct) return { name: error.name };
367
- if (error.constructor.name !== construct) return { name: error.constructor.name };
368
- return {};
369
- }
370
370
  function getErrorOptions(error, features) {
371
- let options = getInitialErrorOptions(error);
372
- const names = Object.getOwnPropertyNames(error);
373
- for (let i = 0, len = names.length, name; i < len; i++) {
374
- name = names[i];
375
- if (name !== "name" && name !== "message") {
376
- if (name === "stack") {
377
- if (features & 4) {
378
- options = options || {};
379
- options[name] = error[name];
380
- }
381
- } else {
382
- options = options || {};
383
- options[name] = error[name];
384
- }
385
- }
386
- }
371
+ const options = Object.create(null);
372
+ const construct = ERROR_CONSTRUCTOR_STRING[getErrorConstructor(error)];
373
+ if (error.name !== construct) options.name = error.name;
374
+ else if (error.constructor.name !== construct) options.name = error.constructor.name;
375
+ for (const name of Object.getOwnPropertyNames(error)) if (name !== "name" && name !== "message" && (name !== "stack" || features & 4)) options[name] = error[name];
387
376
  return options;
388
377
  }
389
378
  //#endregion
390
379
  //#region src/core/utils/get-object-flag.ts
391
380
  function getObjectFlag(obj) {
381
+ if (Object.isExtensible(obj)) return 0;
392
382
  if (Object.isFrozen(obj)) return 3;
393
383
  if (Object.isSealed(obj)) return 2;
394
- if (Object.isExtensible(obj)) return 0;
395
384
  return 1;
396
385
  }
397
386
  //#endregion
@@ -426,86 +415,265 @@ function createNumberNode(value) {
426
415
  }
427
416
  if (value !== value) return NAN_NODE;
428
417
  if (Object.is(value, -0)) return NEG_ZERO_NODE;
429
- return createSerovalNode(0, void 0, value, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
418
+ return createSerovalNode(0, void 0, value);
430
419
  }
431
420
  function createStringNode(value) {
432
- return createSerovalNode(1, void 0, serializeString(value), void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
421
+ return createSerovalNode(1, void 0, serializeString(value));
433
422
  }
434
423
  function createBigIntNode(current) {
435
- return createSerovalNode(3, void 0, "" + current, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
424
+ return createSerovalNode(3, void 0, "" + current);
436
425
  }
437
426
  function createIndexedValueNode(id) {
438
- return createSerovalNode(4, id, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
427
+ return createSerovalNode(4, id);
439
428
  }
440
429
  function createDateNode(id, current) {
441
430
  const timestamp = current.valueOf();
442
- return createSerovalNode(5, id, timestamp !== timestamp ? "" : current.toISOString(), void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
431
+ return createSerovalNode(5, id, timestamp === timestamp ? current.toISOString() : "");
443
432
  }
444
433
  function createTemporalNode(id, type, current) {
445
- return createSerovalNode(36, id, current.toString(), type, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
434
+ return createSerovalNode(36, id, current.toString(), type);
446
435
  }
447
436
  function createRegExpNode(id, current) {
448
- return createSerovalNode(6, id, void 0, serializeString(current.source), current.flags, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
437
+ return createSerovalNode(6, id, void 0, serializeString(current.source), current.flags);
449
438
  }
450
439
  function createWKSymbolNode(id, current) {
451
- return createSerovalNode(17, id, INV_SYMBOL_REF[current], void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
440
+ return createSerovalNode(17, id, INV_SYMBOL_REF[current]);
452
441
  }
453
- function createReferenceNode(id, ref) {
454
- return createSerovalNode(18, id, serializeString(getReferenceID(ref)), void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
442
+ function createReferenceNode(id, referenceId) {
443
+ return createSerovalNode(18, id, serializeString(referenceId));
455
444
  }
456
445
  function createPluginNode(id, tag, value) {
457
- return createSerovalNode(25, id, value, serializeString(tag), void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
446
+ return createSerovalNode(25, id, value, serializeString(tag));
458
447
  }
459
448
  function createArrayNode(id, current, parsedItems) {
460
- return createSerovalNode(9, id, void 0, void 0, void 0, void 0, void 0, parsedItems, void 0, void 0, getObjectFlag(current), void 0);
449
+ return createSerovalNode(9, id, void 0, void 0, void 0, void 0, void 0, parsedItems, void 0, void 0, getObjectFlag(current));
461
450
  }
462
451
  function createBoxedNode(id, boxed) {
463
- return createSerovalNode(21, id, void 0, void 0, void 0, void 0, void 0, void 0, boxed, void 0, void 0, void 0);
452
+ return createSerovalNode(21, id, void 0, void 0, void 0, void 0, void 0, void 0, boxed);
464
453
  }
465
454
  const MAX_TYPED_ARRAY_LENGTH = 1e6;
466
- function createTypedArrayNode(id, current, buffer) {
467
- if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
468
- return createSerovalNode(15, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
469
- }
470
- function createBigIntTypedArrayNode(id, current, buffer) {
471
- if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
472
- return createSerovalNode(16, id, void 0, getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
473
- }
474
- function createDataViewNode(id, current, buffer) {
475
- if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
476
- return createSerovalNode(20, id, void 0, void 0, void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.byteLength);
455
+ function createViewNode(type, id, current, buffer) {
456
+ const isDataView = type === 20;
457
+ const size = isDataView ? current.byteLength : current.length;
458
+ if (size > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
459
+ return createSerovalNode(type, id, void 0, isDataView ? void 0 : getTypedArrayName(current), void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, size);
477
460
  }
478
- function createErrorNode(id, current, options) {
479
- return createSerovalNode(13, id, getErrorConstructor(current), void 0, serializeString(current.message), options, void 0, void 0, void 0, void 0, void 0, void 0);
480
- }
481
- function createAggregateErrorNode(id, current, options) {
482
- return createSerovalNode(14, id, getErrorConstructor(current), void 0, serializeString(current.message), options, void 0, void 0, void 0, void 0, void 0, void 0);
461
+ function createErrorNode(type, id, current, options) {
462
+ return createSerovalNode(type, id, getErrorConstructor(current), void 0, serializeString(current.message), options);
483
463
  }
484
464
  function createSetNode(id, items) {
485
- return createSerovalNode(7, id, void 0, void 0, void 0, void 0, void 0, items, void 0, void 0, void 0, void 0);
486
- }
487
- function createIteratorFactoryInstanceNode(factory, items) {
488
- return createSerovalNode(28, void 0, void 0, void 0, void 0, void 0, void 0, [factory, items], void 0, void 0, void 0, void 0);
489
- }
490
- function createAsyncIteratorFactoryInstanceNode(factory, items) {
491
- return createSerovalNode(30, void 0, void 0, void 0, void 0, void 0, void 0, [factory, items], void 0, void 0, void 0, void 0);
492
- }
493
- function createStreamConstructorNode(id, factory, sequence) {
494
- return createSerovalNode(31, id, void 0, void 0, void 0, void 0, void 0, sequence, factory, void 0, void 0, void 0);
465
+ return createSerovalNode(7, id, void 0, void 0, void 0, void 0, void 0, items);
495
466
  }
496
- function createStreamNextNode(id, parsed) {
497
- return createSerovalNode(32, id, void 0, void 0, void 0, void 0, void 0, void 0, parsed, void 0, void 0, void 0);
467
+ function createIteratorFactoryInstanceNode(type, factory, items) {
468
+ return createSerovalNode(type, void 0, void 0, void 0, void 0, void 0, void 0, [factory, items]);
498
469
  }
499
- function createStreamThrowNode(id, parsed) {
500
- return createSerovalNode(33, id, void 0, void 0, void 0, void 0, void 0, void 0, parsed, void 0, void 0, void 0);
470
+ function createStreamConstructorNode(id, factory, sequence, live) {
471
+ return createSerovalNode(31, id, void 0, void 0, void 0, void 0, void 0, sequence, factory, void 0, void 0, live);
501
472
  }
502
- function createStreamReturnNode(id, parsed) {
503
- return createSerovalNode(34, id, void 0, void 0, void 0, void 0, void 0, void 0, parsed, void 0, void 0, void 0);
473
+ function createStreamEventNode(type, id, parsed) {
474
+ return createSerovalNode(type, id, void 0, void 0, void 0, void 0, void 0, void 0, parsed);
504
475
  }
505
476
  function createSequenceNode(id, sequence, throwAt, doneAt) {
506
477
  return createSerovalNode(35, id, throwAt, void 0, void 0, void 0, void 0, sequence, void 0, void 0, void 0, doneAt);
507
478
  }
508
479
  //#endregion
480
+ //#region src/core/live-stream.ts
481
+ function isLiveStream(value) {
482
+ return value instanceof LiveStream;
483
+ }
484
+ /**
485
+ * A single-consumer stream for incremental serialization. Unlike
486
+ * `createStream`, it keeps no history: at most one event is held, and the
487
+ * producer operation that sent it settles only when the consumer accepts it.
488
+ *
489
+ * An internal class rather than a tagged POJO: identity is checked with
490
+ * `instanceof`, which untrusted input cannot forge. The class is exported
491
+ * because bundlers cannot drop an unexported top-level class.
492
+ */
493
+ var LiveStream = class {
494
+ constructor(options) {
495
+ this.consumed = false;
496
+ this.closed = false;
497
+ this.cancelled = false;
498
+ this.options = options;
499
+ }
500
+ deliver(reader, record) {
501
+ record.delivered = true;
502
+ reader.resolve({
503
+ event: record.event,
504
+ accept: () => {
505
+ if (this.pending === record && record.delivered) {
506
+ const terminal = record.event.type !== "next";
507
+ record.event = void 0;
508
+ this.pending = void 0;
509
+ const resolve = record.resolve;
510
+ record.resolve = void 0;
511
+ record.reject = void 0;
512
+ if (terminal) {
513
+ this.closed = true;
514
+ this.options = void 0;
515
+ const waiter = this.waiting;
516
+ this.waiting = void 0;
517
+ waiter?.reject(new SerovalLiveStreamError("closed"));
518
+ }
519
+ resolve?.();
520
+ }
521
+ }
522
+ });
523
+ }
524
+ /** @internal */
525
+ push(event) {
526
+ if (this.cancelled) return Promise.reject(this.cancelReason);
527
+ if (this.closed) return Promise.reject(new SerovalLiveStreamError("closed"));
528
+ if (this.pending) return Promise.reject(new SerovalLiveStreamError("pending"));
529
+ return new Promise((resolve, reject) => {
530
+ const record = {
531
+ event,
532
+ delivered: false,
533
+ resolve,
534
+ reject
535
+ };
536
+ this.pending = record;
537
+ if (this.waiting) {
538
+ const waiter = this.waiting;
539
+ this.waiting = void 0;
540
+ this.deliver(waiter, record);
541
+ }
542
+ });
543
+ }
544
+ cancel(reason) {
545
+ if (this.cancelled || this.closed) return;
546
+ this.cancelled = true;
547
+ this.cancelReason = reason;
548
+ const record = this.pending;
549
+ const waiter = this.waiting;
550
+ this.pending = void 0;
551
+ this.waiting = void 0;
552
+ const callbackOwner = this.options;
553
+ this.options = void 0;
554
+ if (record) {
555
+ record.event = void 0;
556
+ const reject = record.reject;
557
+ record.resolve = void 0;
558
+ record.reject = void 0;
559
+ reject?.(reason);
560
+ }
561
+ if (waiter) waiter.reject(reason);
562
+ callbackOwner?.onCancel?.(reason);
563
+ }
564
+ read() {
565
+ if (this.cancelled) return Promise.reject(this.cancelReason);
566
+ if (this.closed) return Promise.reject(new SerovalLiveStreamError("closed"));
567
+ if (this.waiting) return Promise.reject(new SerovalLiveStreamError("reading"));
568
+ return new Promise((resolve, reject) => {
569
+ const next = {
570
+ resolve,
571
+ reject
572
+ };
573
+ if (this.pending && !this.pending.delivered) this.deliver(next, this.pending);
574
+ else this.waiting = next;
575
+ });
576
+ }
577
+ consume() {
578
+ if (this.consumed) throw new SerovalLiveStreamError("consumed");
579
+ this.consumed = true;
580
+ return {
581
+ read: () => this.read(),
582
+ cancel: (reason) => this.cancel(reason)
583
+ };
584
+ }
585
+ /**
586
+ * Consumes the stream through a replay-style listener, accepting each
587
+ * event as soon as it has been delivered. Use `consume` or `pump` when
588
+ * acceptance must wait for processing.
589
+ */
590
+ on(listener) {
591
+ const wrap = (key) => (value, accept) => {
592
+ listener[key](value);
593
+ accept();
594
+ };
595
+ return this.pump({
596
+ next: wrap("next"),
597
+ throw: wrap("throw"),
598
+ return: wrap("return")
599
+ });
600
+ }
601
+ /**
602
+ * Consumes the stream into a sink that controls acceptance. Returns the
603
+ * cancel function.
604
+ * @internal
605
+ */
606
+ pump(sink) {
607
+ const consumer = this.consume();
608
+ let current = sink;
609
+ function next() {
610
+ consumer.read().then((delivery) => {
611
+ const target = current;
612
+ if (!target) return;
613
+ const event = delivery.event;
614
+ let failure;
615
+ let failed = false;
616
+ try {
617
+ failure = target[event.type](event.type === "throw" ? event.error : event.value, delivery.accept);
618
+ } catch (error) {
619
+ failed = true;
620
+ failure = error;
621
+ }
622
+ if (failed || failure !== void 0) {
623
+ current = void 0;
624
+ try {
625
+ consumer.cancel(failure);
626
+ } finally {
627
+ target.done?.();
628
+ }
629
+ return;
630
+ }
631
+ if (event.type === "next") {
632
+ next();
633
+ return;
634
+ }
635
+ current = void 0;
636
+ target.done?.();
637
+ }, (reason) => {
638
+ const target = current;
639
+ current = void 0;
640
+ target?.error?.(reason);
641
+ });
642
+ }
643
+ next();
644
+ return consumer.cancel;
645
+ }
646
+ };
647
+ /**
648
+ * Creates a live stream and the producer that writes to it.
649
+ */
650
+ function createLiveStream(options) {
651
+ const stream = new LiveStream(options);
652
+ return {
653
+ stream,
654
+ producer: {
655
+ write(value) {
656
+ return stream.push({
657
+ type: "next",
658
+ value
659
+ });
660
+ },
661
+ close(value) {
662
+ return stream.push({
663
+ type: "return",
664
+ value
665
+ });
666
+ },
667
+ fail(error) {
668
+ return stream.push({
669
+ type: "throw",
670
+ error
671
+ });
672
+ }
673
+ }
674
+ };
675
+ }
676
+ //#endregion
509
677
  //#region src/core/opaque-reference.ts
510
678
  /**
511
679
  * An opaque reference allows hiding values from the serializer.
@@ -543,7 +711,7 @@ const PROMISE_FAILURE = (resolver, data) => {
543
711
  const SERIALIZED_PROMISE_CONSTRUCTOR = /* @__PURE__ */ PROMISE_CONSTRUCTOR.toString();
544
712
  const SERIALIZED_PROMISE_SUCCESS = /* @__PURE__ */ PROMISE_SUCCESS.toString();
545
713
  const SERIALIZED_PROMISE_FAILURE = /* @__PURE__ */ PROMISE_FAILURE.toString();
546
- const STREAM_CONSTRUCTOR = () => {
714
+ const STREAM_CONSTRUCTOR = (live) => {
547
715
  const buffer = [];
548
716
  const listeners = [];
549
717
  let alive = true;
@@ -551,6 +719,7 @@ const STREAM_CONSTRUCTOR = () => {
551
719
  let count = 0;
552
720
  const internal = {
553
721
  flush(value, mode, x) {
722
+ live > 1 || buffer.push(value);
554
723
  for (x = 0; x < count; x++) {
555
724
  const listener = listeners[x];
556
725
  if (listener) listener[mode](value);
@@ -564,6 +733,7 @@ const STREAM_CONSTRUCTOR = () => {
564
733
  }
565
734
  },
566
735
  on(listener, temp = 0) {
736
+ if (live > 1) throw new Error("Stream consumed");
567
737
  let subscribed = alive;
568
738
  if (alive) {
569
739
  for (temp = 0; temp < count; temp++) if (!listeners[temp]) break;
@@ -571,6 +741,10 @@ const STREAM_CONSTRUCTOR = () => {
571
741
  listeners[temp] = listener;
572
742
  }
573
743
  internal.up(listener);
744
+ if (live) {
745
+ live = 2;
746
+ buffer.length = 0;
747
+ }
574
748
  return () => {
575
749
  if (alive && subscribed) {
576
750
  subscribed = false;
@@ -587,14 +761,10 @@ const STREAM_CONSTRUCTOR = () => {
587
761
  return internal.on(listener);
588
762
  },
589
763
  next(value) {
590
- if (alive) {
591
- buffer.push(value);
592
- internal.flush(value, "next");
593
- }
764
+ if (alive) internal.flush(value, "next");
594
765
  },
595
766
  throw(value) {
596
767
  if (alive) {
597
- buffer.push(value);
598
768
  internal.flush(value, "throw");
599
769
  alive = false;
600
770
  success = false;
@@ -603,7 +773,6 @@ const STREAM_CONSTRUCTOR = () => {
603
773
  },
604
774
  return(value) {
605
775
  if (alive) {
606
- buffer.push(value);
607
776
  internal.flush(value, "return");
608
777
  alive = false;
609
778
  success = true;
@@ -725,7 +894,8 @@ const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR = /* @__PURE__ */ ARRAY_BUFFER_CONSTRU
725
894
  //#region src/core/sequence.ts
726
895
  /**
727
896
  * An internal class rather than a tagged POJO: identity is checked with
728
- * `instanceof`, which untrusted input cannot forge (the class is not exported).
897
+ * `instanceof`, which untrusted input cannot forge. The class is exported
898
+ * because bundlers cannot drop an unexported top-level class.
729
899
  * The eval-based `deserialize` path still rebuilds a `{__SEROVAL_SEQUENCE__…}`
730
900
  * POJO from embedded source - it has no access to this class - so a value read
731
901
  * back through `deserialize` is not an instance and, by design, is not treated
@@ -749,7 +919,7 @@ function createSequenceFromIterable(source) {
749
919
  let throwsAt = -1;
750
920
  let doneAt = -1;
751
921
  const iterator = source[SYM_ITERATOR]();
752
- while (true) try {
922
+ for (;;) try {
753
923
  const value = iterator.next();
754
924
  values.push(value.value);
755
925
  if (value.done) {
@@ -764,7 +934,7 @@ function createSequenceFromIterable(source) {
764
934
  }
765
935
  return createSequence(values, throwsAt, doneAt);
766
936
  }
767
- const createIterator = ITERATOR_CONSTRUCTOR(SYM_ITERATOR);
937
+ const createIterator = /* @__PURE__ */ ITERATOR_CONSTRUCTOR(SYM_ITERATOR);
768
938
  function sequenceToIterator(sequence) {
769
939
  return createIterator(sequence);
770
940
  }
@@ -795,7 +965,8 @@ const SPECIAL_REF_STRING = {
795
965
  //#region src/core/stream.ts
796
966
  /**
797
967
  * An internal class rather than a tagged POJO: identity is checked with
798
- * `instanceof`, which untrusted input cannot forge (the class is not exported).
968
+ * `instanceof`, which untrusted input cannot forge. The class is exported
969
+ * because bundlers cannot drop an unexported top-level class.
799
970
  *
800
971
  * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
801
972
  * constructor's source is embedded verbatim into the eval-based `deserialize`
@@ -805,18 +976,17 @@ const SPECIAL_REF_STRING = {
805
976
  * implementations in sync.
806
977
  */
807
978
  var Stream = class {
808
- constructor() {
979
+ constructor(live) {
809
980
  this.buffer = [];
810
981
  this.listeners = [];
811
982
  this.alive = true;
812
983
  this.success = false;
813
984
  this.count = 0;
985
+ this.live = live;
814
986
  }
815
987
  flush(value, mode) {
816
- for (let x = 0; x < this.count; x++) {
817
- var _this$listeners$x;
818
- (_this$listeners$x = this.listeners[x]) === null || _this$listeners$x === void 0 || _this$listeners$x[mode](value);
819
- }
988
+ this.live > 1 || this.buffer.push(value);
989
+ for (let x = 0; x < this.count; x++) this.listeners[x]?.[mode](value);
820
990
  }
821
991
  replay(listener) {
822
992
  for (let x = 0, z = this.buffer.length; x < z; x++) {
@@ -826,6 +996,7 @@ var Stream = class {
826
996
  }
827
997
  }
828
998
  on(listener) {
999
+ if (this.live > 1) throw new Error("Stream consumed");
829
1000
  let subscribed = this.alive;
830
1001
  let temp = 0;
831
1002
  if (subscribed) {
@@ -834,6 +1005,10 @@ var Stream = class {
834
1005
  this.listeners[temp] = listener;
835
1006
  }
836
1007
  this.replay(listener);
1008
+ if (this.live) {
1009
+ this.live = 2;
1010
+ this.buffer.length = 0;
1011
+ }
837
1012
  return () => {
838
1013
  if (this.alive && subscribed) {
839
1014
  subscribed = false;
@@ -844,14 +1019,10 @@ var Stream = class {
844
1019
  };
845
1020
  }
846
1021
  next(value) {
847
- if (this.alive) {
848
- this.buffer.push(value);
849
- this.flush(value, "next");
850
- }
1022
+ if (this.alive) this.flush(value, "next");
851
1023
  }
852
1024
  throw(value) {
853
1025
  if (this.alive) {
854
- this.buffer.push(value);
855
1026
  this.flush(value, "throw");
856
1027
  this.alive = false;
857
1028
  this.success = false;
@@ -860,7 +1031,6 @@ var Stream = class {
860
1031
  }
861
1032
  return(value) {
862
1033
  if (this.alive) {
863
- this.buffer.push(value);
864
1034
  this.flush(value, "return");
865
1035
  this.alive = false;
866
1036
  this.success = true;
@@ -869,46 +1039,12 @@ var Stream = class {
869
1039
  }
870
1040
  };
871
1041
  function isStream(value) {
872
- return value instanceof Stream;
1042
+ return value instanceof Stream || isLiveStream(value);
873
1043
  }
874
1044
  function createStream() {
875
1045
  return new Stream();
876
1046
  }
877
- function createStreamFromAsyncIterable(iterable, cleanups) {
878
- const stream = createStream();
879
- const iterator = iterable[SYM_ASYNC_ITERATOR]();
880
- let cancelled = false;
881
- let done = false;
882
- cleanups === null || cleanups === void 0 || cleanups.push(() => {
883
- if (!(done || cancelled)) {
884
- cancelled = true;
885
- Promise.resolve().then(() => {
886
- var _iterator$return;
887
- return (_iterator$return = iterator.return) === null || _iterator$return === void 0 ? void 0 : _iterator$return.call(iterator);
888
- }).catch(() => {});
889
- }
890
- });
891
- async function push() {
892
- try {
893
- while (!cancelled) {
894
- const value = await iterator.next();
895
- if (cancelled) return;
896
- if (value.done) {
897
- done = true;
898
- stream.return(value.value);
899
- break;
900
- }
901
- stream.next(value.value);
902
- }
903
- } catch (error) {
904
- done = true;
905
- if (!cancelled) stream.throw(error);
906
- }
907
- }
908
- push().catch(() => {});
909
- return stream;
910
- }
911
- const createAsyncIterable = ASYNC_ITERATOR_CONSTRUCTOR(SYM_ASYNC_ITERATOR, PROMISE_CONSTRUCTOR);
1047
+ const createAsyncIterable = /* @__PURE__ */ ASYNC_ITERATOR_CONSTRUCTOR(SYM_ASYNC_ITERATOR, PROMISE_CONSTRUCTOR);
912
1048
  function streamToAsyncIterable(stream) {
913
1049
  return createAsyncIterable(stream);
914
1050
  }
@@ -922,20 +1058,158 @@ async function promiseToResult(current) {
922
1058
  }
923
1059
  }
924
1060
  //#endregion
1061
+ //#region src/core/binary-browser.ts
1062
+ function encodeArrayBuffer$1(current) {
1063
+ const bytes = new Uint8Array(current);
1064
+ if (typeof bytes.toBase64 === "function") return bytes.toBase64();
1065
+ let result = "";
1066
+ for (let i = 0, len = bytes.length; i < len; i++) result += String.fromCharCode(bytes[i]);
1067
+ return btoa(result);
1068
+ }
1069
+ //#endregion
1070
+ //#region src/core/binary-neutral.ts
1071
+ const MIN_NATIVE_BASE64_LENGTH = 512;
1072
+ function encodeArrayBuffer(current) {
1073
+ if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
1074
+ return encodeArrayBuffer$1(current);
1075
+ }
1076
+ function decodeArrayBuffer(source) {
1077
+ if (source.length < MIN_NATIVE_BASE64_LENGTH || typeof Buffer === "undefined") return ARRAY_BUFFER_CONSTRUCTOR(source);
1078
+ const decoded = atob(source);
1079
+ const buffer = new ArrayBuffer(decoded.length);
1080
+ Buffer.from(buffer).write(decoded, "latin1");
1081
+ return buffer;
1082
+ }
1083
+ //#endregion
1084
+ //#region src/core/plugin.ts
1085
+ let SerovalMode = /* @__PURE__ */ function(SerovalMode) {
1086
+ SerovalMode[SerovalMode["Vanilla"] = 1] = "Vanilla";
1087
+ SerovalMode[SerovalMode["Cross"] = 2] = "Cross";
1088
+ return SerovalMode;
1089
+ }({});
1090
+ function createPlugin(plugin) {
1091
+ return plugin;
1092
+ }
1093
+ function dedupePlugins(deduped, plugins) {
1094
+ for (let i = 0, len = plugins.length; i < len; i++) {
1095
+ const current = plugins[i];
1096
+ if (!deduped.has(current)) {
1097
+ deduped.add(current);
1098
+ if (current.extends) dedupePlugins(deduped, current.extends);
1099
+ }
1100
+ }
1101
+ }
1102
+ const RESOLVED_PLUGINS = /* @__PURE__ */ new WeakMap();
1103
+ function matchResolved(resolved, plugins, added) {
1104
+ for (let i = 0, len = plugins.length; i < len; i++) {
1105
+ const current = plugins[i];
1106
+ if (current === resolved[added]) {
1107
+ added++;
1108
+ if (current.extends) {
1109
+ added = matchResolved(resolved, current.extends, added);
1110
+ if (added === -1) return -1;
1111
+ }
1112
+ } else {
1113
+ const index = resolved.indexOf(current);
1114
+ if (index === -1 || index >= added) return -1;
1115
+ }
1116
+ }
1117
+ return added;
1118
+ }
1119
+ function resolvePlugins(plugins) {
1120
+ if (plugins) {
1121
+ const cached = RESOLVED_PLUGINS.get(plugins);
1122
+ if (cached && matchResolved(cached, plugins, 0) === cached.length) return cached;
1123
+ const deduped = /* @__PURE__ */ new Set();
1124
+ dedupePlugins(deduped, plugins);
1125
+ const resolved = [...deduped];
1126
+ RESOLVED_PLUGINS.set(plugins, resolved);
1127
+ return resolved;
1128
+ }
1129
+ }
1130
+ /**
1131
+ * Returns the plugins that are tested for plain objects. It is the same array
1132
+ * when no plugin sets `skipPlainObjects`.
1133
+ */
1134
+ function getPlainObjectPlugins(plugins) {
1135
+ if (plugins) {
1136
+ for (let i = 0, len = plugins.length; i < len; i++) if (plugins[i].skipPlainObjects) {
1137
+ const result = plugins.filter((plugin) => !plugin.skipPlainObjects);
1138
+ return result.length ? result : void 0;
1139
+ }
1140
+ }
1141
+ return plugins;
1142
+ }
1143
+ //#endregion
1144
+ //#region src/core/keys.ts
1145
+ const REFERENCES_KEY = "__SEROVAL_REFS__";
1146
+ const GLOBAL_CONTEXT_R = `self.\$R`;
1147
+ function getCrossReferenceHeader(id) {
1148
+ if (id == null) return `${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||[]`;
1149
+ return `(${GLOBAL_CONTEXT_R}=${GLOBAL_CONTEXT_R}||{})["${serializeString(id)}"]=[]`;
1150
+ }
1151
+ //#endregion
1152
+ //#region src/core/reference.ts
1153
+ const REFERENCE = /* @__PURE__ */ new Map();
1154
+ const INV_REFERENCE = /* @__PURE__ */ new Map();
1155
+ let installed = false;
1156
+ function getGlobalObject() {
1157
+ if (typeof globalThis !== "undefined") return globalThis;
1158
+ if (typeof window !== "undefined") return window;
1159
+ if (typeof self !== "undefined") return self;
1160
+ if (typeof global !== "undefined") return global;
1161
+ }
1162
+ function installReferenceStore() {
1163
+ if (!installed) {
1164
+ installed = true;
1165
+ const globalObject = getGlobalObject();
1166
+ if (globalObject) Object.defineProperty(globalObject, REFERENCES_KEY, {
1167
+ value: INV_REFERENCE,
1168
+ configurable: true,
1169
+ writable: false,
1170
+ enumerable: false
1171
+ });
1172
+ }
1173
+ }
1174
+ function createReference(id, value) {
1175
+ installReferenceStore();
1176
+ REFERENCE.set(value, id);
1177
+ INV_REFERENCE.set(id, value);
1178
+ return value;
1179
+ }
1180
+ function hasReference(id) {
1181
+ return INV_REFERENCE.has(id);
1182
+ }
1183
+ function getReferenceID(value) {
1184
+ return REFERENCE.get(value);
1185
+ }
1186
+ function getReference(id) {
1187
+ if (hasReference(id)) return INV_REFERENCE.get(id);
1188
+ throw new SerovalMissingReferenceForIdError(id);
1189
+ }
1190
+ //#endregion
925
1191
  //#region src/core/context/parser.ts
926
- function createBaseParserContext(mode, options) {
927
- var _options$compactArray;
1192
+ function createBaseParserContext(options) {
928
1193
  return {
929
1194
  plugins: options.plugins,
930
- mode,
1195
+ plainObjectPlugins: getPlainObjectPlugins(options.plugins),
931
1196
  marked: /* @__PURE__ */ new Set(),
932
- features: 127 ^ (options.disabledFeatures || 0),
933
- refs: options.refs || /* @__PURE__ */ new Map(),
1197
+ features: 127 ^ (options.disabledFeatures ?? 0),
1198
+ refs: options.refs ?? /* @__PURE__ */ new Map(),
934
1199
  depthLimit: options.depthLimit || 1e3,
935
- compactArrayBufferViews: (_options$compactArray = options.compactArrayBufferViews) !== null && _options$compactArray !== void 0 ? _options$compactArray : false
1200
+ compactArrayBufferViews: options.compactArrayBufferViews ?? false
936
1201
  };
937
1202
  }
938
1203
  /**
1204
+ * Returns the plugins to test for an object. Plain objects, whose prototype is
1205
+ * `Object.prototype`, skip the plugins that set `skipPlainObjects`. Checking
1206
+ * the prototype as well as `constructor` keeps instances whose prototype has
1207
+ * no own `constructor` property from skipping those plugins.
1208
+ */
1209
+ function getObjectPlugins(ctx, current, currentClass) {
1210
+ return currentClass === Object && Object.getPrototypeOf(current) === Object.prototype ? ctx.plainObjectPlugins : ctx.plugins;
1211
+ }
1212
+ /**
939
1213
  * Ensures that the value (based on an identifier) has been visited by the parser.
940
1214
  * @param ctx
941
1215
  * @param id
@@ -957,125 +1231,166 @@ function getNodeForIndexedValue(ctx, current) {
957
1231
  const registeredId = ctx.refs.get(current);
958
1232
  if (registeredId != null) {
959
1233
  markParserRef(ctx, registeredId);
960
- return {
961
- type: 1,
962
- value: createIndexedValueNode(registeredId)
963
- };
1234
+ return createIndexedValueNode(registeredId);
964
1235
  }
965
- return {
966
- type: 0,
967
- value: createIndexForValue(ctx, current)
968
- };
1236
+ return createIndexForValue(ctx, current);
969
1237
  }
970
1238
  function getReferenceNode(ctx, current) {
971
1239
  const indexed = getNodeForIndexedValue(ctx, current);
972
- if (indexed.type === 1) return indexed;
973
- if (hasReferenceID(current)) return {
974
- type: 2,
975
- value: createReferenceNode(indexed.value, current)
976
- };
977
- return indexed;
1240
+ if (typeof indexed !== "number") return indexed;
1241
+ const referenceId = getReferenceID(current);
1242
+ return referenceId === void 0 ? indexed : createReferenceNode(indexed, referenceId);
978
1243
  }
979
1244
  /**
980
1245
  * Parsing methods
981
1246
  */
982
1247
  function parseWellKnownSymbol(ctx, current) {
983
1248
  const ref = getReferenceNode(ctx, current);
984
- if (ref.type !== 0) return ref.value;
985
- if (current in INV_SYMBOL_REF) return createWKSymbolNode(ref.value, current);
1249
+ if (typeof ref !== "number") return ref;
1250
+ if (current in INV_SYMBOL_REF) return createWKSymbolNode(ref, current);
986
1251
  throw new SerovalUnsupportedTypeError(current);
987
1252
  }
988
1253
  function parseSpecialReference(ctx, ref) {
989
1254
  const result = getNodeForIndexedValue(ctx, SPECIAL_REFS[ref]);
990
- if (result.type === 1) return result.value;
991
- return createSerovalNode(26, result.value, ref, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0);
1255
+ if (typeof result !== "number") return result;
1256
+ return createSerovalNode(26, result, ref);
992
1257
  }
993
1258
  function parseIteratorFactory(ctx) {
994
1259
  const result = getNodeForIndexedValue(ctx, ITERATOR);
995
- if (result.type === 1) return result.value;
996
- return createSerovalNode(27, result.value, void 0, void 0, void 0, void 0, void 0, void 0, parseWellKnownSymbol(ctx, SYM_ITERATOR), void 0, void 0, void 0);
1260
+ if (typeof result !== "number") return result;
1261
+ return createSerovalNode(27, result, void 0, void 0, void 0, void 0, void 0, void 0, parseWellKnownSymbol(ctx, SYM_ITERATOR));
997
1262
  }
998
1263
  function parseAsyncIteratorFactory(ctx) {
999
1264
  const result = getNodeForIndexedValue(ctx, ASYNC_ITERATOR);
1000
- if (result.type === 1) return result.value;
1001
- return createSerovalNode(29, result.value, void 0, void 0, void 0, void 0, void 0, [parseSpecialReference(ctx, 1), parseWellKnownSymbol(ctx, SYM_ASYNC_ITERATOR)], void 0, void 0, void 0, void 0);
1265
+ if (typeof result !== "number") return result;
1266
+ return createSerovalNode(29, result, void 0, void 0, void 0, void 0, void 0, [parseSpecialReference(ctx, 1), parseWellKnownSymbol(ctx, SYM_ASYNC_ITERATOR)]);
1002
1267
  }
1003
- function createObjectNode(id, current, empty, record) {
1004
- return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current), void 0);
1268
+ function getTemporalType(currentClass) {
1269
+ switch (currentClass) {
1270
+ case Temporal.Instant: return 0;
1271
+ case Temporal.Duration: return 1;
1272
+ case Temporal.PlainDate: return 2;
1273
+ case Temporal.PlainDateTime: return 3;
1274
+ case Temporal.PlainMonthDay: return 4;
1275
+ case Temporal.PlainTime: return 5;
1276
+ case Temporal.PlainYearMonth: return 6;
1277
+ case Temporal.ZonedDateTime: return 7;
1278
+ default: return;
1279
+ }
1280
+ }
1281
+ function getObjectClass(current) {
1282
+ const currentClass = current.constructor;
1283
+ if (currentClass !== void 0 && typeof currentClass !== "function") {
1284
+ const proto = Object.getPrototypeOf(current);
1285
+ return proto === null ? void 0 : proto.constructor;
1286
+ }
1287
+ return currentClass;
1005
1288
  }
1006
1289
  /**
1007
- * Gets the sentinel node for a Map. Call it before parsing the entries, so
1008
- * that an outer Map declares the sentinel before any Map inside it uses it.
1290
+ * Decides how an object is parsed. Shared by the sync, stream and async
1291
+ * parsers so the class checks and feature gates live in one place.
1009
1292
  */
1010
- function parseMapSentinel(ctx) {
1011
- return parseSpecialReference(ctx, 0);
1012
- }
1013
- function createMapNode(id, sentinel, k, v) {
1014
- return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
1015
- k,
1016
- v
1017
- }, void 0, sentinel, void 0, void 0, void 0);
1018
- }
1293
+ function getObjectKind(current, currentClass, features) {
1294
+ switch (currentClass) {
1295
+ case Object: return 1;
1296
+ case void 0: return 2;
1297
+ case Date: return 3;
1298
+ case Error:
1299
+ case EvalError:
1300
+ case RangeError:
1301
+ case ReferenceError:
1302
+ case SyntaxError:
1303
+ case TypeError:
1304
+ case URIError: return 4;
1305
+ case Number:
1306
+ case Boolean:
1307
+ case String:
1308
+ case BigInt: return 6;
1309
+ case ArrayBuffer: return 7;
1310
+ case Int8Array:
1311
+ case Int16Array:
1312
+ case Int32Array:
1313
+ case Uint8Array:
1314
+ case Uint16Array:
1315
+ case Uint32Array:
1316
+ case Uint8ClampedArray:
1317
+ case Float32Array:
1318
+ case Float64Array: return 8;
1319
+ case DataView: return 10;
1320
+ case Map: return 11;
1321
+ case Set: return 12;
1322
+ }
1323
+ if (currentClass === Promise || current instanceof Promise) return 13;
1324
+ if (features & 32 && currentClass === RegExp) return 14;
1325
+ if (features & 16 && (currentClass === BigInt64Array || currentClass === BigUint64Array)) return 9;
1326
+ if (features & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return 5;
1327
+ if (features & 64 && typeof Temporal !== "undefined" && getTemporalType(currentClass) != null) return 15;
1328
+ if (current instanceof Error) return 4;
1329
+ if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return 16;
1330
+ return 0;
1331
+ }
1332
+ function createObjectNode(id, current, empty, record) {
1333
+ return createSerovalNode(empty ? 11 : 10, id, void 0, void 0, void 0, record, void 0, void 0, void 0, void 0, getObjectFlag(current));
1334
+ }
1335
+ /**
1336
+ * Gets the sentinel node for a Map. Call it before parsing the entries, so
1337
+ * that an outer Map declares the sentinel before any Map inside it uses it.
1338
+ */
1339
+ function parseMapSentinel(ctx) {
1340
+ return parseSpecialReference(ctx, 0);
1341
+ }
1342
+ function createMapNode(id, sentinel, k, v) {
1343
+ return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
1344
+ k,
1345
+ v
1346
+ }, void 0, sentinel);
1347
+ }
1019
1348
  function createPromiseConstructorNode(ctx, id, resolver) {
1020
- return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, void 0);
1349
+ return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1));
1021
1350
  }
1022
1351
  function getArrayBufferView(ctx, current) {
1023
1352
  if (!ctx.compactArrayBufferViews) return current;
1024
1353
  const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
1025
1354
  return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
1026
1355
  }
1027
- function encodeArrayBuffer(current) {
1028
- if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
1029
- const bytes = new Uint8Array(current);
1030
- if (typeof bytes.toBase64 === "function") return bytes.toBase64();
1031
- let result = "";
1032
- for (let i = 0, len = bytes.length; i < len; i++) result += String.fromCharCode(bytes[i]);
1033
- return btoa(result);
1034
- }
1035
1356
  function createArrayBufferNode(ctx, id, current) {
1036
- return createSerovalNode(19, id, encodeArrayBuffer(current), void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 5), void 0, void 0, void 0);
1357
+ return createSerovalNode(19, id, encodeArrayBuffer(current), void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 5));
1037
1358
  }
1038
1359
  //#endregion
1039
1360
  //#region src/core/context/async-parser.ts
1040
- function createAsyncParserContext(mode, options) {
1041
- return {
1042
- base: createBaseParserContext(mode, options),
1043
- child: void 0
1044
- };
1361
+ function createAsyncParserContext(options) {
1362
+ return { base: createBaseParserContext(options) };
1045
1363
  }
1046
- var AsyncParsePluginContext = class {
1047
- constructor(_p, depth) {
1048
- this._p = _p;
1049
- this.depth = depth;
1050
- }
1051
- parse(current) {
1052
- return parseAsync(this._p, this.depth, current);
1053
- }
1054
- };
1055
1364
  async function parseItems$1(ctx, depth, current) {
1056
- const nodes = [];
1057
- for (let i = 0, len = current.length; i < len; i++) if (i in current) nodes[i] = await parseAsync(ctx, depth, current[i]);
1058
- else nodes[i] = 0;
1365
+ const len = current.length;
1366
+ const nodes = new Array(len);
1367
+ for (let i = 0, node; i < len; i++) if (i in current) {
1368
+ node = parseValueAsync(ctx, depth, current[i]);
1369
+ nodes[i] = node instanceof Promise ? await node : node;
1370
+ } else nodes[i] = 0;
1059
1371
  return nodes;
1060
1372
  }
1061
1373
  async function parseArray$1(ctx, depth, id, current) {
1062
1374
  return createArrayNode(id, current, await parseItems$1(ctx, depth, current));
1063
1375
  }
1064
1376
  async function parseProperties$1(ctx, depth, properties) {
1065
- const entries = Object.entries(properties);
1066
- const keyNodes = [];
1067
- const valueNodes = [];
1068
- for (let i = 0, len = entries.length; i < len; i++) {
1069
- keyNodes.push(serializeString(entries[i][0]));
1070
- valueNodes.push(await parseAsync(ctx, depth, entries[i][1]));
1377
+ const keys = Object.keys(properties);
1378
+ const len = keys.length;
1379
+ const keyNodes = new Array(len);
1380
+ const valueNodes = new Array(len);
1381
+ for (let i = 0, key, node; i < len; i++) {
1382
+ key = keys[i];
1383
+ keyNodes[i] = serializeString(key);
1384
+ node = parseValueAsync(ctx, depth, properties[key]);
1385
+ valueNodes[i] = node instanceof Promise ? await node : node;
1071
1386
  }
1072
1387
  if (SYM_ITERATOR in properties) {
1073
1388
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
1074
- valueNodes.push(createIteratorFactoryInstanceNode(parseIteratorFactory(ctx.base), await parseAsync(ctx, depth, createSequenceFromIterable(properties))));
1389
+ valueNodes.push(createIteratorFactoryInstanceNode(28, parseIteratorFactory(ctx.base), await parseAsync(ctx, depth, createSequenceFromIterable(properties))));
1075
1390
  }
1076
1391
  if (SYM_ASYNC_ITERATOR in properties) {
1077
1392
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
1078
- valueNodes.push(createAsyncIteratorFactoryInstanceNode(parseAsyncIteratorFactory(ctx.base), await parseAsync(ctx, depth, createStreamFromAsyncIterable(properties))));
1393
+ valueNodes.push(createIteratorFactoryInstanceNode(30, parseAsyncIteratorFactory(ctx.base), await parseAsyncIterable$1(ctx, depth, properties)));
1079
1394
  }
1080
1395
  if (SYM_TO_STRING_TAG in properties) {
1081
1396
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
@@ -1096,167 +1411,183 @@ async function parsePlainObject$1(ctx, depth, id, current, empty) {
1096
1411
  async function parseBoxed$1(ctx, depth, id, current) {
1097
1412
  return createBoxedNode(id, await parseAsync(ctx, depth, current.valueOf()));
1098
1413
  }
1099
- async function parseTypedArray$1(ctx, depth, id, current) {
1100
- current = getArrayBufferView(ctx.base, current);
1101
- return createTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
1102
- }
1103
- async function parseBigIntTypedArray$1(ctx, depth, id, current) {
1104
- current = getArrayBufferView(ctx.base, current);
1105
- return createBigIntTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
1106
- }
1107
- async function parseDataView$1(ctx, depth, id, current) {
1414
+ async function parseView$1(ctx, depth, type, id, current) {
1108
1415
  current = getArrayBufferView(ctx.base, current);
1109
- return createDataViewNode(id, current, await parseAsync(ctx, depth, current.buffer));
1416
+ return createViewNode(type, id, current, await parseAsync(ctx, depth, current.buffer));
1110
1417
  }
1111
- async function parseError$1(ctx, depth, id, current) {
1418
+ async function parseError$1(ctx, depth, type, id, current) {
1112
1419
  const options = getErrorOptions(current, ctx.base.features);
1113
- return createErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
1114
- }
1115
- async function parseAggregateError$1(ctx, depth, id, current) {
1116
- const options = getErrorOptions(current, ctx.base.features);
1117
- return createAggregateErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
1420
+ return createErrorNode(type, id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
1118
1421
  }
1119
1422
  async function parseMap$1(ctx, depth, id, current) {
1120
1423
  const sentinel = parseMapSentinel(ctx.base);
1121
- const keyNodes = [];
1122
- const valueNodes = [];
1424
+ const keyNodes = new Array(current.size);
1425
+ const valueNodes = new Array(current.size);
1426
+ let node;
1427
+ let i = 0;
1123
1428
  for (const [key, value] of current.entries()) {
1124
- keyNodes.push(await parseAsync(ctx, depth, key));
1125
- valueNodes.push(await parseAsync(ctx, depth, value));
1429
+ node = parseValueAsync(ctx, depth, key);
1430
+ keyNodes[i] = node instanceof Promise ? await node : node;
1431
+ node = parseValueAsync(ctx, depth, value);
1432
+ valueNodes[i] = node instanceof Promise ? await node : node;
1433
+ i++;
1126
1434
  }
1127
1435
  return createMapNode(id, sentinel, keyNodes, valueNodes);
1128
1436
  }
1129
1437
  async function parseSet$1(ctx, depth, id, current) {
1130
- const items = [];
1131
- for (const item of current.keys()) items.push(await parseAsync(ctx, depth, item));
1438
+ const items = new Array(current.size);
1439
+ let node;
1440
+ let i = 0;
1441
+ for (const item of current.keys()) {
1442
+ node = parseValueAsync(ctx, depth, item);
1443
+ items[i++] = node instanceof Promise ? await node : node;
1444
+ }
1132
1445
  return createSetNode(id, items);
1133
1446
  }
1134
- async function parsePlugin$1(ctx, depth, id, current) {
1135
- const currentPlugins = ctx.base.plugins;
1447
+ async function parsePlugin$1(ctx, depth, id, current, currentPlugins) {
1136
1448
  if (currentPlugins) for (let i = 0, len = currentPlugins.length; i < len; i++) {
1137
1449
  const plugin = currentPlugins[i];
1138
- if (plugin.parse.async && plugin.test(current)) return createPluginNode(id, plugin.tag, await plugin.parse.async(current, new AsyncParsePluginContext(ctx, depth), { id }));
1450
+ if (plugin.parse.async && plugin.test(current)) return createPluginNode(id, plugin.tag, await plugin.parse.async(current, {
1451
+ parse: (value) => parseAsync(ctx, depth, value),
1452
+ parseStreamSource(source) {
1453
+ if (depth >= ctx.base.depthLimit) throw new SerovalDepthLimitError(ctx.base.depthLimit);
1454
+ return parseAsyncIterable$1(ctx, depth + 1, source);
1455
+ }
1456
+ }, { id }));
1139
1457
  }
1140
1458
  }
1141
1459
  async function parsePromise$1(ctx, depth, id, current) {
1142
1460
  const [status, result] = await promiseToResult(current);
1143
- return createSerovalNode(12, id, status, void 0, void 0, void 0, void 0, void 0, await parseAsync(ctx, depth, result), void 0, void 0, void 0);
1461
+ return createSerovalNode(12, id, status, void 0, void 0, void 0, void 0, void 0, await parseAsync(ctx, depth, result));
1144
1462
  }
1145
1463
  function parseStreamHandle(depth, id, current, resolve, reject) {
1146
1464
  const sequence = [];
1147
- const cleanup = current.on({
1148
- next: (value) => {
1149
- markParserRef(this.base, id);
1150
- parseAsync(this, depth, value).then((data) => {
1151
- sequence.push(createStreamNextNode(id, data));
1152
- }, (data) => {
1153
- reject(data);
1154
- cleanup();
1155
- });
1156
- },
1157
- throw: (value) => {
1158
- markParserRef(this.base, id);
1159
- parseAsync(this, depth, value).then((data) => {
1160
- sequence.push(createStreamThrowNode(id, data));
1161
- resolve(sequence);
1162
- cleanup();
1163
- }, (data) => {
1164
- reject(data);
1165
- cleanup();
1166
- });
1167
- },
1168
- return: (value) => {
1169
- markParserRef(this.base, id);
1170
- parseAsync(this, depth, value).then((data) => {
1171
- sequence.push(createStreamReturnNode(id, data));
1172
- resolve(sequence);
1173
- cleanup();
1174
- }, (data) => {
1175
- reject(data);
1176
- cleanup();
1177
- });
1465
+ let unparsed = 0;
1466
+ let ended = false;
1467
+ let settled = false;
1468
+ const fail = (error) => {
1469
+ if (!settled) {
1470
+ settled = true;
1471
+ try {
1472
+ cleanup(error);
1473
+ } catch {}
1474
+ reject(error);
1178
1475
  }
1179
- });
1476
+ };
1477
+ const handle = (type) => (value, accept) => {
1478
+ if (settled) return;
1479
+ markParserRef(this.base, id);
1480
+ const slot = sequence.push(void 0) - 1;
1481
+ unparsed++;
1482
+ if (type !== 32) ended = true;
1483
+ parseAsync(this, depth, value).then((data) => {
1484
+ if (!settled) {
1485
+ sequence[slot] = createStreamEventNode(type, id, data);
1486
+ unparsed--;
1487
+ accept?.();
1488
+ if (ended && unparsed === 0) {
1489
+ settled = true;
1490
+ try {
1491
+ cleanup();
1492
+ } catch (error) {
1493
+ reject(error);
1494
+ return;
1495
+ }
1496
+ resolve(sequence);
1497
+ }
1498
+ }
1499
+ }, fail);
1500
+ };
1501
+ const listener = {
1502
+ next: handle(32),
1503
+ throw: handle(33),
1504
+ return: handle(34)
1505
+ };
1506
+ const cleanup = isLiveStream(current) ? current.pump(listener) : current.on(listener);
1180
1507
  }
1181
1508
  async function parseStream$1(ctx, depth, id, current) {
1182
1509
  return createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), await new Promise(parseStreamHandle.bind(ctx, depth, id, current)));
1183
1510
  }
1511
+ /**
1512
+ * Collects an async iterable into a replay node, one value at a time.
1513
+ */
1514
+ async function parseAsyncIterable$1(ctx, depth, current) {
1515
+ const id = createIndexForValue(ctx.base, {});
1516
+ const reference = parseSpecialReference(ctx.base, 4);
1517
+ const iterator = current[SYM_ASYNC_ITERATOR]();
1518
+ const sequence = [];
1519
+ for (;;) {
1520
+ let result;
1521
+ try {
1522
+ result = await iterator.next();
1523
+ } catch (error) {
1524
+ markParserRef(ctx.base, id);
1525
+ sequence.push(createStreamEventNode(33, id, await parseAsync(ctx, depth, error)));
1526
+ break;
1527
+ }
1528
+ markParserRef(ctx.base, id);
1529
+ let parsed;
1530
+ try {
1531
+ parsed = await parseAsync(ctx, depth, result.value);
1532
+ } catch (error) {
1533
+ Promise.resolve().then(() => iterator.return?.()).catch(() => {});
1534
+ throw error;
1535
+ }
1536
+ sequence.push(createStreamEventNode(result.done ? 34 : 32, id, parsed));
1537
+ if (result.done) break;
1538
+ }
1539
+ return createStreamConstructorNode(id, reference, sequence);
1540
+ }
1184
1541
  async function parseSequence$1(ctx, depth, id, current) {
1185
- const nodes = [];
1186
- for (let i = 0, len = current.v.length; i < len; i++) nodes[i] = await parseAsync(ctx, depth, current.v[i]);
1542
+ const len = current.v.length;
1543
+ const nodes = new Array(len);
1544
+ for (let i = 0, node; i < len; i++) {
1545
+ node = parseValueAsync(ctx, depth, current.v[i]);
1546
+ nodes[i] = node instanceof Promise ? await node : node;
1547
+ }
1187
1548
  return createSequenceNode(id, nodes, current.t, current.d);
1188
1549
  }
1189
1550
  async function parseObjectAsync(ctx, depth, id, current) {
1190
1551
  if (Array.isArray(current)) return parseArray$1(ctx, depth, id, current);
1191
1552
  if (isStream(current)) return parseStream$1(ctx, depth, id, current);
1192
1553
  if (isSequence(current)) return parseSequence$1(ctx, depth, id, current);
1193
- let currentClass = current.constructor;
1194
- if (currentClass !== void 0 && typeof currentClass !== "function") {
1195
- const proto = Object.getPrototypeOf(current);
1196
- currentClass = proto === null ? void 0 : proto.constructor;
1197
- }
1554
+ const currentClass = getObjectClass(current);
1198
1555
  if (currentClass === OpaqueReference) return parseAsync(ctx, depth, current.replacement);
1199
- const parsed = await parsePlugin$1(ctx, depth, id, current);
1556
+ const parsed = await parsePlugin$1(ctx, depth, id, current, getObjectPlugins(ctx.base, current, currentClass));
1200
1557
  if (parsed) return parsed;
1201
- switch (currentClass) {
1202
- case Object: return parsePlainObject$1(ctx, depth, id, current, false);
1203
- case void 0: return parsePlainObject$1(ctx, depth, id, current, true);
1204
- case Date: return createDateNode(id, current);
1205
- case Error:
1206
- case EvalError:
1207
- case RangeError:
1208
- case ReferenceError:
1209
- case SyntaxError:
1210
- case TypeError:
1211
- case URIError: return parseError$1(ctx, depth, id, current);
1212
- case Number:
1213
- case Boolean:
1214
- case String:
1215
- case BigInt: return parseBoxed$1(ctx, depth, id, current);
1216
- case ArrayBuffer: return createArrayBufferNode(ctx.base, id, current);
1217
- case Int8Array:
1218
- case Int16Array:
1219
- case Int32Array:
1220
- case Uint8Array:
1221
- case Uint16Array:
1222
- case Uint32Array:
1223
- case Uint8ClampedArray:
1224
- case Float32Array:
1225
- case Float64Array: return parseTypedArray$1(ctx, depth, id, current);
1226
- case DataView: return parseDataView$1(ctx, depth, id, current);
1227
- case Map: return parseMap$1(ctx, depth, id, current);
1228
- case Set: return parseSet$1(ctx, depth, id, current);
1229
- }
1230
- if (currentClass === Promise || current instanceof Promise) return parsePromise$1(ctx, depth, id, current);
1231
- const currentFeatures = ctx.base.features;
1232
- if (currentFeatures & 32 && currentClass === RegExp) return createRegExpNode(id, current);
1233
- if (currentFeatures & 16) switch (currentClass) {
1234
- case BigInt64Array:
1235
- case BigUint64Array: return parseBigIntTypedArray$1(ctx, depth, id, current);
1236
- }
1237
- if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError$1(ctx, depth, id, current);
1238
- if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
1239
- case Temporal.Instant: return createTemporalNode(id, 0, current);
1240
- case Temporal.Duration: return createTemporalNode(id, 1, current);
1241
- case Temporal.PlainDate: return createTemporalNode(id, 2, current);
1242
- case Temporal.PlainDateTime: return createTemporalNode(id, 3, current);
1243
- case Temporal.PlainMonthDay: return createTemporalNode(id, 4, current);
1244
- case Temporal.PlainTime: return createTemporalNode(id, 5, current);
1245
- case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
1246
- case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
1247
- }
1248
- if (current instanceof Error) return parseError$1(ctx, depth, id, current);
1249
- if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject$1(ctx, depth, id, current, !!currentClass);
1250
- throw new SerovalUnsupportedTypeError(current);
1558
+ if (currentClass === Object) return parsePlainObject$1(ctx, depth, id, current, false);
1559
+ switch (getObjectKind(current, currentClass, ctx.base.features)) {
1560
+ case 2: return parsePlainObject$1(ctx, depth, id, current, true);
1561
+ case 3: return createDateNode(id, current);
1562
+ case 4: return parseError$1(ctx, depth, 13, id, current);
1563
+ case 5: return parseError$1(ctx, depth, 14, id, current);
1564
+ case 6: return parseBoxed$1(ctx, depth, id, current);
1565
+ case 7: return createArrayBufferNode(ctx.base, id, current);
1566
+ case 8: return parseView$1(ctx, depth, 15, id, current);
1567
+ case 9: return parseView$1(ctx, depth, 16, id, current);
1568
+ case 10: return parseView$1(ctx, depth, 20, id, current);
1569
+ case 11: return parseMap$1(ctx, depth, id, current);
1570
+ case 12: return parseSet$1(ctx, depth, id, current);
1571
+ case 13: return parsePromise$1(ctx, depth, id, current);
1572
+ case 14: return createRegExpNode(id, current);
1573
+ case 15: return createTemporalNode(id, getTemporalType(currentClass), current);
1574
+ case 16: return parsePlainObject$1(ctx, depth, id, current, !!currentClass);
1575
+ default: throw new SerovalUnsupportedTypeError(current);
1576
+ }
1251
1577
  }
1252
1578
  async function parseFunctionAsync(ctx, depth, current) {
1253
1579
  const ref = getReferenceNode(ctx.base, current);
1254
- if (ref.type !== 0) return ref.value;
1255
- const plugin = await parsePlugin$1(ctx, depth, ref.value, current);
1580
+ if (typeof ref !== "number") return ref;
1581
+ const plugin = await parsePlugin$1(ctx, depth, ref, current, ctx.base.plugins);
1256
1582
  if (plugin) return plugin;
1257
1583
  throw new SerovalUnsupportedTypeError(current);
1258
1584
  }
1259
- async function parseAsync(ctx, depth, current) {
1585
+ /**
1586
+ * Parses primitives and already-seen values synchronously; only objects and
1587
+ * functions come back as a Promise. Errors are thrown synchronously, which
1588
+ * an async caller turns into a rejection as before.
1589
+ */
1590
+ function parseValueAsync(ctx, depth, current) {
1260
1591
  if (depth >= ctx.base.depthLimit) throw new SerovalDepthLimitError(ctx.base.depthLimit);
1261
1592
  switch (typeof current) {
1262
1593
  case "boolean": return current ? TRUE_NODE : FALSE_NODE;
@@ -1267,7 +1598,7 @@ async function parseAsync(ctx, depth, current) {
1267
1598
  case "object":
1268
1599
  if (current) {
1269
1600
  const ref = getReferenceNode(ctx.base, current);
1270
- return ref.type === 0 ? await parseObjectAsync(ctx, depth + 1, ref.value, current) : ref.value;
1601
+ return typeof ref === "number" ? parseObjectAsync(ctx, depth + 1, ref, current) : ref;
1271
1602
  }
1272
1603
  return NULL_NODE;
1273
1604
  case "symbol": return parseWellKnownSymbol(ctx.base, current);
@@ -1275,6 +1606,9 @@ async function parseAsync(ctx, depth, current) {
1275
1606
  default: throw new SerovalUnsupportedTypeError(current);
1276
1607
  }
1277
1608
  }
1609
+ async function parseAsync(ctx, depth, current) {
1610
+ return await parseValueAsync(ctx, depth, current);
1611
+ }
1278
1612
  async function parseTopAsync(ctx, current) {
1279
1613
  try {
1280
1614
  return await parseAsync(ctx, 0, current);
@@ -1283,32 +1617,6 @@ async function parseTopAsync(ctx, current) {
1283
1617
  }
1284
1618
  }
1285
1619
  //#endregion
1286
- //#region src/core/plugin.ts
1287
- let SerovalMode = /* @__PURE__ */ function(SerovalMode) {
1288
- SerovalMode[SerovalMode["Vanilla"] = 1] = "Vanilla";
1289
- SerovalMode[SerovalMode["Cross"] = 2] = "Cross";
1290
- return SerovalMode;
1291
- }({});
1292
- function createPlugin(plugin) {
1293
- return plugin;
1294
- }
1295
- function dedupePlugins(deduped, plugins) {
1296
- for (let i = 0, len = plugins.length; i < len; i++) {
1297
- const current = plugins[i];
1298
- if (!deduped.has(current)) {
1299
- deduped.add(current);
1300
- if (current.extends) dedupePlugins(deduped, current.extends);
1301
- }
1302
- }
1303
- }
1304
- function resolvePlugins(plugins) {
1305
- if (plugins) {
1306
- const deduped = /* @__PURE__ */ new Set();
1307
- dedupePlugins(deduped, plugins);
1308
- return [...deduped];
1309
- }
1310
- }
1311
- //#endregion
1312
1620
  //#region src/core/utils/valid-properties.ts
1313
1621
  function isValidKey(key) {
1314
1622
  switch (key) {
@@ -1334,7 +1642,6 @@ function isValidSymbol(symbol) {
1334
1642
  //#endregion
1335
1643
  //#region src/core/context/deserializer.ts
1336
1644
  const DEFAULT_MAX_BASE64_LENGTH = 1e6;
1337
- const MIN_NATIVE_BASE64_LENGTH = 512;
1338
1645
  const MAX_BIGINT_LENGTH = 1e4;
1339
1646
  const MAX_REGEXP_SOURCE_LENGTH = 2e4;
1340
1647
  function applyObjectFlag(obj, flag) {
@@ -1346,68 +1653,48 @@ function applyObjectFlag(obj, flag) {
1346
1653
  }
1347
1654
  }
1348
1655
  const DEFAULT_DEPTH_LIMIT = 1e3;
1349
- function createBaseDeserializerContext(mode, options) {
1350
- var _options$maxBase64Len, _options$features;
1351
- const maxBase64Length = (_options$maxBase64Len = options.maxBase64Length) !== null && _options$maxBase64Len !== void 0 ? _options$maxBase64Len : DEFAULT_MAX_BASE64_LENGTH;
1656
+ function createBaseDeserializerContext(options) {
1657
+ const maxBase64Length = options.maxBase64Length ?? DEFAULT_MAX_BASE64_LENGTH;
1352
1658
  if (!Number.isSafeInteger(maxBase64Length) || maxBase64Length < 0) throw new RangeError("maxBase64Length must be a non-negative safe integer");
1353
- const refs = options.refs || /* @__PURE__ */ new Map();
1659
+ const refs = options.refs ?? /* @__PURE__ */ new Map();
1354
1660
  if (!("types" in refs)) Object.assign(refs, { types: /* @__PURE__ */ new Map() });
1355
1661
  return {
1356
- mode,
1357
1662
  plugins: options.plugins,
1358
1663
  refs,
1359
- features: (_options$features = options.features) !== null && _options$features !== void 0 ? _options$features : 127 ^ (options.disabledFeatures || 0),
1664
+ features: options.features ?? 127 ^ (options.disabledFeatures ?? 0),
1360
1665
  depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT,
1361
1666
  maxBase64Length
1362
1667
  };
1363
1668
  }
1364
1669
  function createVanillaDeserializerContext(options) {
1365
1670
  return {
1366
- mode: 1,
1367
- base: createBaseDeserializerContext(1, options),
1368
- child: void 0,
1369
- state: { marked: new Set(options.markedRefs) }
1671
+ base: createBaseDeserializerContext(options),
1672
+ marked: new Set(options.markedRefs)
1370
1673
  };
1371
1674
  }
1372
1675
  function createCrossDeserializerContext(options) {
1373
1676
  return {
1374
- mode: 2,
1375
- base: createBaseDeserializerContext(2, options),
1376
- child: void 0
1677
+ base: createBaseDeserializerContext(options),
1678
+ marked: void 0
1377
1679
  };
1378
1680
  }
1379
- var DeserializePluginContext = class {
1380
- constructor(_p, depth) {
1381
- this._p = _p;
1382
- this.depth = depth;
1383
- }
1384
- deserialize(node) {
1385
- return deserialize$1(this._p, this.depth, node);
1386
- }
1387
- };
1388
1681
  function guardIndexedValue(ctx, id) {
1389
- if (id < 0 || !Number.isFinite(id) || !Number.isInteger(id)) throw new SerovalMalformedNodeError({
1682
+ const node = {
1390
1683
  t: 4,
1391
1684
  i: id
1392
- });
1393
- if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1685
+ };
1686
+ if (id < 0 || !Number.isInteger(id)) throw new SerovalMalformedNodeError(node);
1687
+ if (ctx.refs.has(id)) throw new SerovalConflictedNodeIdError(node);
1394
1688
  }
1395
1689
  function isThennable(value) {
1396
1690
  return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1397
1691
  }
1398
- function assignIndexedValueVanilla(ctx, id, value) {
1399
- guardIndexedValue(ctx.base, id);
1400
- if (ctx.state.marked.has(id)) ctx.base.refs.set(id, value);
1401
- return value;
1402
- }
1403
- function assignIndexedValueCross(ctx, id, value) {
1692
+ function assignIndexedValue$1(ctx, id, value) {
1404
1693
  guardIndexedValue(ctx.base, id);
1405
- ctx.base.refs.set(id, value);
1694
+ const marked = ctx.marked;
1695
+ if (!marked || marked.has(id)) ctx.base.refs.set(id, value);
1406
1696
  return value;
1407
1697
  }
1408
- function assignIndexedValue$1(ctx, id, value) {
1409
- return ctx.mode === 1 ? assignIndexedValueVanilla(ctx, id, value) : assignIndexedValueCross(ctx, id, value);
1410
- }
1411
1698
  function deserializeKnownValue(node, record, key) {
1412
1699
  if (Object.hasOwn(record, key)) return record[key];
1413
1700
  throw new SerovalMalformedNodeError(node);
@@ -1464,7 +1751,8 @@ function deserializeProperties(ctx, depth, node, result) {
1464
1751
  const keys = node.k;
1465
1752
  validateNodeList(node, keys);
1466
1753
  validateNodeList(node, node.v);
1467
- if (keys.length > 0) for (let i = 0, vals = node.v, len = keys.length; i < len; i++) assignProperty(ctx, depth, result, keys[i], vals[i]);
1754
+ const len = keys.length;
1755
+ if (len > 0) for (let i = 0, vals = node.v; i < len; i++) assignProperty(ctx, depth, result, keys[i], vals[i]);
1468
1756
  return result;
1469
1757
  }
1470
1758
  function deserializeObject(ctx, depth, node) {
@@ -1478,35 +1766,8 @@ function deserializeDate(ctx, node) {
1478
1766
  }
1479
1767
  function deserializeTemporal(ctx, node) {
1480
1768
  if (!(ctx.base.features & 64)) throw new SerovalUnsupportedNodeError(node);
1481
- let value;
1482
- switch (node.c) {
1483
- case 0:
1484
- value = Temporal.Instant.from(node.s);
1485
- break;
1486
- case 1:
1487
- value = Temporal.Duration.from(node.s);
1488
- break;
1489
- case 2:
1490
- value = Temporal.PlainDate.from(node.s);
1491
- break;
1492
- case 3:
1493
- value = Temporal.PlainDateTime.from(node.s);
1494
- break;
1495
- case 4:
1496
- value = Temporal.PlainMonthDay.from(node.s);
1497
- break;
1498
- case 5:
1499
- value = Temporal.PlainTime.from(node.s);
1500
- break;
1501
- case 6:
1502
- value = Temporal.PlainYearMonth.from(node.s);
1503
- break;
1504
- case 7:
1505
- value = Temporal.ZonedDateTime.from(node.s);
1506
- break;
1507
- default: throw new SerovalMalformedNodeError(node);
1508
- }
1509
- return assignIndexedValue$1(ctx, node.i, value);
1769
+ const construct = Temporal[deserializeKnownValue(node, TEMPORAL_TYPE_NAME, node.c)];
1770
+ return assignIndexedValue$1(ctx, node.i, construct.from(node.s));
1510
1771
  }
1511
1772
  function deserializeRegExp(ctx, node) {
1512
1773
  if (ctx.base.features & 32) {
@@ -1532,32 +1793,15 @@ function deserializeMap(ctx, depth, node) {
1532
1793
  function deserializeArrayBuffer(ctx, node) {
1533
1794
  if (typeof node.s !== "string") throw new SerovalMalformedNodeError(node);
1534
1795
  if (node.s.length > ctx.base.maxBase64Length) throw new RangeError("ArrayBuffer exceeds maxBase64Length (" + ctx.base.maxBase64Length + ")");
1535
- const source = deserializeString(node.s);
1536
- let buffer;
1537
- if (source.length < MIN_NATIVE_BASE64_LENGTH || typeof Buffer === "undefined") buffer = ARRAY_BUFFER_CONSTRUCTOR(source);
1538
- else {
1539
- const decoded = atob(source);
1540
- buffer = new ArrayBuffer(decoded.length);
1541
- Buffer.from(buffer).write(decoded, "latin1");
1542
- }
1796
+ const buffer = decodeArrayBuffer(deserializeString(node.s));
1543
1797
  return assignIndexedValue$1(ctx, node.i, buffer);
1544
1798
  }
1545
- function deserializeTypedArray(ctx, depth, node) {
1546
- var _node$b;
1547
- const construct = getTypedArrayConstructor(node.c);
1548
- const source = deserialize$1(ctx, depth, node.f);
1549
- if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1550
- const offset = (_node$b = node.b) !== null && _node$b !== void 0 ? _node$b : 0;
1551
- if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1552
- return assignIndexedValue$1(ctx, node.i, new construct(source, offset, node.l));
1553
- }
1554
- function deserializeDataView(ctx, depth, node) {
1555
- var _node$b2;
1799
+ function deserializeView(ctx, depth, node, construct) {
1556
1800
  const source = deserialize$1(ctx, depth, node.f);
1557
1801
  if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1558
- const offset = (_node$b2 = node.b) !== null && _node$b2 !== void 0 ? _node$b2 : 0;
1802
+ const offset = node.b ?? 0;
1559
1803
  if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1560
- return assignIndexedValue$1(ctx, node.i, new DataView(source, offset, node.l));
1804
+ return assignIndexedValue$1(ctx, node.i, construct ? new construct(source, offset, node.l) : new DataView(source, offset, node.l));
1561
1805
  }
1562
1806
  function deserializeDictionary(ctx, depth, node, result) {
1563
1807
  if (node.p) {
@@ -1591,7 +1835,7 @@ function deserializePlugin(ctx, depth, node) {
1591
1835
  const tag = deserializeString(node.c);
1592
1836
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
1593
1837
  const plugin = currentPlugins[i];
1594
- if (plugin.tag === tag) return assignIndexedValue$1(ctx, node.i, plugin.deserialize(node.s, new DeserializePluginContext(ctx, depth), { id: node.i }));
1838
+ if (plugin.tag === tag) return assignIndexedValue$1(ctx, node.i, plugin.deserialize(node.s, { deserialize: (current) => deserialize$1(ctx, depth, current) }, { id: node.i }));
1595
1839
  }
1596
1840
  }
1597
1841
  throw new SerovalMissingPluginError(node.c);
@@ -1599,6 +1843,7 @@ function deserializePlugin(ctx, depth, node) {
1599
1843
  function deserializePromiseConstructor(ctx, node) {
1600
1844
  const value = assignIndexedValue$1(ctx, node.i, assignIndexedValue$1(ctx, node.s, PROMISE_CONSTRUCTOR()).p);
1601
1845
  assignNodeType(ctx, node.s, 22);
1846
+ ctx.base.pending?.add(node.s);
1602
1847
  return value;
1603
1848
  }
1604
1849
  function deserializePromiseFulfill(ctx, depth, node) {
@@ -1609,6 +1854,7 @@ function deserializePromiseFulfill(ctx, depth, node) {
1609
1854
  if (isThennable(deserialized)) throw new SerovalMalformedNodeError(node.a[1]);
1610
1855
  if (node.t === 23) deferred.s(deserialized);
1611
1856
  else deferred.f(deserialized);
1857
+ ctx.base.pending?.delete(node.i);
1612
1858
  return;
1613
1859
  }
1614
1860
  throw new SerovalMissingInstanceError("Promise");
@@ -1626,37 +1872,21 @@ function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1626
1872
  return streamToAsyncIterable(source);
1627
1873
  }
1628
1874
  function deserializeStreamConstructor(ctx, depth, node) {
1629
- const result = assignIndexedValue$1(ctx, node.i, createStream());
1875
+ const result = assignIndexedValue$1(ctx, node.i, new Stream(node.l === 1 ? 1 : void 0));
1630
1876
  assignNodeType(ctx, node.i, 31);
1877
+ ctx.base.pending?.add(node.i);
1631
1878
  const items = node.a;
1632
1879
  validateNodeList(node, items);
1633
1880
  const len = items.length;
1634
1881
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1635
1882
  return result;
1636
1883
  }
1637
- function deserializeStreamNext(ctx, depth, node) {
1884
+ function deserializeStreamCall(ctx, depth, node, method) {
1638
1885
  const deferred = ctx.base.refs.get(node.i);
1639
1886
  if (deferred) {
1640
1887
  validateNodeType(ctx, node, node.i, 31);
1641
- deferred.next(deserialize$1(ctx, depth, node.f));
1642
- return;
1643
- }
1644
- throw new SerovalMissingInstanceError("Stream");
1645
- }
1646
- function deserializeStreamThrow(ctx, depth, node) {
1647
- const deferred = ctx.base.refs.get(node.i);
1648
- if (deferred) {
1649
- validateNodeType(ctx, node, node.i, 31);
1650
- deferred.throw(deserialize$1(ctx, depth, node.f));
1651
- return;
1652
- }
1653
- throw new SerovalMissingInstanceError("Stream");
1654
- }
1655
- function deserializeStreamReturn(ctx, depth, node) {
1656
- const deferred = ctx.base.refs.get(node.i);
1657
- if (deferred) {
1658
- validateNodeType(ctx, node, node.i, 31);
1659
- deferred.return(deserialize$1(ctx, depth, node.f));
1888
+ deferred[method](deserialize$1(ctx, depth, node.f));
1889
+ if (method !== "next") ctx.base.pending?.delete(node.i);
1660
1890
  return;
1661
1891
  }
1662
1892
  throw new SerovalMissingInstanceError("Stream");
@@ -1675,6 +1905,7 @@ function deserializeSequence(ctx, depth, node) {
1675
1905
  const size = node.a.length;
1676
1906
  if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1677
1907
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1908
+ assignNodeType(ctx, node.i, 35);
1678
1909
  for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1679
1910
  return result;
1680
1911
  }
@@ -1699,8 +1930,8 @@ function deserialize$1(ctx, depth, node) {
1699
1930
  case 8: return deserializeMap(ctx, depth, node);
1700
1931
  case 19: return deserializeArrayBuffer(ctx, node);
1701
1932
  case 16:
1702
- case 15: return deserializeTypedArray(ctx, depth, node);
1703
- case 20: return deserializeDataView(ctx, depth, node);
1933
+ case 15: return deserializeView(ctx, depth, node, getTypedArrayConstructor(node.c));
1934
+ case 20: return deserializeView(ctx, depth, node);
1704
1935
  case 14: return deserializeAggregateError(ctx, depth, node);
1705
1936
  case 13: return deserializeError(ctx, depth, node);
1706
1937
  case 12: return deserializePromise(ctx, depth, node);
@@ -1713,9 +1944,9 @@ function deserialize$1(ctx, depth, node) {
1713
1944
  case 28: return deserializeIteratorFactoryInstance(ctx, depth, node);
1714
1945
  case 30: return deserializeAsyncIteratorFactoryInstance(ctx, depth, node);
1715
1946
  case 31: return deserializeStreamConstructor(ctx, depth, node);
1716
- case 32: return deserializeStreamNext(ctx, depth, node);
1717
- case 33: return deserializeStreamThrow(ctx, depth, node);
1718
- case 34: return deserializeStreamReturn(ctx, depth, node);
1947
+ case 32: return deserializeStreamCall(ctx, depth, node, "next");
1948
+ case 33: return deserializeStreamCall(ctx, depth, node, "throw");
1949
+ case 34: return deserializeStreamCall(ctx, depth, node, "return");
1719
1950
  case 27: return deserializeIteratorFactory(ctx, depth, node);
1720
1951
  case 29: return deserializeAsyncIteratorFactory(ctx, depth, node);
1721
1952
  case 35: return deserializeSequence(ctx, depth, node);
@@ -1730,11 +1961,31 @@ function deserializeTop(ctx, node) {
1730
1961
  throw new SerovalDeserializationError(error);
1731
1962
  }
1732
1963
  }
1964
+ /**
1965
+ * Rejects every pending promise and throws into every open stream tracked
1966
+ * by `ctx.base.pending`, then drops the bookkeeping so the context no longer
1967
+ * accepts deferred values. Does nothing once the bookkeeping is gone.
1968
+ */
1969
+ function abortDeferred(ctx, reason) {
1970
+ const pending = ctx.base.pending;
1971
+ if (pending) {
1972
+ ctx.base.pending = void 0;
1973
+ const refs = ctx.base.refs;
1974
+ const errors = [];
1975
+ for (const id of pending) try {
1976
+ const value = refs.get(id);
1977
+ if (refs.types.get(id) === 22) value.f(reason);
1978
+ else value.throw(reason);
1979
+ } catch (error) {
1980
+ errors.push(error);
1981
+ }
1982
+ if (errors.length) throw errors[0];
1983
+ }
1984
+ }
1733
1985
  //#endregion
1734
1986
  //#region src/core/function-string.ts
1735
1987
  const RETURN = () => T;
1736
- const SERIALIZED_RETURN = /* @__PURE__ */ RETURN.toString();
1737
- const IS_MODERN = /* @__PURE__ */ /=>/.test(SERIALIZED_RETURN);
1988
+ const IS_MODERN = /* @__PURE__ */ (/* @__PURE__ */ RETURN.toString()).includes("=>");
1738
1989
  function createFunction(parameters, body) {
1739
1990
  if (IS_MODERN) return (parameters.length === 1 ? parameters[0] : "(" + parameters.join(",") + ")") + "=>" + (body.startsWith("{") ? "(" + body + ")" : body);
1740
1991
  return "function(" + parameters.join(",") + "){return " + body + "}";
@@ -1762,10 +2013,13 @@ function getIdentifier(index) {
1762
2013
  }
1763
2014
  //#endregion
1764
2015
  //#region src/core/utils/is-valid-identifier.ts
1765
- const IDENTIFIER_CHECK = /^[$A-Z_][0-9A-Z_$]*$/i;
1766
2016
  function isValidIdentifier(name) {
1767
- const char = name[0];
1768
- return (char === "$" || char === "_" || char >= "A" && char <= "Z" || char >= "a" && char <= "z") && IDENTIFIER_CHECK.test(name);
2017
+ const len = name.length;
2018
+ for (let i = 0; i < len; i++) {
2019
+ const code = name.charCodeAt(i);
2020
+ if (!(code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 && i > 0 || code === 95 || code === 36)) return false;
2021
+ }
2022
+ return len > 0;
1769
2023
  }
1770
2024
  //#endregion
1771
2025
  //#region src/core/context/serializer.ts
@@ -1779,58 +2033,31 @@ function getAssignmentExpression(assignment) {
1779
2033
  }
1780
2034
  }
1781
2035
  const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
1782
- function mergeAssignments(assignments) {
1783
- const newAssignments = [];
1784
- let current = assignments[0];
2036
+ function resolveAssignments(assignments) {
2037
+ if (!assignments.length) return void 0;
2038
+ let previous = assignments[0];
2039
+ let expression = getAssignmentExpression(previous);
2040
+ let result = "";
1785
2041
  let chainLength = 1;
1786
- for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
1787
- item = assignments[i];
2042
+ for (let index = 1, length = assignments.length; index < length; index++) {
2043
+ const assignment = assignments[index];
1788
2044
  if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
1789
- newAssignments.push(current);
1790
- current = item;
2045
+ result += expression + ",";
2046
+ expression = getAssignmentExpression(assignment);
1791
2047
  chainLength = 0;
1792
- } else if (item.t === 0 && prev.t === 0 && item.v === prev.v) current = {
1793
- t: 0,
1794
- s: item.s,
1795
- k: void 0,
1796
- v: getAssignmentExpression(current)
1797
- };
1798
- else if (item.t === 2 && prev.t === 2 && item.s === prev.s) current = {
1799
- t: 2,
1800
- s: getAssignmentExpression(current),
1801
- k: item.k,
1802
- v: item.v
1803
- };
1804
- else if (item.t === 1 && prev.t === 1 && item.s === prev.s) current = {
1805
- t: 1,
1806
- s: getAssignmentExpression(current),
1807
- k: void 0,
1808
- v: item.v
1809
- };
1810
- else if (item.t === 3 && prev.t === 2 && item.s === prev.s) current = {
1811
- t: 3,
1812
- s: getAssignmentExpression(current),
1813
- k: item.k,
1814
- v: void 0
1815
- };
2048
+ } else if (assignment.t === 0 && previous.t === 0 && assignment.v === previous.v) expression = assignment.s + "=" + expression;
2049
+ else if (assignment.t === 2 && previous.t === 2 && assignment.s === previous.s) expression += ".set(" + assignment.k + "," + assignment.v + ")";
2050
+ else if (assignment.t === 1 && previous.t === 1 && assignment.s === previous.s) expression += ".add(" + assignment.v + ")";
2051
+ else if (assignment.t === 3 && previous.t === 2 && assignment.s === previous.s) expression += ".delete(" + assignment.k + ")";
1816
2052
  else {
1817
- newAssignments.push(current);
1818
- current = item;
2053
+ result += expression + ",";
2054
+ expression = getAssignmentExpression(assignment);
1819
2055
  chainLength = 0;
1820
2056
  }
1821
2057
  chainLength++;
1822
- prev = item;
1823
- }
1824
- newAssignments.push(current);
1825
- return newAssignments;
1826
- }
1827
- function resolveAssignments(assignments) {
1828
- if (assignments.length) {
1829
- let result = "";
1830
- const merged = mergeAssignments(assignments);
1831
- for (let i = 0, len = merged.length; i < len; i++) result += getAssignmentExpression(merged[i]) + ",";
1832
- return result;
2058
+ previous = assignment;
1833
2059
  }
2060
+ return result + expression + ",";
1834
2061
  }
1835
2062
  const NULL_CONSTRUCTOR = "Object.create(null)";
1836
2063
  const SET_CONSTRUCTOR = "new Set";
@@ -1848,42 +2075,34 @@ function createBaseSerializerContext(mode, options) {
1848
2075
  mode,
1849
2076
  plugins: options.plugins,
1850
2077
  features: options.features,
1851
- marked: new Set(options.markedRefs),
2078
+ marked: Array.isArray(options.markedRefs) ? new Set(options.markedRefs) : options.markedRefs,
1852
2079
  stack: [],
1853
2080
  flags: [],
1854
- assignments: []
2081
+ assignments: [],
2082
+ assignAll: mode === 2 && !options.assignSharedRefsOnly
1855
2083
  };
1856
2084
  }
1857
2085
  function createVanillaSerializerState() {
1858
2086
  return {
1859
2087
  valid: /* @__PURE__ */ new Map(),
1860
- vars: []
2088
+ vars: [],
2089
+ sentinels: /* @__PURE__ */ new Set()
1861
2090
  };
1862
2091
  }
1863
2092
  function createVanillaSerializerContext(options) {
1864
2093
  return {
1865
2094
  mode: 1,
1866
2095
  base: createBaseSerializerContext(1, options),
1867
- state: createVanillaSerializerState(),
1868
- child: void 0
2096
+ state: createVanillaSerializerState()
1869
2097
  };
1870
2098
  }
1871
2099
  function createCrossSerializerContext(options) {
1872
2100
  return {
1873
2101
  mode: 2,
1874
2102
  base: createBaseSerializerContext(2, options),
1875
- state: options,
1876
- child: void 0
2103
+ state: options
1877
2104
  };
1878
2105
  }
1879
- var SerializePluginContext = class {
1880
- constructor(_p) {
1881
- this._p = _p;
1882
- }
1883
- serialize(node) {
1884
- return serialize$1(this._p, node);
1885
- }
1886
- };
1887
2106
  /**
1888
2107
  * Creates the reference param (identifier) from the given reference ID
1889
2108
  * Calling this function means the value has been referenced somewhere
@@ -1991,7 +2210,7 @@ function createArrayAssign(ctx, ref, index, value) {
1991
2210
  createAssignment(ctx.base, getRefParam(ctx, ref) + "[" + index + "]", value);
1992
2211
  }
1993
2212
  function createObjectAssign(ctx, ref, key, value) {
1994
- if (!isValidKey(key)) {
2213
+ if (key === "__proto__") {
1995
2214
  ctx.base.assignments.push({
1996
2215
  t: 4,
1997
2216
  s: getRefParam(ctx, ref),
@@ -2009,6 +2228,15 @@ function createSequenceAssign(ctx, ref, index, value) {
2009
2228
  * Checks if the value is in the stack. Stack here is a reference
2010
2229
  * structure to know if a object is to be accessed in a TDZ.
2011
2230
  */
2231
+ function getKeyKind(key) {
2232
+ const first = key.charCodeAt(0);
2233
+ if (first >= 48 && first <= 57) {
2234
+ const check = Number(key);
2235
+ return check >= 0 && check.toString() === key ? 2 : 0;
2236
+ }
2237
+ if (key === "Infinity") return 2;
2238
+ return isValidIdentifier(key) ? 1 : 0;
2239
+ }
2012
2240
  function isIndexedValueInStack(ctx, node) {
2013
2241
  return node.t === 4 && ctx.stack.includes(node.i);
2014
2242
  }
@@ -2035,7 +2263,7 @@ function hasMarkedNode(ctx, node) {
2035
2263
  * it.
2036
2264
  */
2037
2265
  function assignIndexedValue(ctx, index, value) {
2038
- if (ctx.mode === 1 && !isSerializerRefMarked(ctx.base, index)) return value;
2266
+ if (!ctx.base.assignAll && !isSerializerRefMarked(ctx.base, index)) return value;
2039
2267
  /**
2040
2268
  * In cross-reference, we have to assume that
2041
2269
  * every reference are going to be referenced
@@ -2043,12 +2271,13 @@ function assignIndexedValue(ctx, index, value) {
2043
2271
  * all of it into the reference array.
2044
2272
  *
2045
2273
  * otherwise in vanilla, we only do this if it
2046
- * is actually referenced
2274
+ * is actually referenced. `assignSharedRefsOnly` gives cross-reference
2275
+ * output the vanilla behavior.
2047
2276
  */
2048
2277
  return getRefParam(ctx, index) + "=" + value;
2049
2278
  }
2050
2279
  function serializeReference(node) {
2051
- return "__SEROVAL_REFS__.get(\"" + node.s + "\")";
2280
+ return REFERENCES_KEY + ".get(\"" + node.s + "\")";
2052
2281
  }
2053
2282
  function serializeArrayItem(ctx, id, item, index) {
2054
2283
  if (item) {
@@ -2082,16 +2311,15 @@ function serializeArray(ctx, node) {
2082
2311
  }
2083
2312
  function serializeProperty(ctx, source, key, val) {
2084
2313
  if (typeof key === "string") {
2085
- const check = Number(key);
2086
- const isIdentifier = check >= 0 && check.toString() === key || isValidIdentifier(key);
2314
+ const kind = getKeyKind(key);
2087
2315
  if (isIndexedValueInStack(ctx.base, val)) {
2088
2316
  const refParam = getRefParam(ctx, val.i);
2089
2317
  markSerializerRef(ctx.base, source.i);
2090
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, refParam);
2091
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", refParam);
2318
+ if (kind === 1) createObjectAssign(ctx, source.i, key, refParam);
2319
+ else createArrayAssign(ctx, source.i, kind === 2 ? key : "\"" + key + "\"", refParam);
2092
2320
  return "";
2093
2321
  }
2094
- if (isValidKey(key)) return (isIdentifier ? key : "\"" + key + "\"") + ":" + serialize$1(ctx, val);
2322
+ if (key !== "__proto__") return (kind === 0 ? "\"" + key + "\"" : key) + ":" + serialize$1(ctx, val);
2095
2323
  return "[\"" + key + "\"]:" + serialize$1(ctx, val);
2096
2324
  }
2097
2325
  return "[" + serialize$1(ctx, key) + "]:" + serialize$1(ctx, val);
@@ -2103,7 +2331,7 @@ function serializeProperties(ctx, source, record) {
2103
2331
  const values = record.v;
2104
2332
  ctx.base.stack.push(source.i);
2105
2333
  let result = serializeProperty(ctx, source, keys[0], values[0]);
2106
- for (let i = 1, item = result; i < len; i++) {
2334
+ for (let i = 1, item; i < len; i++) {
2107
2335
  item = serializeProperty(ctx, source, keys[i], values[i]);
2108
2336
  result += (item && result && ",") + item;
2109
2337
  }
@@ -2124,18 +2352,14 @@ function serializeWithObjectAssign(ctx, source, value, serialized) {
2124
2352
  function serializeStringKeyAssignment(ctx, source, mainAssignments, key, value) {
2125
2353
  const base = ctx.base;
2126
2354
  const serialized = serialize$1(ctx, value);
2127
- const check = Number(key);
2128
- const isIdentifier = check >= 0 && check.toString() === key || isValidIdentifier(key);
2129
- if (isIndexedValueInStack(base, value)) {
2130
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
2131
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
2132
- } else {
2133
- const parentAssignment = base.assignments;
2134
- base.assignments = mainAssignments;
2135
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
2136
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
2137
- base.assignments = parentAssignment;
2138
- }
2355
+ const parentAssignment = base.assignments;
2356
+ if (!isIndexedValueInStack(base, value)) base.assignments = mainAssignments;
2357
+ createKeyAssign(ctx, source.i, getKeyKind(key), key, serialized);
2358
+ base.assignments = parentAssignment;
2359
+ }
2360
+ function createKeyAssign(ctx, ref, kind, key, value) {
2361
+ if (kind === 1) createObjectAssign(ctx, ref, key, value);
2362
+ else createArrayAssign(ctx, ref, kind === 2 ? key : "\"" + key + "\"", value);
2139
2363
  }
2140
2364
  function serializeAssignment(ctx, source, mainAssignments, key, value) {
2141
2365
  if (typeof key === "string") serializeStringKeyAssignment(ctx, source, mainAssignments, key, value);
@@ -2166,7 +2390,7 @@ function serializeAssignments(ctx, source, node) {
2166
2390
  function serializeDictionary(ctx, node, init) {
2167
2391
  if (node.p) {
2168
2392
  const base = ctx.base;
2169
- if (base.features & 8) init = serializeWithObjectAssign(ctx, node, node.p, init);
2393
+ if (base.features & 8 && !node.p.k.includes("__proto__")) init = serializeWithObjectAssign(ctx, node, node.p, init);
2170
2394
  else {
2171
2395
  markSerializerRef(base, node.i);
2172
2396
  const assignments = serializeAssignments(ctx, node, node.p);
@@ -2182,18 +2406,8 @@ function serializeNullConstructor(ctx, node) {
2182
2406
  function serializeDate(node) {
2183
2407
  return "new Date(\"" + node.s + "\")";
2184
2408
  }
2185
- const TEMPORAL_CONSTRUCTOR = {
2186
- [0]: "Temporal.Instant",
2187
- [1]: "Temporal.Duration",
2188
- [2]: "Temporal.PlainDate",
2189
- [3]: "Temporal.PlainDateTime",
2190
- [4]: "Temporal.PlainMonthDay",
2191
- [5]: "Temporal.PlainTime",
2192
- [6]: "Temporal.PlainYearMonth",
2193
- [7]: "Temporal.ZonedDateTime"
2194
- };
2195
2409
  function serializeTemporal(ctx, node) {
2196
- if (ctx.base.features & 64) return TEMPORAL_CONSTRUCTOR[node.c] + ".from(\"" + node.s + "\")";
2410
+ if (ctx.base.features & 64) return "Temporal." + TEMPORAL_TYPE_NAME[node.c] + ".from(\"" + node.s + "\")";
2197
2411
  throw new SerovalUnsupportedNodeError(node);
2198
2412
  }
2199
2413
  function serializeRegExp(ctx, node) {
@@ -2220,7 +2434,7 @@ function serializeSet(ctx, node) {
2220
2434
  if (size > 0) {
2221
2435
  ctx.base.stack.push(id);
2222
2436
  let result = serializeSetItem(ctx, id, items[0]);
2223
- for (let i = 1, item = result; i < size; i++) {
2437
+ for (let i = 1, item; i < size; i++) {
2224
2438
  item = serializeSetItem(ctx, id, items[i]);
2225
2439
  result += (item && result && ",") + item;
2226
2440
  }
@@ -2229,7 +2443,7 @@ function serializeSet(ctx, node) {
2229
2443
  }
2230
2444
  return serialized;
2231
2445
  }
2232
- function serializeMapEntry(ctx, id, key, val, sentinel) {
2446
+ function serializeMapEntry(ctx, id, key, val, getSentinel) {
2233
2447
  const base = ctx.base;
2234
2448
  if (isIndexedValueInStack(base, key)) {
2235
2449
  const keyRef = getRefParam(ctx, key.i);
@@ -2240,6 +2454,7 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
2240
2454
  }
2241
2455
  if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
2242
2456
  markSerializerRef(base, val.i);
2457
+ const sentinel = getSentinel();
2243
2458
  const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
2244
2459
  createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
2245
2460
  createDeleteAssignment(ctx, id, sentinel);
@@ -2256,6 +2471,7 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
2256
2471
  markSerializerRef(base, id);
2257
2472
  if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
2258
2473
  markSerializerRef(base, key.i);
2474
+ const sentinel = getSentinel();
2259
2475
  const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
2260
2476
  createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
2261
2477
  createDeleteAssignment(ctx, id, sentinel);
@@ -2275,20 +2491,27 @@ function serializeMap(ctx, node) {
2275
2491
  const size = keys.length;
2276
2492
  const id = node.i;
2277
2493
  const sentinel = node.f;
2278
- const sentinelId = getRefParam(ctx, sentinel.i);
2494
+ let sentinelRef;
2495
+ const getSentinel = () => {
2496
+ if (sentinelRef == null) {
2497
+ sentinelRef = getRefParam(ctx, sentinel.i);
2498
+ if (ctx.mode === 1) ctx.state.sentinels.add(ctx.state.valid.get(sentinel.i));
2499
+ }
2500
+ return sentinelRef;
2501
+ };
2279
2502
  const base = ctx.base;
2280
2503
  if (size > 0) {
2281
2504
  const vals = node.e.v;
2282
2505
  base.stack.push(id);
2283
- let result = serializeMapEntry(ctx, id, keys[0], vals[0], sentinelId);
2284
- for (let i = 1, item = result; i < size; i++) {
2285
- item = serializeMapEntry(ctx, id, keys[i], vals[i], sentinelId);
2506
+ let result = serializeMapEntry(ctx, id, keys[0], vals[0], getSentinel);
2507
+ for (let i = 1, item; i < size; i++) {
2508
+ item = serializeMapEntry(ctx, id, keys[i], vals[i], getSentinel);
2286
2509
  result += (item && result && ",") + item;
2287
2510
  }
2288
2511
  base.stack.pop();
2289
2512
  if (result) serialized += "([" + result + "])";
2290
2513
  }
2291
- if (sentinel.t === 26) {
2514
+ if (ctx.mode === 2 && sentinel.t === 26) {
2292
2515
  markSerializerRef(base, sentinel.i);
2293
2516
  serialized = "(" + serialize$1(ctx, sentinel) + "," + serialized + ")";
2294
2517
  }
@@ -2297,11 +2520,8 @@ function serializeMap(ctx, node) {
2297
2520
  function serializeArrayBuffer(ctx, node) {
2298
2521
  return getConstructor(ctx, node.f) + "(\"" + node.s + "\")";
2299
2522
  }
2300
- function serializeTypedArray(ctx, node) {
2301
- return "new " + node.c + "(" + serialize$1(ctx, node.f) + "," + node.b + "," + node.l + ")";
2302
- }
2303
- function serializeDataView(ctx, node) {
2304
- return "new DataView(" + serialize$1(ctx, node.f) + "," + node.b + "," + node.l + ")";
2523
+ function serializeView(ctx, node) {
2524
+ return "new " + (node.t === 20 ? "DataView" : node.c) + "(" + serialize$1(ctx, node.f) + "," + node.b + "," + node.l + ")";
2305
2525
  }
2306
2526
  function serializeAggregateError(ctx, node) {
2307
2527
  const id = node.i;
@@ -2341,11 +2561,7 @@ function serializePromiseConstructor(ctx, node) {
2341
2561
  if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2342
2562
  return "(" + assignIndexedValue(ctx, node.s, getConstructor(ctx, node.f) + "()") + ").p";
2343
2563
  }
2344
- function serializePromiseResolve(ctx, node) {
2345
- if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2346
- return getConstructor(ctx, node.a[0]) + "(" + getRefParam(ctx, node.i) + "," + serialize$1(ctx, node.a[1]) + ")";
2347
- }
2348
- function serializePromiseReject(ctx, node) {
2564
+ function serializePromiseResult(ctx, node) {
2349
2565
  if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2350
2566
  return getConstructor(ctx, node.a[0]) + "(" + getRefParam(ctx, node.i) + "," + serialize$1(ctx, node.a[1]) + ")";
2351
2567
  }
@@ -2353,10 +2569,7 @@ function serializePlugin(ctx, node) {
2353
2569
  const currentPlugins = ctx.base.plugins;
2354
2570
  if (currentPlugins) for (let i = 0, len = currentPlugins.length; i < len; i++) {
2355
2571
  const plugin = currentPlugins[i];
2356
- if (plugin.tag === node.c) {
2357
- if (ctx.child == null) ctx.child = new SerializePluginContext(ctx);
2358
- return plugin.serialize(node.s, ctx.child, { id: node.i });
2359
- }
2572
+ if (plugin.tag === node.c) return plugin.serialize(node.s, { serialize: (current) => serialize$1(ctx, current) }, { id: node.i });
2360
2573
  }
2361
2574
  throw new SerovalMissingPluginError(node.c);
2362
2575
  }
@@ -2393,11 +2606,8 @@ function serializeAsyncIteratorFactory(ctx, node) {
2393
2606
  if (result) return result + iterator + ")";
2394
2607
  return iterator;
2395
2608
  }
2396
- function serializeAsyncIteratorFactoryInstance(ctx, node) {
2397
- return getConstructor(ctx, node.a[0]) + "(" + serialize$1(ctx, node.a[1]) + ")";
2398
- }
2399
2609
  function serializeStreamConstructor(ctx, node) {
2400
- const result = assignIndexedValue(ctx, node.i, getConstructor(ctx, node.f) + "()");
2610
+ const result = assignIndexedValue(ctx, node.i, getConstructor(ctx, node.f) + (node.l === 1 ? "(1)" : "()"));
2401
2611
  const len = node.a.length;
2402
2612
  if (len) {
2403
2613
  let values = serialize$1(ctx, node.a[0]);
@@ -2406,14 +2616,8 @@ function serializeStreamConstructor(ctx, node) {
2406
2616
  }
2407
2617
  return result;
2408
2618
  }
2409
- function serializeStreamNext(ctx, node) {
2410
- return getRefParam(ctx, node.i) + ".next(" + serialize$1(ctx, node.f) + ")";
2411
- }
2412
- function serializeStreamThrow(ctx, node) {
2413
- return getRefParam(ctx, node.i) + ".throw(" + serialize$1(ctx, node.f) + ")";
2414
- }
2415
- function serializeStreamReturn(ctx, node) {
2416
- return getRefParam(ctx, node.i) + ".return(" + serialize$1(ctx, node.f) + ")";
2619
+ function serializeStreamCall(ctx, node, method) {
2620
+ return getRefParam(ctx, node.i) + "." + method + "(" + serialize$1(ctx, node.f) + ")";
2417
2621
  }
2418
2622
  function serializeSequenceItem(ctx, id, index, item) {
2419
2623
  const base = ctx.base;
@@ -2431,7 +2635,7 @@ function serializeSequence(ctx, node) {
2431
2635
  if (size > 0) {
2432
2636
  ctx.base.stack.push(id);
2433
2637
  let result = serializeSequenceItem(ctx, id, 0, items[0]);
2434
- for (let i = 1, item = result; i < size; i++) {
2638
+ for (let i = 1, item; i < size; i++) {
2435
2639
  item = serializeSequenceItem(ctx, id, i, items[i]);
2436
2640
  result += (item && result && ",") + item;
2437
2641
  }
@@ -2453,8 +2657,8 @@ function serializeAssignable(ctx, node) {
2453
2657
  case 8: return serializeMap(ctx, node);
2454
2658
  case 19: return serializeArrayBuffer(ctx, node);
2455
2659
  case 16:
2456
- case 15: return serializeTypedArray(ctx, node);
2457
- case 20: return serializeDataView(ctx, node);
2660
+ case 15:
2661
+ case 20: return serializeView(ctx, node);
2458
2662
  case 14: return serializeAggregateError(ctx, node);
2459
2663
  case 13: return serializeError(ctx, node);
2460
2664
  case 12: return serializePromise(ctx, node);
@@ -2474,20 +2678,20 @@ function serialize$1(ctx, node) {
2474
2678
  case 1: return "\"" + node.s + "\"";
2475
2679
  case 3: return node.s + "n";
2476
2680
  case 4: return getRefParam(ctx, node.i);
2477
- case 23: return serializePromiseResolve(ctx, node);
2478
- case 24: return serializePromiseReject(ctx, node);
2681
+ case 23:
2682
+ case 24: return serializePromiseResult(ctx, node);
2479
2683
  case 27: return serializeIteratorFactory(ctx, node);
2480
- case 28: return serializeIteratorFactoryInstance(ctx, node);
2684
+ case 28:
2685
+ case 30: return serializeIteratorFactoryInstance(ctx, node);
2481
2686
  case 29: return serializeAsyncIteratorFactory(ctx, node);
2482
- case 30: return serializeAsyncIteratorFactoryInstance(ctx, node);
2483
2687
  case 31: return serializeStreamConstructor(ctx, node);
2484
- case 32: return serializeStreamNext(ctx, node);
2485
- case 33: return serializeStreamThrow(ctx, node);
2486
- case 34: return serializeStreamReturn(ctx, node);
2688
+ case 32: return serializeStreamCall(ctx, node, "next");
2689
+ case 33: return serializeStreamCall(ctx, node, "throw");
2690
+ case 34: return serializeStreamCall(ctx, node, "return");
2487
2691
  default: return assignIndexedValue(ctx, node.i, serializeAssignable(ctx, node));
2488
2692
  }
2489
2693
  }
2490
- function serializeTopVanilla(ctx, tree) {
2694
+ function serializeVanilla(ctx, tree) {
2491
2695
  const result = serialize$1(ctx, tree);
2492
2696
  if (tree.i != null && ctx.state.vars.length) {
2493
2697
  const patches = resolvePatches(ctx.base);
@@ -2498,12 +2702,18 @@ function serializeTopVanilla(ctx, tree) {
2498
2702
  if (!result.startsWith(index + "=")) body = index + "=" + body;
2499
2703
  body = "(" + body + ")";
2500
2704
  }
2705
+ const sentinels = ctx.state.sentinels;
2706
+ if (sentinels.size) {
2707
+ let declarations = "";
2708
+ for (const index of sentinels) declarations += ctx.state.vars[index] + "=[],";
2709
+ body = "(" + declarations + body + ")";
2710
+ }
2501
2711
  return "(" + createFunction(ctx.state.vars, body) + ")()";
2502
2712
  }
2503
2713
  if (tree.t === 10) return "(" + result + ")";
2504
2714
  return result;
2505
2715
  }
2506
- function serializeTopCross(ctx, tree) {
2716
+ function serializeCross(ctx, tree) {
2507
2717
  const result = serialize$1(ctx, tree);
2508
2718
  const id = tree.i;
2509
2719
  if (id == null) return result;
@@ -2511,7 +2721,11 @@ function serializeTopCross(ctx, tree) {
2511
2721
  const ref = getRefParam(ctx, id);
2512
2722
  const scopeId = ctx.state.scopeId;
2513
2723
  const params = scopeId == null ? "" : "$R";
2514
- const body = patches ? "(" + result + "," + patches + ref + ")" : result;
2724
+ let body = result;
2725
+ if (patches) {
2726
+ if (!ctx.base.assignAll && !result.startsWith(ref + "=")) body = ref + "=" + result;
2727
+ body = "(" + body + "," + patches + ref + ")";
2728
+ }
2515
2729
  if (params === "") {
2516
2730
  if (tree.t === 10 && !patches) return "(" + body + ")";
2517
2731
  return body;
@@ -2519,76 +2733,35 @@ function serializeTopCross(ctx, tree) {
2519
2733
  const args = scopeId == null ? "()" : "($R[\"" + serializeString(scopeId) + "\"])";
2520
2734
  return "(" + createFunction([params], body) + ")" + args;
2521
2735
  }
2522
- //#endregion
2523
- //#region src/core/context/sync-parser.ts
2524
- function createSyncParserContext(mode, options) {
2525
- return {
2526
- type: 1,
2527
- base: createBaseParserContext(mode, options),
2528
- child: void 0
2529
- };
2736
+ function wrapSerializationError(error) {
2737
+ return error instanceof SerovalSerializationError ? error : new SerovalSerializationError(error);
2530
2738
  }
2531
- var SyncParsePluginContext = class {
2532
- constructor(_p, depth) {
2533
- this._p = _p;
2534
- this.depth = depth;
2535
- }
2536
- parse(current) {
2537
- return parseSOS(this._p, this.depth, current);
2538
- }
2539
- };
2540
- var StreamParsePluginContext = class {
2541
- constructor(_p, depth) {
2542
- this._p = _p;
2543
- this.depth = depth;
2544
- }
2545
- parse(current) {
2546
- return parseSOS(this._p, this.depth, current);
2547
- }
2548
- parseWithError(current) {
2549
- return parseWithError(this._p, this.depth, current);
2550
- }
2551
- isAlive() {
2552
- return this._p.state.alive;
2553
- }
2554
- pushPendingState() {
2555
- pushPendingState(this._p);
2556
- }
2557
- popPendingState() {
2558
- popPendingState(this._p);
2559
- }
2560
- onParse(node) {
2561
- onParse(this._p, node);
2562
- }
2563
- onError(error) {
2564
- onError(this._p, error);
2739
+ function serializeTopVanilla(ctx, tree) {
2740
+ try {
2741
+ return serializeVanilla(ctx, tree);
2742
+ } catch (error) {
2743
+ throw wrapSerializationError(error);
2565
2744
  }
2566
- addCleanup(callback) {
2567
- this._p.state.cleanups.push(callback);
2745
+ }
2746
+ function serializeTopCross(ctx, tree) {
2747
+ try {
2748
+ return serializeCross(ctx, tree);
2749
+ } catch (error) {
2750
+ throw wrapSerializationError(error);
2568
2751
  }
2569
- };
2570
- function createStreamParserState(options) {
2571
- return {
2572
- alive: true,
2573
- pending: 0,
2574
- initial: true,
2575
- buffer: [],
2576
- onParse: options.onParse,
2577
- onError: options.onError,
2578
- onDone: options.onDone,
2579
- cleanups: []
2580
- };
2581
2752
  }
2582
- function createStreamParserContext(options) {
2753
+ //#endregion
2754
+ //#region src/core/context/sync-parser.ts
2755
+ function createSyncParserContext(options) {
2583
2756
  return {
2584
- type: 2,
2585
- base: createBaseParserContext(2, options),
2586
- state: createStreamParserState(options)
2757
+ type: 1,
2758
+ base: createBaseParserContext(options)
2587
2759
  };
2588
2760
  }
2589
2761
  function parseItems(ctx, depth, current) {
2590
- const nodes = [];
2591
- for (let i = 0, len = current.length; i < len; i++) if (i in current) nodes[i] = parseSOS(ctx, depth, current[i]);
2762
+ const len = current.length;
2763
+ const nodes = new Array(len);
2764
+ for (let i = 0; i < len; i++) if (i in current) nodes[i] = parseSOS(ctx, depth, current[i]);
2592
2765
  else nodes[i] = 0;
2593
2766
  return nodes;
2594
2767
  }
@@ -2596,20 +2769,22 @@ function parseArray(ctx, depth, id, current) {
2596
2769
  return createArrayNode(id, current, parseItems(ctx, depth, current));
2597
2770
  }
2598
2771
  function parseProperties(ctx, depth, properties) {
2599
- const entries = Object.entries(properties);
2600
- const keyNodes = [];
2601
- const valueNodes = [];
2602
- for (let i = 0, len = entries.length; i < len; i++) {
2603
- keyNodes.push(serializeString(entries[i][0]));
2604
- valueNodes.push(parseSOS(ctx, depth, entries[i][1]));
2772
+ const keys = Object.keys(properties);
2773
+ const len = keys.length;
2774
+ const keyNodes = new Array(len);
2775
+ const valueNodes = new Array(len);
2776
+ for (let i = 0, key; i < len; i++) {
2777
+ key = keys[i];
2778
+ keyNodes[i] = serializeString(key);
2779
+ valueNodes[i] = parseSOS(ctx, depth, properties[key]);
2605
2780
  }
2606
2781
  if (SYM_ITERATOR in properties) {
2607
2782
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
2608
- valueNodes.push(createIteratorFactoryInstanceNode(parseIteratorFactory(ctx.base), parseSOS(ctx, depth, createSequenceFromIterable(properties))));
2783
+ valueNodes.push(createIteratorFactoryInstanceNode(28, parseIteratorFactory(ctx.base), parseSOS(ctx, depth, createSequenceFromIterable(properties))));
2609
2784
  }
2610
2785
  if (SYM_ASYNC_ITERATOR in properties) {
2611
2786
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
2612
- valueNodes.push(createAsyncIteratorFactoryInstanceNode(parseAsyncIteratorFactory(ctx.base), parseSOS(ctx, depth, ctx.type === 1 ? createStream() : createStreamFromAsyncIterable(properties, ctx.state.cleanups))));
2787
+ valueNodes.push(createIteratorFactoryInstanceNode(30, parseAsyncIteratorFactory(ctx.base), parseAsyncIterable(ctx, depth, properties)));
2613
2788
  }
2614
2789
  if (SYM_TO_STRING_TAG in properties) {
2615
2790
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
@@ -2624,188 +2799,111 @@ function parseProperties(ctx, depth, properties) {
2624
2799
  v: valueNodes
2625
2800
  };
2626
2801
  }
2802
+ function parseAsyncIterable(ctx, depth, current) {
2803
+ const id = createIndexForValue(ctx.base, {});
2804
+ const result = createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), []);
2805
+ if (ctx.type === 2) ctx.state.iterable(ctx, depth, id, current);
2806
+ return result;
2807
+ }
2627
2808
  function parsePlainObject(ctx, depth, id, current, empty) {
2628
2809
  return createObjectNode(id, current, empty, parseProperties(ctx, depth, current));
2629
2810
  }
2630
2811
  function parseBoxed(ctx, depth, id, current) {
2631
2812
  return createBoxedNode(id, parseSOS(ctx, depth, current.valueOf()));
2632
2813
  }
2633
- function parseTypedArray(ctx, depth, id, current) {
2814
+ function parseView(ctx, depth, type, id, current) {
2634
2815
  current = getArrayBufferView(ctx.base, current);
2635
- return createTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2816
+ return createViewNode(type, id, current, parseSOS(ctx, depth, current.buffer));
2636
2817
  }
2637
- function parseBigIntTypedArray(ctx, depth, id, current) {
2638
- current = getArrayBufferView(ctx.base, current);
2639
- return createBigIntTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2640
- }
2641
- function parseDataView(ctx, depth, id, current) {
2642
- current = getArrayBufferView(ctx.base, current);
2643
- return createDataViewNode(id, current, parseSOS(ctx, depth, current.buffer));
2644
- }
2645
- function parseError(ctx, depth, id, current) {
2818
+ function parseError(ctx, depth, type, id, current) {
2646
2819
  const options = getErrorOptions(current, ctx.base.features);
2647
- return createErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
2648
- }
2649
- function parseAggregateError(ctx, depth, id, current) {
2650
- const options = getErrorOptions(current, ctx.base.features);
2651
- return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
2820
+ return createErrorNode(type, id, current, options ? parseProperties(ctx, depth, options) : void 0);
2652
2821
  }
2653
2822
  function parseMap(ctx, depth, id, current) {
2654
2823
  const sentinel = parseMapSentinel(ctx.base);
2655
- const keyNodes = [];
2656
- const valueNodes = [];
2824
+ const keyNodes = new Array(current.size);
2825
+ const valueNodes = new Array(current.size);
2826
+ let i = 0;
2657
2827
  for (const [key, value] of current.entries()) {
2658
- keyNodes.push(parseSOS(ctx, depth, key));
2659
- valueNodes.push(parseSOS(ctx, depth, value));
2828
+ keyNodes[i] = parseSOS(ctx, depth, key);
2829
+ valueNodes[i] = parseSOS(ctx, depth, value);
2830
+ i++;
2660
2831
  }
2661
2832
  return createMapNode(id, sentinel, keyNodes, valueNodes);
2662
2833
  }
2663
2834
  function parseSet(ctx, depth, id, current) {
2664
- const items = [];
2665
- for (const item of current.keys()) items.push(parseSOS(ctx, depth, item));
2835
+ const items = new Array(current.size);
2836
+ let i = 0;
2837
+ for (const item of current.keys()) items[i++] = parseSOS(ctx, depth, item);
2666
2838
  return createSetNode(id, items);
2667
2839
  }
2668
2840
  function parseStream(ctx, depth, id, current) {
2669
2841
  const result = createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), []);
2670
- if (ctx.type === 1) return result;
2671
- pushPendingState(ctx);
2672
- current.on({
2673
- next: (value) => {
2674
- if (ctx.state.alive) {
2675
- const parsed = parseWithError(ctx, depth, value);
2676
- if (parsed) onParse(ctx, createStreamNextNode(id, parsed));
2677
- }
2678
- },
2679
- throw: (value) => {
2680
- if (ctx.state.alive) {
2681
- const parsed = parseWithError(ctx, depth, value);
2682
- if (parsed) onParse(ctx, createStreamThrowNode(id, parsed));
2683
- }
2684
- popPendingState(ctx);
2685
- },
2686
- return: (value) => {
2687
- if (ctx.state.alive) {
2688
- const parsed = parseWithError(ctx, depth, value);
2689
- if (parsed) onParse(ctx, createStreamReturnNode(id, parsed));
2690
- }
2691
- popPendingState(ctx);
2692
- }
2693
- });
2842
+ if (ctx.type === 2) ctx.state.stream(ctx, depth, id, current);
2694
2843
  return result;
2695
2844
  }
2696
- function handlePromiseSuccess(id, depth, data) {
2697
- if (this.state.alive) {
2698
- const parsed = parseWithError(this, depth, data);
2699
- if (parsed) onParse(this, createSerovalNode(23, id, void 0, void 0, void 0, void 0, void 0, [parseSpecialReference(this.base, 2), parsed], void 0, void 0, void 0, void 0));
2700
- popPendingState(this);
2701
- }
2702
- }
2703
- function handlePromiseFailure(id, depth, data) {
2704
- if (this.state.alive) {
2705
- const parsed = parseWithError(this, depth, data);
2706
- if (parsed) onParse(this, createSerovalNode(24, id, void 0, void 0, void 0, void 0, void 0, [parseSpecialReference(this.base, 3), parsed], void 0, void 0, void 0, void 0));
2707
- }
2708
- popPendingState(this);
2845
+ function parseLiveStream(ctx, depth, id, current) {
2846
+ const stream = ctx.type === 2;
2847
+ const result = createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), [], stream ? 1 : void 0);
2848
+ if (stream) ctx.state.live(ctx, depth, id, current);
2849
+ return result;
2709
2850
  }
2710
2851
  function parsePromise(ctx, depth, id, current) {
2852
+ if (ctx.type !== 2) throw new SerovalUnsupportedTypeError(current);
2711
2853
  const resolver = createIndexForValue(ctx.base, {});
2712
- if (ctx.type === 2) {
2713
- pushPendingState(ctx);
2714
- current.then(handlePromiseSuccess.bind(ctx, resolver, depth), handlePromiseFailure.bind(ctx, resolver, depth));
2715
- }
2854
+ ctx.state.promise(ctx, resolver, depth, current);
2716
2855
  return createPromiseConstructorNode(ctx.base, id, resolver);
2717
2856
  }
2718
2857
  function parsePluginSync(ctx, depth, id, current, currentPlugins) {
2719
2858
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
2720
2859
  const plugin = currentPlugins[i];
2721
- if (plugin.parse.sync && plugin.test(current)) return createPluginNode(id, plugin.tag, plugin.parse.sync(current, new SyncParsePluginContext(ctx, depth), { id }));
2860
+ if (plugin.parse.sync && plugin.test(current)) return createPluginNode(id, plugin.tag, plugin.parse.sync(current, { parse: (value) => parseSOS(ctx, depth, value) }, { id }));
2722
2861
  }
2723
2862
  }
2724
- function parsePluginStream(ctx, depth, id, current, currentPlugins) {
2725
- for (let i = 0, len = currentPlugins.length; i < len; i++) {
2726
- const plugin = currentPlugins[i];
2727
- if (plugin.parse.stream && plugin.test(current)) return createPluginNode(id, plugin.tag, plugin.parse.stream(current, new StreamParsePluginContext(ctx, depth), { id }));
2728
- }
2729
- }
2730
- function parsePlugin(ctx, depth, id, current) {
2731
- const currentPlugins = ctx.base.plugins;
2732
- if (currentPlugins) return ctx.type === 1 ? parsePluginSync(ctx, depth, id, current, currentPlugins) : parsePluginStream(ctx, depth, id, current, currentPlugins);
2863
+ function parsePlugin(ctx, depth, id, current, currentPlugins) {
2864
+ if (currentPlugins) return ctx.type === 1 ? parsePluginSync(ctx, depth, id, current, currentPlugins) : ctx.state.plugin(ctx, depth, id, current, currentPlugins);
2733
2865
  }
2734
2866
  function parseSequence(ctx, depth, id, current) {
2735
- const nodes = [];
2736
- for (let i = 0, len = current.v.length; i < len; i++) nodes[i] = parseSOS(ctx, depth, current.v[i]);
2867
+ const len = current.v.length;
2868
+ const nodes = new Array(len);
2869
+ for (let i = 0; i < len; i++) nodes[i] = parseSOS(ctx, depth, current.v[i]);
2737
2870
  return createSequenceNode(id, nodes, current.t, current.d);
2738
2871
  }
2739
2872
  function parseObjectPhase2(ctx, depth, id, current, currentClass) {
2740
- switch (currentClass) {
2741
- case Object: return parsePlainObject(ctx, depth, id, current, false);
2742
- case void 0: return parsePlainObject(ctx, depth, id, current, true);
2743
- case Date: return createDateNode(id, current);
2744
- case Error:
2745
- case EvalError:
2746
- case RangeError:
2747
- case ReferenceError:
2748
- case SyntaxError:
2749
- case TypeError:
2750
- case URIError: return parseError(ctx, depth, id, current);
2751
- case Number:
2752
- case Boolean:
2753
- case String:
2754
- case BigInt: return parseBoxed(ctx, depth, id, current);
2755
- case ArrayBuffer: return createArrayBufferNode(ctx.base, id, current);
2756
- case Int8Array:
2757
- case Int16Array:
2758
- case Int32Array:
2759
- case Uint8Array:
2760
- case Uint16Array:
2761
- case Uint32Array:
2762
- case Uint8ClampedArray:
2763
- case Float32Array:
2764
- case Float64Array: return parseTypedArray(ctx, depth, id, current);
2765
- case DataView: return parseDataView(ctx, depth, id, current);
2766
- case Map: return parseMap(ctx, depth, id, current);
2767
- case Set: return parseSet(ctx, depth, id, current);
2768
- }
2769
- if (currentClass === Promise || current instanceof Promise) return parsePromise(ctx, depth, id, current);
2770
- const currentFeatures = ctx.base.features;
2771
- if (currentFeatures & 32 && currentClass === RegExp) return createRegExpNode(id, current);
2772
- if (currentFeatures & 16) switch (currentClass) {
2773
- case BigInt64Array:
2774
- case BigUint64Array: return parseBigIntTypedArray(ctx, depth, id, current);
2775
- }
2776
- if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError(ctx, depth, id, current);
2777
- if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
2778
- case Temporal.Instant: return createTemporalNode(id, 0, current);
2779
- case Temporal.Duration: return createTemporalNode(id, 1, current);
2780
- case Temporal.PlainDate: return createTemporalNode(id, 2, current);
2781
- case Temporal.PlainDateTime: return createTemporalNode(id, 3, current);
2782
- case Temporal.PlainMonthDay: return createTemporalNode(id, 4, current);
2783
- case Temporal.PlainTime: return createTemporalNode(id, 5, current);
2784
- case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
2785
- case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
2786
- }
2787
- if (current instanceof Error) return parseError(ctx, depth, id, current);
2788
- if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject(ctx, depth, id, current, !!currentClass);
2789
- throw new SerovalUnsupportedTypeError(current);
2873
+ if (currentClass === Object) return parsePlainObject(ctx, depth, id, current, false);
2874
+ switch (getObjectKind(current, currentClass, ctx.base.features)) {
2875
+ case 2: return parsePlainObject(ctx, depth, id, current, true);
2876
+ case 3: return createDateNode(id, current);
2877
+ case 4: return parseError(ctx, depth, 13, id, current);
2878
+ case 5: return parseError(ctx, depth, 14, id, current);
2879
+ case 6: return parseBoxed(ctx, depth, id, current);
2880
+ case 7: return createArrayBufferNode(ctx.base, id, current);
2881
+ case 8: return parseView(ctx, depth, 15, id, current);
2882
+ case 9: return parseView(ctx, depth, 16, id, current);
2883
+ case 10: return parseView(ctx, depth, 20, id, current);
2884
+ case 11: return parseMap(ctx, depth, id, current);
2885
+ case 12: return parseSet(ctx, depth, id, current);
2886
+ case 13: return parsePromise(ctx, depth, id, current);
2887
+ case 14: return createRegExpNode(id, current);
2888
+ case 15: return createTemporalNode(id, getTemporalType(currentClass), current);
2889
+ case 16: return parsePlainObject(ctx, depth, id, current, !!currentClass);
2890
+ default: throw new SerovalUnsupportedTypeError(current);
2891
+ }
2790
2892
  }
2791
2893
  function parseObject(ctx, depth, id, current) {
2792
2894
  if (Array.isArray(current)) return parseArray(ctx, depth, id, current);
2793
- if (isStream(current)) return parseStream(ctx, depth, id, current);
2895
+ if (isStream(current)) return isLiveStream(current) ? parseLiveStream(ctx, depth, id, current) : parseStream(ctx, depth, id, current);
2794
2896
  if (isSequence(current)) return parseSequence(ctx, depth, id, current);
2795
- let currentClass = current.constructor;
2796
- if (currentClass !== void 0 && typeof currentClass !== "function") {
2797
- const proto = Object.getPrototypeOf(current);
2798
- currentClass = proto === null ? void 0 : proto.constructor;
2799
- }
2897
+ const currentClass = getObjectClass(current);
2800
2898
  if (currentClass === OpaqueReference) return parseSOS(ctx, depth, current.replacement);
2801
- const parsed = parsePlugin(ctx, depth, id, current);
2899
+ const parsed = parsePlugin(ctx, depth, id, current, getObjectPlugins(ctx.base, current, currentClass));
2802
2900
  if (parsed) return parsed;
2803
2901
  return parseObjectPhase2(ctx, depth, id, current, currentClass);
2804
2902
  }
2805
2903
  function parseFunction(ctx, depth, current) {
2806
2904
  const ref = getReferenceNode(ctx.base, current);
2807
- if (ref.type !== 0) return ref.value;
2808
- const plugin = parsePlugin(ctx, depth, ref.value, current);
2905
+ if (typeof ref !== "number") return ref;
2906
+ const plugin = parsePlugin(ctx, depth, ref, current, ctx.base.plugins);
2809
2907
  if (plugin) return plugin;
2810
2908
  throw new SerovalUnsupportedTypeError(current);
2811
2909
  }
@@ -2820,7 +2918,7 @@ function parseSOS(ctx, depth, current) {
2820
2918
  case "object":
2821
2919
  if (current) {
2822
2920
  const ref = getReferenceNode(ctx.base, current);
2823
- return ref.type === 0 ? parseObject(ctx, depth + 1, ref.value, current) : ref.value;
2921
+ return typeof ref === "number" ? parseObject(ctx, depth + 1, ref, current) : ref;
2824
2922
  }
2825
2923
  return NULL_NODE;
2826
2924
  case "symbol": return parseWellKnownSymbol(ctx.base, current);
@@ -2835,63 +2933,431 @@ function parseTop(ctx, current) {
2835
2933
  throw error instanceof SerovalParserError ? error : new SerovalParserError(error);
2836
2934
  }
2837
2935
  }
2838
- function onParse(ctx, node) {
2839
- if (ctx.state.initial) ctx.state.buffer.push(node);
2840
- else onParseInternal(ctx, node, false);
2936
+ //#endregion
2937
+ //#region src/core/context/stream-parser.ts
2938
+ /**
2939
+ * Streaming parse mode. Everything here is reached through the function
2940
+ * fields of the stream parser state, which only `createStreamParserContext`
2941
+ * sets, so synchronous consumers (`serialize`, `toJSON`) never bundle it.
2942
+ */
2943
+ function createStreamParsePluginContext(ctx, depth) {
2944
+ const state = ctx.state;
2945
+ function parse(current) {
2946
+ state.parsing++;
2947
+ try {
2948
+ return parseSOS(ctx, depth, current);
2949
+ } finally {
2950
+ state.parsing--;
2951
+ if (!state.alive) releaseParserValues(ctx);
2952
+ }
2953
+ }
2954
+ return {
2955
+ parse,
2956
+ parseStreamSource(current) {
2957
+ state.parsing++;
2958
+ try {
2959
+ if (depth >= ctx.base.depthLimit) throw new SerovalDepthLimitError(ctx.base.depthLimit);
2960
+ const id = createIndexForValue(ctx.base, {});
2961
+ const node = createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), [], 1);
2962
+ iterateAsync(ctx, depth + 1, id, current, true);
2963
+ return node;
2964
+ } finally {
2965
+ state.parsing--;
2966
+ if (!state.alive) releaseParserValues(ctx);
2967
+ }
2968
+ },
2969
+ parseWithError(current) {
2970
+ try {
2971
+ return parse(current);
2972
+ } catch (error) {
2973
+ stopStreamParse(ctx, 1, error);
2974
+ return;
2975
+ }
2976
+ },
2977
+ isAlive: () => state.alive,
2978
+ pushPendingState: () => {
2979
+ pushPendingState(ctx);
2980
+ },
2981
+ popPendingState: () => {
2982
+ popPendingState(ctx);
2983
+ },
2984
+ onParse(node) {
2985
+ if (state.alive) {
2986
+ state.queue.push({
2987
+ node,
2988
+ initial: false,
2989
+ accept: void 0
2990
+ });
2991
+ drainOutput(ctx);
2992
+ }
2993
+ },
2994
+ onError(error) {
2995
+ stopStreamParse(ctx, 1, error);
2996
+ },
2997
+ addCleanup(callback) {
2998
+ addCleanup(ctx, callback);
2999
+ }
3000
+ };
3001
+ }
3002
+ function getStreamParsePluginContext(ctx, depth) {
3003
+ const contexts = ctx.state.pluginContexts;
3004
+ return contexts[depth] ?? (contexts[depth] = createStreamParsePluginContext(ctx, depth));
3005
+ }
3006
+ function addCleanup(ctx, callback) {
3007
+ if (ctx.state.alive) ctx.state.cleanups.push(callback);
3008
+ else callback();
2841
3009
  }
2842
- function onError(ctx, error) {
2843
- if (ctx.state.onError) ctx.state.onError(error);
2844
- else throw error instanceof SerovalParserError ? error : new SerovalParserError(error);
3010
+ function parsePluginStream(ctx, depth, id, current, currentPlugins) {
3011
+ for (let i = 0, len = currentPlugins.length; i < len; i++) {
3012
+ const plugin = currentPlugins[i];
3013
+ if (plugin.parse.stream && plugin.test(current)) return createPluginNode(id, plugin.tag, plugin.parse.stream(current, getStreamParsePluginContext(ctx, depth), { id }));
3014
+ }
2845
3015
  }
2846
- function onDone(ctx) {
2847
- if (ctx.state.onDone) ctx.state.onDone();
2848
- for (let i = 0, len = ctx.state.cleanups.length; i < len; i++) ctx.state.cleanups[i]();
3016
+ /**
3017
+ * One listener shape serves both `Stream.on` (no accept) and
3018
+ * `LiveStream.pump` (accept tied to record acceptance). Handlers return the
3019
+ * parse error so the pump can stop the source.
3020
+ */
3021
+ function streamListener(ctx, depth, id, subscription) {
3022
+ const handle = (type, terminal) => (value, accept) => {
3023
+ let failure = void 0;
3024
+ if (ctx.state.alive) try {
3025
+ failure = parseEvent(ctx, depth, value, createStreamEventNode.bind(null, type, id), accept);
3026
+ } catch (error) {
3027
+ if (!subscription?.active) throw error;
3028
+ subscription.failure ?? (subscription.failure = { value: error });
3029
+ failure = error;
3030
+ }
3031
+ if (terminal && !accept) popPendingState(ctx);
3032
+ return failure;
3033
+ };
3034
+ return {
3035
+ next: handle(32, false),
3036
+ throw: handle(33, true),
3037
+ return: handle(34, true),
3038
+ done() {
3039
+ popPendingState(ctx);
3040
+ },
3041
+ error(reason) {
3042
+ if (ctx.state.alive) stopStreamParse(ctx, 1, reason);
3043
+ }
3044
+ };
2849
3045
  }
2850
- function onParseInternal(ctx, node, initial) {
3046
+ function subscribeStream(ctx, depth, id, current) {
3047
+ pushPendingState(ctx);
3048
+ const subscription = {
3049
+ active: true,
3050
+ failure: void 0
3051
+ };
3052
+ let cleanup;
3053
+ try {
3054
+ cleanup = current.on(streamListener(ctx, depth, id, subscription));
3055
+ } finally {
3056
+ subscription.active = false;
3057
+ }
2851
3058
  try {
2852
- ctx.state.onParse(node, initial);
3059
+ addCleanup(ctx, cleanup);
2853
3060
  } catch (error) {
2854
- onError(ctx, error);
3061
+ subscription.failure ?? (subscription.failure = { value: error });
2855
3062
  }
3063
+ const failure = subscription.failure;
3064
+ subscription.failure = void 0;
3065
+ if (failure) throw failure.value;
3066
+ }
3067
+ function consumeLiveStream(ctx, depth, id, current) {
3068
+ const cancel = current.pump(streamListener(ctx, depth, id));
3069
+ pushPendingState(ctx);
3070
+ addCleanup(ctx, () => {
3071
+ cancel(ctx.state.reason);
3072
+ });
3073
+ }
3074
+ function wrapPromiseResult(ctx, type, id, node) {
3075
+ return createSerovalNode(type, id, void 0, void 0, void 0, void 0, void 0, [parseSpecialReference(ctx.base, type === 23 ? 2 : 3), node], void 0, void 0, void 0, void 0);
3076
+ }
3077
+ function handlePromise(type, id, depth, data) {
3078
+ if (this.state.alive) parseEvent(this, depth, data, wrapPromiseResult.bind(null, this, type, id), void 0);
3079
+ popPendingState(this);
3080
+ }
3081
+ function watchPromise(ctx, resolver, depth, current) {
3082
+ pushPendingState(ctx);
3083
+ current.then(handlePromise.bind(ctx, 23, resolver, depth), handlePromise.bind(ctx, 24, resolver, depth));
3084
+ }
3085
+ function returnIterator(iterator) {
3086
+ Promise.resolve().then(() => iterator.return?.()).catch(() => {});
3087
+ }
3088
+ /**
3089
+ * Drives an async iterator directly. The next value is pulled only after the
3090
+ * record for the previous one has been accepted, and cancellation returns
3091
+ * the iterator once.
3092
+ */
3093
+ function iterateAsync(ctx, depth, id, current, forwardReason) {
3094
+ const iterator = current[SYM_ASYNC_ITERATOR]();
3095
+ const listener = streamListener(ctx, depth, id);
3096
+ let active = true;
3097
+ function stop() {
3098
+ if (active) {
3099
+ active = false;
3100
+ if (forwardReason) try {
3101
+ Promise.resolve(iterator.return?.(ctx.state.reason)).catch(() => {});
3102
+ } catch {}
3103
+ else returnIterator(iterator);
3104
+ }
3105
+ }
3106
+ function pull() {
3107
+ if (active) iterator.next().then((result) => {
3108
+ if (active) {
3109
+ if (result.done) {
3110
+ active = false;
3111
+ listener.return(result.value, void 0);
3112
+ } else if (listener.next(result.value, pull) !== void 0) {
3113
+ stop();
3114
+ listener.done();
3115
+ }
3116
+ }
3117
+ }, (error) => {
3118
+ if (active) {
3119
+ active = false;
3120
+ listener.throw(error, void 0);
3121
+ }
3122
+ });
3123
+ }
3124
+ pushPendingState(ctx);
3125
+ addCleanup(ctx, stop);
3126
+ pull();
3127
+ }
3128
+ function createStreamParserState(options) {
3129
+ return {
3130
+ alive: true,
3131
+ pending: 0,
3132
+ parsing: 0,
3133
+ queue: [],
3134
+ writing: false,
3135
+ inFlight: void 0,
3136
+ reason: void 0,
3137
+ onParse: options.onParse,
3138
+ onError: options.onError,
3139
+ onDone: options.onDone,
3140
+ cleanups: [],
3141
+ pluginContexts: [],
3142
+ stream: subscribeStream,
3143
+ live: consumeLiveStream,
3144
+ promise: watchPromise,
3145
+ iterable: iterateAsync,
3146
+ plugin: parsePluginStream
3147
+ };
3148
+ }
3149
+ function createStreamParserContext(options) {
3150
+ return {
3151
+ type: 2,
3152
+ base: createBaseParserContext(options),
3153
+ state: createStreamParserState(options)
3154
+ };
2856
3155
  }
2857
3156
  function pushPendingState(ctx) {
2858
- ctx.state.pending++;
3157
+ if (ctx.state.alive) ctx.state.pending++;
2859
3158
  }
2860
3159
  function popPendingState(ctx) {
2861
- if (--ctx.state.pending <= 0) onDone(ctx);
3160
+ if (ctx.state.alive) {
3161
+ ctx.state.pending--;
3162
+ checkStreamParse(ctx);
3163
+ }
2862
3164
  }
2863
- function parseWithError(ctx, depth, current) {
3165
+ /**
3166
+ * Parses a value that arrived after the root. Its record is queued before
3167
+ * parsing starts so that records discovered inside it follow it, and it is
3168
+ * dropped again if parsing fails. Returns the parse error after reporting
3169
+ * it, or `undefined`.
3170
+ */
3171
+ function parseEvent(ctx, depth, value, wrap, accept) {
3172
+ const state = ctx.state;
3173
+ const record = {
3174
+ node: void 0,
3175
+ initial: false,
3176
+ accept
3177
+ };
3178
+ let failure;
3179
+ state.queue.push(record);
3180
+ state.parsing++;
2864
3181
  try {
2865
- return parseSOS(ctx, depth, current);
2866
- } catch (err) {
2867
- onError(ctx, err);
2868
- return;
3182
+ record.node = wrap(parseSOS(ctx, depth, value));
3183
+ } catch (error) {
3184
+ failure = { value: error };
3185
+ } finally {
3186
+ state.parsing--;
3187
+ if (!state.alive) releaseParserValues(ctx);
3188
+ }
3189
+ if (failure) stopStreamParse(ctx, 1, failure.value);
3190
+ else drainOutput(ctx);
3191
+ return failure?.value;
3192
+ }
3193
+ /**
3194
+ * Emits queued records one at a time. A callback that returns a promise
3195
+ * pauses emission until it settles; the source event behind the record is
3196
+ * accepted only after that.
3197
+ */
3198
+ function drainOutput(ctx) {
3199
+ const state = ctx.state;
3200
+ if (state.writing || state.parsing > 0) return;
3201
+ while (state.alive && state.queue.length > 0) {
3202
+ const record = state.queue.shift();
3203
+ if (!record.node) continue;
3204
+ let pending;
3205
+ state.writing = true;
3206
+ state.inFlight = record;
3207
+ state.parsing++;
3208
+ try {
3209
+ if (!state.onParse) throw new Error("Stream output callback is unavailable");
3210
+ const result = state.onParse(record.node, record.initial);
3211
+ if (result !== null && (typeof result === "object" || typeof result === "function")) {
3212
+ const then = Reflect.get(result, "then");
3213
+ if (typeof then === "function") pending = new Promise((resolve, reject) => {
3214
+ Reflect.apply(then, result, [resolve, reject]);
3215
+ });
3216
+ }
3217
+ } catch (error) {
3218
+ releaseRecord(record);
3219
+ stopStreamParse(ctx, 1, error);
3220
+ return;
3221
+ } finally {
3222
+ state.parsing--;
3223
+ if (!state.alive) releaseParserValues(ctx);
3224
+ }
3225
+ record.node = void 0;
3226
+ if (pending) {
3227
+ if (!state.alive) releaseRecord(record);
3228
+ pending.then(() => {
3229
+ state.writing = false;
3230
+ state.inFlight = void 0;
3231
+ if (state.alive) {
3232
+ const accept = record.accept;
3233
+ releaseRecord(record);
3234
+ accept?.();
3235
+ drainOutput(ctx);
3236
+ }
3237
+ }, (error) => {
3238
+ state.writing = false;
3239
+ state.inFlight = void 0;
3240
+ releaseRecord(record);
3241
+ stopStreamParse(ctx, 1, error);
3242
+ });
3243
+ return;
3244
+ }
3245
+ if (!state.alive) {
3246
+ releaseRecord(record);
3247
+ return;
3248
+ }
3249
+ state.writing = false;
3250
+ state.inFlight = void 0;
3251
+ const accept = record.accept;
3252
+ releaseRecord(record);
3253
+ accept?.();
2869
3254
  }
3255
+ checkStreamParse(ctx);
3256
+ }
3257
+ function checkStreamParse(ctx) {
3258
+ const state = ctx.state;
3259
+ if (state.alive && state.parsing === 0 && state.pending <= 0 && state.queue.length === 0 && !state.writing) stopStreamParse(ctx, 0);
2870
3260
  }
2871
3261
  function startStreamParse(ctx, current) {
2872
- const parsed = parseWithError(ctx, 0, current);
2873
- if (parsed) {
2874
- onParseInternal(ctx, parsed, true);
2875
- ctx.state.initial = false;
2876
- flushStreamParse(ctx, ctx.state);
2877
- if (ctx.state.pending <= 0) destroyStreamParse(ctx);
3262
+ const state = ctx.state;
3263
+ let parsed;
3264
+ let failure;
3265
+ state.parsing++;
3266
+ try {
3267
+ parsed = parseSOS(ctx, 0, current);
3268
+ } catch (error) {
3269
+ failure = { value: error };
3270
+ } finally {
3271
+ state.parsing--;
3272
+ if (!state.alive) releaseParserValues(ctx);
3273
+ }
3274
+ if (failure) {
3275
+ if (state.alive) stopStreamParse(ctx, 1, failure.value);
3276
+ else throw failure.value;
3277
+ } else if (parsed && state.alive) {
3278
+ state.queue.unshift({
3279
+ node: parsed,
3280
+ initial: true,
3281
+ accept: void 0
3282
+ });
3283
+ drainOutput(ctx);
3284
+ }
3285
+ }
3286
+ function runCleanups(state) {
3287
+ const cleanups = state.cleanups;
3288
+ let failure;
3289
+ state.cleanups = [];
3290
+ for (const record of state.queue) releaseRecord(record);
3291
+ state.queue.length = 0;
3292
+ if (state.inFlight) releaseRecord(state.inFlight);
3293
+ state.inFlight = void 0;
3294
+ for (let i = 0, len = cleanups.length; i < len; i++) try {
3295
+ cleanups[i]();
3296
+ } catch (error) {
3297
+ failure ?? (failure = { value: error });
2878
3298
  }
3299
+ if (failure) throw failure.value;
2879
3300
  }
2880
- function flushStreamParse(ctx, state) {
2881
- for (let i = 0, len = state.buffer.length; i < len; i++) onParseInternal(ctx, state.buffer[i], false);
3301
+ function releaseRecord(record) {
3302
+ record.node = void 0;
3303
+ record.accept = void 0;
2882
3304
  }
2883
- function destroyStreamParse(ctx) {
2884
- if (ctx.state.alive) {
2885
- onDone(ctx);
2886
- ctx.state.alive = false;
3305
+ function releaseParserValues(ctx) {
3306
+ ctx.base.refs = /* @__PURE__ */ new Map();
3307
+ ctx.base.marked.clear();
3308
+ ctx.base.plugins = void 0;
3309
+ ctx.base.plainObjectPlugins = void 0;
3310
+ ctx.state.pluginContexts = [];
3311
+ if (ctx.state.parsing === 0) ctx.state.reason = void 0;
3312
+ }
3313
+ /**
3314
+ * Ends the parse once: `onDone` on success, `onError` on failure, and every
3315
+ * cleanup either way.
3316
+ */
3317
+ function stopStreamParse(ctx, mode, reason) {
3318
+ const state = ctx.state;
3319
+ if (state.alive) {
3320
+ state.alive = false;
3321
+ const onError = state.onError;
3322
+ const onDone = state.onDone;
3323
+ if (mode === 1 && !onError && !(reason instanceof SerovalParserError)) reason = new SerovalParserError(reason);
3324
+ state.reason = reason;
3325
+ state.onParse = void 0;
3326
+ state.onError = void 0;
3327
+ state.onDone = void 0;
3328
+ state.writing = false;
3329
+ state.parsing++;
3330
+ let failure;
3331
+ try {
3332
+ if (mode === 1) {
3333
+ if (onError) onError(reason);
3334
+ else throw reason;
3335
+ } else if (mode === 0) onDone?.();
3336
+ } catch (error) {
3337
+ failure = { value: error };
3338
+ }
3339
+ try {
3340
+ runCleanups(state);
3341
+ } catch (error) {
3342
+ failure ?? (failure = { value: error });
3343
+ } finally {
3344
+ state.parsing--;
3345
+ releaseParserValues(ctx);
3346
+ state.pending = 0;
3347
+ }
3348
+ if (failure) throw failure.value;
2887
3349
  }
2888
3350
  }
3351
+ function destroyStreamParse(ctx, reason) {
3352
+ stopStreamParse(ctx, 2, reason);
3353
+ }
2889
3354
  //#endregion
2890
3355
  //#region src/core/cross/index.ts
2891
3356
  function crossSerialize(source, options = {}) {
2892
3357
  const plugins = resolvePlugins(options.plugins);
2893
- const ctx = createSyncParserContext(2, {
3358
+ const ctx = createSyncParserContext({
2894
3359
  compactArrayBufferViews: options.compactArrayBufferViews,
3360
+ depthLimit: options.depthLimit,
2895
3361
  plugins,
2896
3362
  disabledFeatures: options.disabledFeatures,
2897
3363
  refs: options.refs
@@ -2901,13 +3367,15 @@ function crossSerialize(source, options = {}) {
2901
3367
  plugins,
2902
3368
  features: ctx.base.features,
2903
3369
  scopeId: options.scopeId,
2904
- markedRefs: ctx.base.marked
3370
+ markedRefs: ctx.base.marked,
3371
+ assignSharedRefsOnly: options.assignSharedRefsOnly
2905
3372
  }), tree);
2906
3373
  }
2907
3374
  async function crossSerializeAsync(source, options = {}) {
2908
3375
  const plugins = resolvePlugins(options.plugins);
2909
- const ctx = createAsyncParserContext(2, {
3376
+ const ctx = createAsyncParserContext({
2910
3377
  compactArrayBufferViews: options.compactArrayBufferViews,
3378
+ depthLimit: options.depthLimit,
2911
3379
  plugins,
2912
3380
  disabledFeatures: options.disabledFeatures,
2913
3381
  refs: options.refs
@@ -2917,13 +3385,15 @@ async function crossSerializeAsync(source, options = {}) {
2917
3385
  plugins,
2918
3386
  features: ctx.base.features,
2919
3387
  scopeId: options.scopeId,
2920
- markedRefs: ctx.base.marked
3388
+ markedRefs: ctx.base.marked,
3389
+ assignSharedRefsOnly: options.assignSharedRefsOnly
2921
3390
  }), tree);
2922
3391
  }
2923
3392
  function toCrossJSON(source, options = {}) {
2924
3393
  const plugins = resolvePlugins(options.plugins);
2925
- return parseTop(createSyncParserContext(2, {
3394
+ return parseTop(createSyncParserContext({
2926
3395
  compactArrayBufferViews: options.compactArrayBufferViews,
3396
+ depthLimit: options.depthLimit,
2927
3397
  plugins,
2928
3398
  disabledFeatures: options.disabledFeatures,
2929
3399
  refs: options.refs
@@ -2931,8 +3401,9 @@ function toCrossJSON(source, options = {}) {
2931
3401
  }
2932
3402
  async function toCrossJSONAsync(source, options = {}) {
2933
3403
  const plugins = resolvePlugins(options.plugins);
2934
- return await parseTopAsync(createAsyncParserContext(2, {
3404
+ return await parseTopAsync(createAsyncParserContext({
2935
3405
  compactArrayBufferViews: options.compactArrayBufferViews,
3406
+ depthLimit: options.depthLimit,
2936
3407
  plugins,
2937
3408
  disabledFeatures: options.disabledFeatures,
2938
3409
  refs: options.refs
@@ -2940,8 +3411,11 @@ async function toCrossJSONAsync(source, options = {}) {
2940
3411
  }
2941
3412
  function crossSerializeStream(source, options) {
2942
3413
  const plugins = resolvePlugins(options.plugins);
3414
+ const onSerialize = options.onSerialize;
3415
+ const scopeId = options.scopeId;
2943
3416
  const ctx = createStreamParserContext({
2944
3417
  compactArrayBufferViews: options.compactArrayBufferViews,
3418
+ depthLimit: options.depthLimit,
2945
3419
  plugins,
2946
3420
  refs: options.refs,
2947
3421
  disabledFeatures: options.disabledFeatures,
@@ -2949,17 +3423,10 @@ function crossSerializeStream(source, options) {
2949
3423
  const serial = createCrossSerializerContext({
2950
3424
  plugins,
2951
3425
  features: ctx.base.features,
2952
- scopeId: options.scopeId,
3426
+ scopeId,
2953
3427
  markedRefs: ctx.base.marked
2954
3428
  });
2955
- let serialized;
2956
- try {
2957
- serialized = serializeTopCross(serial, node);
2958
- } catch (err) {
2959
- if (options.onError) options.onError(err);
2960
- return;
2961
- }
2962
- options.onSerialize(serialized, initial);
3429
+ return onSerialize(serializeTopCross(serial, node), initial);
2963
3430
  },
2964
3431
  onError: options.onError,
2965
3432
  onDone: options.onDone
@@ -2982,22 +3449,39 @@ function toCrossJSONStream(source, options) {
2982
3449
  startStreamParse(ctx, source);
2983
3450
  return destroyStreamParse.bind(null, ctx);
2984
3451
  }
2985
- function fromCrossJSON(source, options) {
2986
- const plugins = resolvePlugins(options.plugins);
2987
- return deserializeTop(createCrossDeserializerContext({
3452
+ function createFromCrossJSONContext(options) {
3453
+ return createCrossDeserializerContext({
2988
3454
  maxBase64Length: options.maxBase64Length,
2989
- plugins,
3455
+ plugins: resolvePlugins(options.plugins),
2990
3456
  refs: options.refs,
2991
3457
  features: options.features,
2992
3458
  disabledFeatures: options.disabledFeatures,
2993
3459
  depthLimit: options.depthLimit
2994
- }), source);
3460
+ });
3461
+ }
3462
+ function fromCrossJSON(source, options) {
3463
+ return deserializeTop(createFromCrossJSONContext(options), source);
3464
+ }
3465
+ function createCrossDeserializer(options) {
3466
+ const ctx = createFromCrossJSONContext(options);
3467
+ ctx.base.pending = /* @__PURE__ */ new Set();
3468
+ return {
3469
+ deserialize(node) {
3470
+ if (!ctx.base.pending) throw new SerovalAbortedError();
3471
+ return deserializeTop(ctx, node);
3472
+ },
3473
+ get pending() {
3474
+ return ctx.base.pending?.size ?? 0;
3475
+ },
3476
+ abort(reason) {
3477
+ abortDeferred(ctx, reason);
3478
+ }
3479
+ };
2995
3480
  }
2996
3481
  //#endregion
2997
3482
  //#region src/core/Serializer.ts
2998
3483
  var Serializer = class {
2999
3484
  constructor(options) {
3000
- this.options = options;
3001
3485
  this.alive = true;
3002
3486
  this.flushed = false;
3003
3487
  this.done = false;
@@ -3006,32 +3490,52 @@ var Serializer = class {
3006
3490
  this.refs = /* @__PURE__ */ new Map();
3007
3491
  this.keys = /* @__PURE__ */ new Set();
3008
3492
  this.ids = 0;
3493
+ this.options = options;
3009
3494
  this.plugins = resolvePlugins(options.plugins);
3010
3495
  }
3011
3496
  write(key, value) {
3012
- if (this.alive && !this.flushed) {
3497
+ const options = this.options;
3498
+ if (this.alive && !this.flushed && options) {
3013
3499
  this.pending++;
3014
3500
  this.keys.add(key);
3015
- this.cleanups.push(crossSerializeStream(value, {
3501
+ const cleanup = crossSerializeStream(value, {
3016
3502
  plugins: this.plugins,
3017
- scopeId: this.options.scopeId,
3503
+ scopeId: options.scopeId,
3018
3504
  refs: this.refs,
3019
- disabledFeatures: this.options.disabledFeatures,
3020
- compactArrayBufferViews: this.options.compactArrayBufferViews,
3021
- onError: this.options.onError,
3505
+ disabledFeatures: options.disabledFeatures,
3506
+ compactArrayBufferViews: options.compactArrayBufferViews,
3507
+ depthLimit: options.depthLimit,
3508
+ onError: (error) => {
3509
+ let failure;
3510
+ try {
3511
+ if (options.onError) options.onError(error);
3512
+ else throw error instanceof SerovalParserError ? error : new SerovalParserError(error);
3513
+ } catch (handlerError) {
3514
+ failure = { value: handlerError };
3515
+ }
3516
+ try {
3517
+ this.finishWrite();
3518
+ } catch (finishError) {
3519
+ failure ?? (failure = { value: finishError });
3520
+ }
3521
+ if (failure) throw failure.value;
3522
+ },
3022
3523
  onSerialize: (data, initial) => {
3023
- if (this.alive) this.options.onData(initial ? this.options.globalIdentifier + "[\"" + serializeString(key) + "\"]=" + data : data);
3524
+ const current = this.options;
3525
+ if (this.alive && current) current.onData(initial ? current.globalIdentifier + "[\"" + serializeString(key) + "\"]=" + data : data);
3024
3526
  },
3025
3527
  onDone: () => {
3026
- if (this.alive) {
3027
- this.pending--;
3028
- if (this.pending <= 0 && this.flushed && !this.done && this.options.onDone) {
3029
- this.options.onDone();
3030
- this.done = true;
3031
- }
3032
- }
3528
+ this.finishWrite();
3033
3529
  }
3034
- }));
3530
+ });
3531
+ if (this.alive) this.cleanups.push(cleanup);
3532
+ else cleanup();
3533
+ }
3534
+ }
3535
+ finishWrite() {
3536
+ if (this.alive) {
3537
+ this.pending--;
3538
+ if (this.pending <= 0 && this.flushed && !this.done) this.close();
3035
3539
  }
3036
3540
  }
3037
3541
  getNextID() {
@@ -3046,20 +3550,36 @@ var Serializer = class {
3046
3550
  flush() {
3047
3551
  if (this.alive) {
3048
3552
  this.flushed = true;
3049
- if (this.pending <= 0 && !this.done && this.options.onDone) {
3050
- this.options.onDone();
3051
- this.done = true;
3052
- }
3553
+ if (this.pending <= 0 && !this.done) this.close();
3053
3554
  }
3054
3555
  }
3055
3556
  close() {
3557
+ this.finish();
3558
+ }
3559
+ finish() {
3056
3560
  if (this.alive) {
3057
- for (let i = 0, len = this.cleanups.length; i < len; i++) this.cleanups[i]();
3058
- if (!this.done && this.options.onDone) {
3059
- this.options.onDone();
3561
+ this.alive = false;
3562
+ const options = this.options;
3563
+ this.options = void 0;
3564
+ this.plugins = void 0;
3565
+ const cleanups = this.cleanups;
3566
+ this.cleanups = [];
3567
+ let failure;
3568
+ for (let index = 0, length = cleanups.length; index < length; index++) try {
3569
+ cleanups[index]();
3570
+ } catch (error) {
3571
+ failure ?? (failure = { value: error });
3572
+ }
3573
+ this.refs.clear();
3574
+ if (!this.done) {
3060
3575
  this.done = true;
3576
+ try {
3577
+ options?.onDone?.();
3578
+ } catch (error) {
3579
+ failure ?? (failure = { value: error });
3580
+ }
3061
3581
  }
3062
- this.alive = false;
3582
+ if (failure) throw failure.value;
3063
3583
  }
3064
3584
  }
3065
3585
  };
@@ -3067,8 +3587,9 @@ var Serializer = class {
3067
3587
  //#region src/core/tree/index.ts
3068
3588
  function serialize(source, options = {}) {
3069
3589
  const plugins = resolvePlugins(options.plugins);
3070
- const ctx = createSyncParserContext(1, {
3590
+ const ctx = createSyncParserContext({
3071
3591
  compactArrayBufferViews: options.compactArrayBufferViews,
3592
+ depthLimit: options.depthLimit,
3072
3593
  plugins,
3073
3594
  disabledFeatures: options.disabledFeatures
3074
3595
  });
@@ -3081,8 +3602,9 @@ function serialize(source, options = {}) {
3081
3602
  }
3082
3603
  async function serializeAsync(source, options = {}) {
3083
3604
  const plugins = resolvePlugins(options.plugins);
3084
- const ctx = createAsyncParserContext(1, {
3605
+ const ctx = createAsyncParserContext({
3085
3606
  compactArrayBufferViews: options.compactArrayBufferViews,
3607
+ depthLimit: options.depthLimit,
3086
3608
  plugins,
3087
3609
  disabledFeatures: options.disabledFeatures
3088
3610
  });
@@ -3098,8 +3620,9 @@ function deserialize(source) {
3098
3620
  }
3099
3621
  function toJSON(source, options = {}) {
3100
3622
  const plugins = resolvePlugins(options.plugins);
3101
- const ctx = createSyncParserContext(1, {
3623
+ const ctx = createSyncParserContext({
3102
3624
  compactArrayBufferViews: options.compactArrayBufferViews,
3625
+ depthLimit: options.depthLimit,
3103
3626
  plugins,
3104
3627
  disabledFeatures: options.disabledFeatures
3105
3628
  });
@@ -3111,8 +3634,9 @@ function toJSON(source, options = {}) {
3111
3634
  }
3112
3635
  async function toJSONAsync(source, options = {}) {
3113
3636
  const plugins = resolvePlugins(options.plugins);
3114
- const ctx = createAsyncParserContext(1, {
3637
+ const ctx = createAsyncParserContext({
3115
3638
  compactArrayBufferViews: options.compactArrayBufferViews,
3639
+ depthLimit: options.depthLimit,
3116
3640
  plugins,
3117
3641
  disabledFeatures: options.disabledFeatures
3118
3642
  });
@@ -3130,11 +3654,11 @@ function compileJSON(source, options = {}) {
3130
3654
  }), source.t);
3131
3655
  }
3132
3656
  function fromJSON(source, options = {}) {
3133
- var _source$f;
3134
3657
  const plugins = resolvePlugins(options.plugins);
3135
- const disabledFeatures = options.disabledFeatures || 0;
3136
- const sourceFeatures = (_source$f = source.f) !== null && _source$f !== void 0 ? _source$f : 127;
3658
+ const disabledFeatures = options.disabledFeatures ?? 0;
3659
+ const sourceFeatures = source.f ?? 127;
3137
3660
  return deserializeTop(createVanillaDeserializerContext({
3661
+ depthLimit: options.depthLimit,
3138
3662
  maxBase64Length: options.maxBase64Length,
3139
3663
  plugins,
3140
3664
  markedRefs: source.m,
@@ -3144,12 +3668,16 @@ function fromJSON(source, options = {}) {
3144
3668
  }
3145
3669
  //#endregion
3146
3670
  exports.Feature = Feature;
3671
+ exports.LiveStream = LiveStream;
3147
3672
  exports.OpaqueReference = OpaqueReference;
3673
+ exports.Sequence = Sequence;
3148
3674
  exports.Serializer = Serializer;
3675
+ exports.SerovalAbortedError = SerovalAbortedError;
3149
3676
  exports.SerovalConflictedNodeIdError = SerovalConflictedNodeIdError;
3150
3677
  exports.SerovalDepthLimitError = SerovalDepthLimitError;
3151
3678
  exports.SerovalDeserializationError = SerovalDeserializationError;
3152
3679
  exports.SerovalError = SerovalError;
3680
+ exports.SerovalLiveStreamError = SerovalLiveStreamError;
3153
3681
  exports.SerovalMalformedNodeError = SerovalMalformedNodeError;
3154
3682
  exports.SerovalMissingInstanceError = SerovalMissingInstanceError;
3155
3683
  exports.SerovalMissingPluginError = SerovalMissingPluginError;
@@ -3161,7 +3689,10 @@ exports.SerovalSerializationError = SerovalSerializationError;
3161
3689
  exports.SerovalUnknownTypedArrayError = SerovalUnknownTypedArrayError;
3162
3690
  exports.SerovalUnsupportedNodeError = SerovalUnsupportedNodeError;
3163
3691
  exports.SerovalUnsupportedTypeError = SerovalUnsupportedTypeError;
3692
+ exports.Stream = Stream;
3164
3693
  exports.compileJSON = compileJSON;
3694
+ exports.createCrossDeserializer = createCrossDeserializer;
3695
+ exports.createLiveStream = createLiveStream;
3165
3696
  exports.createPlugin = createPlugin;
3166
3697
  exports.createReference = createReference;
3167
3698
  exports.createStream = createStream;
@@ -3172,6 +3703,8 @@ exports.deserialize = deserialize;
3172
3703
  exports.fromCrossJSON = fromCrossJSON;
3173
3704
  exports.fromJSON = fromJSON;
3174
3705
  exports.getCrossReferenceHeader = getCrossReferenceHeader;
3706
+ exports.getPlainObjectPlugins = getPlainObjectPlugins;
3707
+ exports.isLiveStream = isLiveStream;
3175
3708
  exports.isStream = isStream;
3176
3709
  exports.resolvePlugins = resolvePlugins;
3177
3710
  exports.serialize = serialize;