seroval 1.6.11 → 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,118 +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);
1002
- }
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);
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)]);
1005
1267
  }
1006
- function createMapNode(ctx, id, k, v) {
1007
- return createSerovalNode(8, id, void 0, void 0, void 0, void 0, {
1008
- k,
1009
- v
1010
- }, void 0, parseSpecialReference(ctx, 0), void 0, void 0, void 0);
1011
- }
1012
- function createPromiseConstructorNode(ctx, id, resolver) {
1013
- return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1), void 0, void 0, 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
+ }
1014
1280
  }
1015
- function getArrayBufferView(ctx, current) {
1016
- if (!ctx.compactArrayBufferViews) return current;
1017
- const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
1018
- return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
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;
1019
1288
  }
1020
- function encodeArrayBuffer(current) {
1021
- if (typeof Buffer !== "undefined") return Buffer.from(current).toString("base64");
1022
- const bytes = new Uint8Array(current);
1023
- if (typeof bytes.toBase64 === "function") return bytes.toBase64();
1024
- let result = "";
1025
- for (let i = 0, len = bytes.length; i < len; i++) result += String.fromCharCode(bytes[i]);
1026
- return btoa(result);
1289
+ /**
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.
1292
+ */
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
+ }
1348
+ function createPromiseConstructorNode(ctx, id, resolver) {
1349
+ return createSerovalNode(22, id, resolver, void 0, void 0, void 0, void 0, void 0, parseSpecialReference(ctx, 1));
1350
+ }
1351
+ function getArrayBufferView(ctx, current) {
1352
+ if (!ctx.compactArrayBufferViews) return current;
1353
+ const buffer = new Uint8Array(current.buffer, current.byteOffset, current.byteLength).slice().buffer;
1354
+ return new (current instanceof DataView ? DataView : getTypedArrayConstructor(getTypedArrayName(current)))(buffer);
1027
1355
  }
1028
1356
  function createArrayBufferNode(ctx, id, current) {
1029
- 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));
1030
1358
  }
1031
1359
  //#endregion
1032
1360
  //#region src/core/context/async-parser.ts
1033
- function createAsyncParserContext(mode, options) {
1034
- return {
1035
- base: createBaseParserContext(mode, options),
1036
- child: void 0
1037
- };
1361
+ function createAsyncParserContext(options) {
1362
+ return { base: createBaseParserContext(options) };
1038
1363
  }
1039
- var AsyncParsePluginContext = class {
1040
- constructor(_p, depth) {
1041
- this._p = _p;
1042
- this.depth = depth;
1043
- }
1044
- parse(current) {
1045
- return parseAsync(this._p, this.depth, current);
1046
- }
1047
- };
1048
1364
  async function parseItems$1(ctx, depth, current) {
1049
- const nodes = [];
1050
- for (let i = 0, len = current.length; i < len; i++) if (i in current) nodes[i] = await parseAsync(ctx, depth, current[i]);
1051
- 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;
1052
1371
  return nodes;
1053
1372
  }
1054
1373
  async function parseArray$1(ctx, depth, id, current) {
1055
1374
  return createArrayNode(id, current, await parseItems$1(ctx, depth, current));
1056
1375
  }
1057
1376
  async function parseProperties$1(ctx, depth, properties) {
1058
- const entries = Object.entries(properties);
1059
- const keyNodes = [];
1060
- const valueNodes = [];
1061
- for (let i = 0, len = entries.length; i < len; i++) {
1062
- keyNodes.push(serializeString(entries[i][0]));
1063
- 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;
1064
1386
  }
1065
1387
  if (SYM_ITERATOR in properties) {
1066
1388
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
1067
- 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))));
1068
1390
  }
1069
1391
  if (SYM_ASYNC_ITERATOR in properties) {
1070
1392
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
1071
- 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)));
1072
1394
  }
1073
1395
  if (SYM_TO_STRING_TAG in properties) {
1074
1396
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
@@ -1089,166 +1411,183 @@ async function parsePlainObject$1(ctx, depth, id, current, empty) {
1089
1411
  async function parseBoxed$1(ctx, depth, id, current) {
1090
1412
  return createBoxedNode(id, await parseAsync(ctx, depth, current.valueOf()));
1091
1413
  }
1092
- async function parseTypedArray$1(ctx, depth, id, current) {
1093
- current = getArrayBufferView(ctx.base, current);
1094
- return createTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
1095
- }
1096
- async function parseBigIntTypedArray$1(ctx, depth, id, current) {
1097
- current = getArrayBufferView(ctx.base, current);
1098
- return createBigIntTypedArrayNode(id, current, await parseAsync(ctx, depth, current.buffer));
1099
- }
1100
- async function parseDataView$1(ctx, depth, id, current) {
1414
+ async function parseView$1(ctx, depth, type, id, current) {
1101
1415
  current = getArrayBufferView(ctx.base, current);
1102
- return createDataViewNode(id, current, await parseAsync(ctx, depth, current.buffer));
1416
+ return createViewNode(type, id, current, await parseAsync(ctx, depth, current.buffer));
1103
1417
  }
1104
- async function parseError$1(ctx, depth, id, current) {
1418
+ async function parseError$1(ctx, depth, type, id, current) {
1105
1419
  const options = getErrorOptions(current, ctx.base.features);
1106
- return createErrorNode(id, current, options ? await parseProperties$1(ctx, depth, options) : void 0);
1107
- }
1108
- async function parseAggregateError$1(ctx, depth, id, current) {
1109
- const options = getErrorOptions(current, ctx.base.features);
1110
- 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);
1111
1421
  }
1112
1422
  async function parseMap$1(ctx, depth, id, current) {
1113
- const keyNodes = [];
1114
- const valueNodes = [];
1423
+ const sentinel = parseMapSentinel(ctx.base);
1424
+ const keyNodes = new Array(current.size);
1425
+ const valueNodes = new Array(current.size);
1426
+ let node;
1427
+ let i = 0;
1115
1428
  for (const [key, value] of current.entries()) {
1116
- keyNodes.push(await parseAsync(ctx, depth, key));
1117
- 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++;
1118
1434
  }
1119
- return createMapNode(ctx.base, id, keyNodes, valueNodes);
1435
+ return createMapNode(id, sentinel, keyNodes, valueNodes);
1120
1436
  }
1121
1437
  async function parseSet$1(ctx, depth, id, current) {
1122
- const items = [];
1123
- 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
+ }
1124
1445
  return createSetNode(id, items);
1125
1446
  }
1126
- async function parsePlugin$1(ctx, depth, id, current) {
1127
- const currentPlugins = ctx.base.plugins;
1447
+ async function parsePlugin$1(ctx, depth, id, current, currentPlugins) {
1128
1448
  if (currentPlugins) for (let i = 0, len = currentPlugins.length; i < len; i++) {
1129
1449
  const plugin = currentPlugins[i];
1130
- 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 }));
1131
1457
  }
1132
1458
  }
1133
1459
  async function parsePromise$1(ctx, depth, id, current) {
1134
1460
  const [status, result] = await promiseToResult(current);
1135
- 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));
1136
1462
  }
1137
1463
  function parseStreamHandle(depth, id, current, resolve, reject) {
1138
1464
  const sequence = [];
1139
- const cleanup = current.on({
1140
- next: (value) => {
1141
- markParserRef(this.base, id);
1142
- parseAsync(this, depth, value).then((data) => {
1143
- sequence.push(createStreamNextNode(id, data));
1144
- }, (data) => {
1145
- reject(data);
1146
- cleanup();
1147
- });
1148
- },
1149
- throw: (value) => {
1150
- markParserRef(this.base, id);
1151
- parseAsync(this, depth, value).then((data) => {
1152
- sequence.push(createStreamThrowNode(id, data));
1153
- resolve(sequence);
1154
- cleanup();
1155
- }, (data) => {
1156
- reject(data);
1157
- cleanup();
1158
- });
1159
- },
1160
- return: (value) => {
1161
- markParserRef(this.base, id);
1162
- parseAsync(this, depth, value).then((data) => {
1163
- sequence.push(createStreamReturnNode(id, data));
1164
- resolve(sequence);
1165
- cleanup();
1166
- }, (data) => {
1167
- reject(data);
1168
- cleanup();
1169
- });
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);
1170
1475
  }
1171
- });
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);
1172
1507
  }
1173
1508
  async function parseStream$1(ctx, depth, id, current) {
1174
1509
  return createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), await new Promise(parseStreamHandle.bind(ctx, depth, id, current)));
1175
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
+ }
1176
1541
  async function parseSequence$1(ctx, depth, id, current) {
1177
- const nodes = [];
1178
- 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
+ }
1179
1548
  return createSequenceNode(id, nodes, current.t, current.d);
1180
1549
  }
1181
1550
  async function parseObjectAsync(ctx, depth, id, current) {
1182
1551
  if (Array.isArray(current)) return parseArray$1(ctx, depth, id, current);
1183
1552
  if (isStream(current)) return parseStream$1(ctx, depth, id, current);
1184
1553
  if (isSequence(current)) return parseSequence$1(ctx, depth, id, current);
1185
- let currentClass = current.constructor;
1186
- if (currentClass !== void 0 && typeof currentClass !== "function") {
1187
- const proto = Object.getPrototypeOf(current);
1188
- currentClass = proto === null ? void 0 : proto.constructor;
1189
- }
1554
+ const currentClass = getObjectClass(current);
1190
1555
  if (currentClass === OpaqueReference) return parseAsync(ctx, depth, current.replacement);
1191
- const parsed = await parsePlugin$1(ctx, depth, id, current);
1556
+ const parsed = await parsePlugin$1(ctx, depth, id, current, getObjectPlugins(ctx.base, current, currentClass));
1192
1557
  if (parsed) return parsed;
1193
- switch (currentClass) {
1194
- case Object: return parsePlainObject$1(ctx, depth, id, current, false);
1195
- case void 0: return parsePlainObject$1(ctx, depth, id, current, true);
1196
- case Date: return createDateNode(id, current);
1197
- case Error:
1198
- case EvalError:
1199
- case RangeError:
1200
- case ReferenceError:
1201
- case SyntaxError:
1202
- case TypeError:
1203
- case URIError: return parseError$1(ctx, depth, id, current);
1204
- case Number:
1205
- case Boolean:
1206
- case String:
1207
- case BigInt: return parseBoxed$1(ctx, depth, id, current);
1208
- case ArrayBuffer: return createArrayBufferNode(ctx.base, id, current);
1209
- case Int8Array:
1210
- case Int16Array:
1211
- case Int32Array:
1212
- case Uint8Array:
1213
- case Uint16Array:
1214
- case Uint32Array:
1215
- case Uint8ClampedArray:
1216
- case Float32Array:
1217
- case Float64Array: return parseTypedArray$1(ctx, depth, id, current);
1218
- case DataView: return parseDataView$1(ctx, depth, id, current);
1219
- case Map: return parseMap$1(ctx, depth, id, current);
1220
- case Set: return parseSet$1(ctx, depth, id, current);
1221
- }
1222
- if (currentClass === Promise || current instanceof Promise) return parsePromise$1(ctx, depth, id, current);
1223
- const currentFeatures = ctx.base.features;
1224
- if (currentFeatures & 32 && currentClass === RegExp) return createRegExpNode(id, current);
1225
- if (currentFeatures & 16) switch (currentClass) {
1226
- case BigInt64Array:
1227
- case BigUint64Array: return parseBigIntTypedArray$1(ctx, depth, id, current);
1228
- }
1229
- if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError$1(ctx, depth, id, current);
1230
- if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
1231
- case Temporal.Instant: return createTemporalNode(id, 0, current);
1232
- case Temporal.Duration: return createTemporalNode(id, 1, current);
1233
- case Temporal.PlainDate: return createTemporalNode(id, 2, current);
1234
- case Temporal.PlainDateTime: return createTemporalNode(id, 3, current);
1235
- case Temporal.PlainMonthDay: return createTemporalNode(id, 4, current);
1236
- case Temporal.PlainTime: return createTemporalNode(id, 5, current);
1237
- case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
1238
- case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
1239
- }
1240
- if (current instanceof Error) return parseError$1(ctx, depth, id, current);
1241
- if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject$1(ctx, depth, id, current, !!currentClass);
1242
- 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
+ }
1243
1577
  }
1244
1578
  async function parseFunctionAsync(ctx, depth, current) {
1245
1579
  const ref = getReferenceNode(ctx.base, current);
1246
- if (ref.type !== 0) return ref.value;
1247
- 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);
1248
1582
  if (plugin) return plugin;
1249
1583
  throw new SerovalUnsupportedTypeError(current);
1250
1584
  }
1251
- 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) {
1252
1591
  if (depth >= ctx.base.depthLimit) throw new SerovalDepthLimitError(ctx.base.depthLimit);
1253
1592
  switch (typeof current) {
1254
1593
  case "boolean": return current ? TRUE_NODE : FALSE_NODE;
@@ -1259,7 +1598,7 @@ async function parseAsync(ctx, depth, current) {
1259
1598
  case "object":
1260
1599
  if (current) {
1261
1600
  const ref = getReferenceNode(ctx.base, current);
1262
- 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;
1263
1602
  }
1264
1603
  return NULL_NODE;
1265
1604
  case "symbol": return parseWellKnownSymbol(ctx.base, current);
@@ -1267,6 +1606,9 @@ async function parseAsync(ctx, depth, current) {
1267
1606
  default: throw new SerovalUnsupportedTypeError(current);
1268
1607
  }
1269
1608
  }
1609
+ async function parseAsync(ctx, depth, current) {
1610
+ return await parseValueAsync(ctx, depth, current);
1611
+ }
1270
1612
  async function parseTopAsync(ctx, current) {
1271
1613
  try {
1272
1614
  return await parseAsync(ctx, 0, current);
@@ -1275,32 +1617,6 @@ async function parseTopAsync(ctx, current) {
1275
1617
  }
1276
1618
  }
1277
1619
  //#endregion
1278
- //#region src/core/plugin.ts
1279
- let SerovalMode = /* @__PURE__ */ function(SerovalMode) {
1280
- SerovalMode[SerovalMode["Vanilla"] = 1] = "Vanilla";
1281
- SerovalMode[SerovalMode["Cross"] = 2] = "Cross";
1282
- return SerovalMode;
1283
- }({});
1284
- function createPlugin(plugin) {
1285
- return plugin;
1286
- }
1287
- function dedupePlugins(deduped, plugins) {
1288
- for (let i = 0, len = plugins.length; i < len; i++) {
1289
- const current = plugins[i];
1290
- if (!deduped.has(current)) {
1291
- deduped.add(current);
1292
- if (current.extends) dedupePlugins(deduped, current.extends);
1293
- }
1294
- }
1295
- }
1296
- function resolvePlugins(plugins) {
1297
- if (plugins) {
1298
- const deduped = /* @__PURE__ */ new Set();
1299
- dedupePlugins(deduped, plugins);
1300
- return [...deduped];
1301
- }
1302
- }
1303
- //#endregion
1304
1620
  //#region src/core/utils/valid-properties.ts
1305
1621
  function isValidKey(key) {
1306
1622
  switch (key) {
@@ -1326,7 +1642,6 @@ function isValidSymbol(symbol) {
1326
1642
  //#endregion
1327
1643
  //#region src/core/context/deserializer.ts
1328
1644
  const DEFAULT_MAX_BASE64_LENGTH = 1e6;
1329
- const MIN_NATIVE_BASE64_LENGTH = 512;
1330
1645
  const MAX_BIGINT_LENGTH = 1e4;
1331
1646
  const MAX_REGEXP_SOURCE_LENGTH = 2e4;
1332
1647
  function applyObjectFlag(obj, flag) {
@@ -1338,68 +1653,48 @@ function applyObjectFlag(obj, flag) {
1338
1653
  }
1339
1654
  }
1340
1655
  const DEFAULT_DEPTH_LIMIT = 1e3;
1341
- function createBaseDeserializerContext(mode, options) {
1342
- var _options$maxBase64Len, _options$features;
1343
- 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;
1344
1658
  if (!Number.isSafeInteger(maxBase64Length) || maxBase64Length < 0) throw new RangeError("maxBase64Length must be a non-negative safe integer");
1345
- const refs = options.refs || /* @__PURE__ */ new Map();
1659
+ const refs = options.refs ?? /* @__PURE__ */ new Map();
1346
1660
  if (!("types" in refs)) Object.assign(refs, { types: /* @__PURE__ */ new Map() });
1347
1661
  return {
1348
- mode,
1349
1662
  plugins: options.plugins,
1350
1663
  refs,
1351
- features: (_options$features = options.features) !== null && _options$features !== void 0 ? _options$features : 127 ^ (options.disabledFeatures || 0),
1664
+ features: options.features ?? 127 ^ (options.disabledFeatures ?? 0),
1352
1665
  depthLimit: options.depthLimit || DEFAULT_DEPTH_LIMIT,
1353
1666
  maxBase64Length
1354
1667
  };
1355
1668
  }
1356
1669
  function createVanillaDeserializerContext(options) {
1357
1670
  return {
1358
- mode: 1,
1359
- base: createBaseDeserializerContext(1, options),
1360
- child: void 0,
1361
- state: { marked: new Set(options.markedRefs) }
1671
+ base: createBaseDeserializerContext(options),
1672
+ marked: new Set(options.markedRefs)
1362
1673
  };
1363
1674
  }
1364
1675
  function createCrossDeserializerContext(options) {
1365
1676
  return {
1366
- mode: 2,
1367
- base: createBaseDeserializerContext(2, options),
1368
- child: void 0
1677
+ base: createBaseDeserializerContext(options),
1678
+ marked: void 0
1369
1679
  };
1370
1680
  }
1371
- var DeserializePluginContext = class {
1372
- constructor(_p, depth) {
1373
- this._p = _p;
1374
- this.depth = depth;
1375
- }
1376
- deserialize(node) {
1377
- return deserialize$1(this._p, this.depth, node);
1378
- }
1379
- };
1380
1681
  function guardIndexedValue(ctx, id) {
1381
- if (id < 0 || !Number.isFinite(id) || !Number.isInteger(id)) throw new SerovalMalformedNodeError({
1682
+ const node = {
1382
1683
  t: 4,
1383
1684
  i: id
1384
- });
1385
- 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);
1386
1688
  }
1387
1689
  function isThennable(value) {
1388
1690
  return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1389
1691
  }
1390
- function assignIndexedValueVanilla(ctx, id, value) {
1391
- guardIndexedValue(ctx.base, id);
1392
- if (ctx.state.marked.has(id)) ctx.base.refs.set(id, value);
1393
- return value;
1394
- }
1395
- function assignIndexedValueCross(ctx, id, value) {
1692
+ function assignIndexedValue$1(ctx, id, value) {
1396
1693
  guardIndexedValue(ctx.base, id);
1397
- ctx.base.refs.set(id, value);
1694
+ const marked = ctx.marked;
1695
+ if (!marked || marked.has(id)) ctx.base.refs.set(id, value);
1398
1696
  return value;
1399
1697
  }
1400
- function assignIndexedValue$1(ctx, id, value) {
1401
- return ctx.mode === 1 ? assignIndexedValueVanilla(ctx, id, value) : assignIndexedValueCross(ctx, id, value);
1402
- }
1403
1698
  function deserializeKnownValue(node, record, key) {
1404
1699
  if (Object.hasOwn(record, key)) return record[key];
1405
1700
  throw new SerovalMalformedNodeError(node);
@@ -1456,7 +1751,8 @@ function deserializeProperties(ctx, depth, node, result) {
1456
1751
  const keys = node.k;
1457
1752
  validateNodeList(node, keys);
1458
1753
  validateNodeList(node, node.v);
1459
- 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]);
1460
1756
  return result;
1461
1757
  }
1462
1758
  function deserializeObject(ctx, depth, node) {
@@ -1470,35 +1766,8 @@ function deserializeDate(ctx, node) {
1470
1766
  }
1471
1767
  function deserializeTemporal(ctx, node) {
1472
1768
  if (!(ctx.base.features & 64)) throw new SerovalUnsupportedNodeError(node);
1473
- let value;
1474
- switch (node.c) {
1475
- case 0:
1476
- value = Temporal.Instant.from(node.s);
1477
- break;
1478
- case 1:
1479
- value = Temporal.Duration.from(node.s);
1480
- break;
1481
- case 2:
1482
- value = Temporal.PlainDate.from(node.s);
1483
- break;
1484
- case 3:
1485
- value = Temporal.PlainDateTime.from(node.s);
1486
- break;
1487
- case 4:
1488
- value = Temporal.PlainMonthDay.from(node.s);
1489
- break;
1490
- case 5:
1491
- value = Temporal.PlainTime.from(node.s);
1492
- break;
1493
- case 6:
1494
- value = Temporal.PlainYearMonth.from(node.s);
1495
- break;
1496
- case 7:
1497
- value = Temporal.ZonedDateTime.from(node.s);
1498
- break;
1499
- default: throw new SerovalMalformedNodeError(node);
1500
- }
1501
- 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));
1502
1771
  }
1503
1772
  function deserializeRegExp(ctx, node) {
1504
1773
  if (ctx.base.features & 32) {
@@ -1524,32 +1793,15 @@ function deserializeMap(ctx, depth, node) {
1524
1793
  function deserializeArrayBuffer(ctx, node) {
1525
1794
  if (typeof node.s !== "string") throw new SerovalMalformedNodeError(node);
1526
1795
  if (node.s.length > ctx.base.maxBase64Length) throw new RangeError("ArrayBuffer exceeds maxBase64Length (" + ctx.base.maxBase64Length + ")");
1527
- const source = deserializeString(node.s);
1528
- let buffer;
1529
- if (source.length < MIN_NATIVE_BASE64_LENGTH || typeof Buffer === "undefined") buffer = ARRAY_BUFFER_CONSTRUCTOR(source);
1530
- else {
1531
- const decoded = atob(source);
1532
- buffer = new ArrayBuffer(decoded.length);
1533
- Buffer.from(buffer).write(decoded, "latin1");
1534
- }
1796
+ const buffer = decodeArrayBuffer(deserializeString(node.s));
1535
1797
  return assignIndexedValue$1(ctx, node.i, buffer);
1536
1798
  }
1537
- function deserializeTypedArray(ctx, depth, node) {
1538
- var _node$b;
1539
- const construct = getTypedArrayConstructor(node.c);
1799
+ function deserializeView(ctx, depth, node, construct) {
1540
1800
  const source = deserialize$1(ctx, depth, node.f);
1541
1801
  if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1542
- const offset = (_node$b = node.b) !== null && _node$b !== void 0 ? _node$b : 0;
1802
+ const offset = node.b ?? 0;
1543
1803
  if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1544
- return assignIndexedValue$1(ctx, node.i, new construct(source, offset, node.l));
1545
- }
1546
- function deserializeDataView(ctx, depth, node) {
1547
- var _node$b2;
1548
- const source = deserialize$1(ctx, depth, node.f);
1549
- if (!(source instanceof ArrayBuffer)) throw new SerovalMalformedNodeError(node);
1550
- const offset = (_node$b2 = node.b) !== null && _node$b2 !== void 0 ? _node$b2 : 0;
1551
- if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1552
- 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));
1553
1805
  }
1554
1806
  function deserializeDictionary(ctx, depth, node, result) {
1555
1807
  if (node.p) {
@@ -1583,7 +1835,7 @@ function deserializePlugin(ctx, depth, node) {
1583
1835
  const tag = deserializeString(node.c);
1584
1836
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
1585
1837
  const plugin = currentPlugins[i];
1586
- 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 }));
1587
1839
  }
1588
1840
  }
1589
1841
  throw new SerovalMissingPluginError(node.c);
@@ -1591,6 +1843,7 @@ function deserializePlugin(ctx, depth, node) {
1591
1843
  function deserializePromiseConstructor(ctx, node) {
1592
1844
  const value = assignIndexedValue$1(ctx, node.i, assignIndexedValue$1(ctx, node.s, PROMISE_CONSTRUCTOR()).p);
1593
1845
  assignNodeType(ctx, node.s, 22);
1846
+ ctx.base.pending?.add(node.s);
1594
1847
  return value;
1595
1848
  }
1596
1849
  function deserializePromiseFulfill(ctx, depth, node) {
@@ -1601,6 +1854,7 @@ function deserializePromiseFulfill(ctx, depth, node) {
1601
1854
  if (isThennable(deserialized)) throw new SerovalMalformedNodeError(node.a[1]);
1602
1855
  if (node.t === 23) deferred.s(deserialized);
1603
1856
  else deferred.f(deserialized);
1857
+ ctx.base.pending?.delete(node.i);
1604
1858
  return;
1605
1859
  }
1606
1860
  throw new SerovalMissingInstanceError("Promise");
@@ -1618,37 +1872,21 @@ function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1618
1872
  return streamToAsyncIterable(source);
1619
1873
  }
1620
1874
  function deserializeStreamConstructor(ctx, depth, node) {
1621
- const result = assignIndexedValue$1(ctx, node.i, createStream());
1875
+ const result = assignIndexedValue$1(ctx, node.i, new Stream(node.l === 1 ? 1 : void 0));
1622
1876
  assignNodeType(ctx, node.i, 31);
1877
+ ctx.base.pending?.add(node.i);
1623
1878
  const items = node.a;
1624
1879
  validateNodeList(node, items);
1625
1880
  const len = items.length;
1626
1881
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1627
1882
  return result;
1628
1883
  }
1629
- function deserializeStreamNext(ctx, depth, node) {
1630
- const deferred = ctx.base.refs.get(node.i);
1631
- if (deferred) {
1632
- validateNodeType(ctx, node, node.i, 31);
1633
- deferred.next(deserialize$1(ctx, depth, node.f));
1634
- return;
1635
- }
1636
- throw new SerovalMissingInstanceError("Stream");
1637
- }
1638
- function deserializeStreamThrow(ctx, depth, node) {
1639
- const deferred = ctx.base.refs.get(node.i);
1640
- if (deferred) {
1641
- validateNodeType(ctx, node, node.i, 31);
1642
- deferred.throw(deserialize$1(ctx, depth, node.f));
1643
- return;
1644
- }
1645
- throw new SerovalMissingInstanceError("Stream");
1646
- }
1647
- function deserializeStreamReturn(ctx, depth, node) {
1884
+ function deserializeStreamCall(ctx, depth, node, method) {
1648
1885
  const deferred = ctx.base.refs.get(node.i);
1649
1886
  if (deferred) {
1650
1887
  validateNodeType(ctx, node, node.i, 31);
1651
- 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);
1652
1890
  return;
1653
1891
  }
1654
1892
  throw new SerovalMissingInstanceError("Stream");
@@ -1667,6 +1905,7 @@ function deserializeSequence(ctx, depth, node) {
1667
1905
  const size = node.a.length;
1668
1906
  if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1669
1907
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1908
+ assignNodeType(ctx, node.i, 35);
1670
1909
  for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1671
1910
  return result;
1672
1911
  }
@@ -1691,8 +1930,8 @@ function deserialize$1(ctx, depth, node) {
1691
1930
  case 8: return deserializeMap(ctx, depth, node);
1692
1931
  case 19: return deserializeArrayBuffer(ctx, node);
1693
1932
  case 16:
1694
- case 15: return deserializeTypedArray(ctx, depth, node);
1695
- 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);
1696
1935
  case 14: return deserializeAggregateError(ctx, depth, node);
1697
1936
  case 13: return deserializeError(ctx, depth, node);
1698
1937
  case 12: return deserializePromise(ctx, depth, node);
@@ -1705,9 +1944,9 @@ function deserialize$1(ctx, depth, node) {
1705
1944
  case 28: return deserializeIteratorFactoryInstance(ctx, depth, node);
1706
1945
  case 30: return deserializeAsyncIteratorFactoryInstance(ctx, depth, node);
1707
1946
  case 31: return deserializeStreamConstructor(ctx, depth, node);
1708
- case 32: return deserializeStreamNext(ctx, depth, node);
1709
- case 33: return deserializeStreamThrow(ctx, depth, node);
1710
- 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");
1711
1950
  case 27: return deserializeIteratorFactory(ctx, depth, node);
1712
1951
  case 29: return deserializeAsyncIteratorFactory(ctx, depth, node);
1713
1952
  case 35: return deserializeSequence(ctx, depth, node);
@@ -1722,11 +1961,31 @@ function deserializeTop(ctx, node) {
1722
1961
  throw new SerovalDeserializationError(error);
1723
1962
  }
1724
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
+ }
1725
1985
  //#endregion
1726
1986
  //#region src/core/function-string.ts
1727
1987
  const RETURN = () => T;
1728
- const SERIALIZED_RETURN = /* @__PURE__ */ RETURN.toString();
1729
- const IS_MODERN = /* @__PURE__ */ /=>/.test(SERIALIZED_RETURN);
1988
+ const IS_MODERN = /* @__PURE__ */ (/* @__PURE__ */ RETURN.toString()).includes("=>");
1730
1989
  function createFunction(parameters, body) {
1731
1990
  if (IS_MODERN) return (parameters.length === 1 ? parameters[0] : "(" + parameters.join(",") + ")") + "=>" + (body.startsWith("{") ? "(" + body + ")" : body);
1732
1991
  return "function(" + parameters.join(",") + "){return " + body + "}";
@@ -1754,10 +2013,13 @@ function getIdentifier(index) {
1754
2013
  }
1755
2014
  //#endregion
1756
2015
  //#region src/core/utils/is-valid-identifier.ts
1757
- const IDENTIFIER_CHECK = /^[$A-Z_][0-9A-Z_$]*$/i;
1758
2016
  function isValidIdentifier(name) {
1759
- const char = name[0];
1760
- 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;
1761
2023
  }
1762
2024
  //#endregion
1763
2025
  //#region src/core/context/serializer.ts
@@ -1770,51 +2032,32 @@ function getAssignmentExpression(assignment) {
1770
2032
  case 4: return "Object.defineProperty(" + assignment.s + ",\"__proto__\",{value:" + assignment.k + ",configurable:!0,enumerable:!0,writable:!0})";
1771
2033
  }
1772
2034
  }
1773
- function mergeAssignments(assignments) {
1774
- const newAssignments = [];
1775
- let current = assignments[0];
1776
- for (let i = 1, len = assignments.length, item, prev = current; i < len; i++) {
1777
- item = assignments[i];
1778
- if (item.t === 0 && item.v === prev.v) current = {
1779
- t: 0,
1780
- s: item.s,
1781
- k: void 0,
1782
- v: getAssignmentExpression(current)
1783
- };
1784
- else if (item.t === 2 && item.s === prev.s) current = {
1785
- t: 2,
1786
- s: getAssignmentExpression(current),
1787
- k: item.k,
1788
- v: item.v
1789
- };
1790
- else if (item.t === 1 && item.s === prev.s) current = {
1791
- t: 1,
1792
- s: getAssignmentExpression(current),
1793
- k: void 0,
1794
- v: item.v
1795
- };
1796
- else if (item.t === 3 && item.s === prev.s) current = {
1797
- t: 3,
1798
- s: getAssignmentExpression(current),
1799
- k: item.k,
1800
- v: void 0
1801
- };
2035
+ const MAX_ASSIGNMENT_CHAIN_LENGTH = 100;
2036
+ function resolveAssignments(assignments) {
2037
+ if (!assignments.length) return void 0;
2038
+ let previous = assignments[0];
2039
+ let expression = getAssignmentExpression(previous);
2040
+ let result = "";
2041
+ let chainLength = 1;
2042
+ for (let index = 1, length = assignments.length; index < length; index++) {
2043
+ const assignment = assignments[index];
2044
+ if (chainLength === MAX_ASSIGNMENT_CHAIN_LENGTH) {
2045
+ result += expression + ",";
2046
+ expression = getAssignmentExpression(assignment);
2047
+ chainLength = 0;
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 + ")";
1802
2052
  else {
1803
- newAssignments.push(current);
1804
- current = item;
2053
+ result += expression + ",";
2054
+ expression = getAssignmentExpression(assignment);
2055
+ chainLength = 0;
1805
2056
  }
1806
- prev = item;
1807
- }
1808
- newAssignments.push(current);
1809
- return newAssignments;
1810
- }
1811
- function resolveAssignments(assignments) {
1812
- if (assignments.length) {
1813
- let result = "";
1814
- const merged = mergeAssignments(assignments);
1815
- for (let i = 0, len = merged.length; i < len; i++) result += getAssignmentExpression(merged[i]) + ",";
1816
- return result;
2057
+ chainLength++;
2058
+ previous = assignment;
1817
2059
  }
2060
+ return result + expression + ",";
1818
2061
  }
1819
2062
  const NULL_CONSTRUCTOR = "Object.create(null)";
1820
2063
  const SET_CONSTRUCTOR = "new Set";
@@ -1832,42 +2075,34 @@ function createBaseSerializerContext(mode, options) {
1832
2075
  mode,
1833
2076
  plugins: options.plugins,
1834
2077
  features: options.features,
1835
- marked: new Set(options.markedRefs),
2078
+ marked: Array.isArray(options.markedRefs) ? new Set(options.markedRefs) : options.markedRefs,
1836
2079
  stack: [],
1837
2080
  flags: [],
1838
- assignments: []
2081
+ assignments: [],
2082
+ assignAll: mode === 2 && !options.assignSharedRefsOnly
1839
2083
  };
1840
2084
  }
1841
2085
  function createVanillaSerializerState() {
1842
2086
  return {
1843
2087
  valid: /* @__PURE__ */ new Map(),
1844
- vars: []
2088
+ vars: [],
2089
+ sentinels: /* @__PURE__ */ new Set()
1845
2090
  };
1846
2091
  }
1847
2092
  function createVanillaSerializerContext(options) {
1848
2093
  return {
1849
2094
  mode: 1,
1850
2095
  base: createBaseSerializerContext(1, options),
1851
- state: createVanillaSerializerState(),
1852
- child: void 0
2096
+ state: createVanillaSerializerState()
1853
2097
  };
1854
2098
  }
1855
2099
  function createCrossSerializerContext(options) {
1856
2100
  return {
1857
2101
  mode: 2,
1858
2102
  base: createBaseSerializerContext(2, options),
1859
- state: options,
1860
- child: void 0
2103
+ state: options
1861
2104
  };
1862
2105
  }
1863
- var SerializePluginContext = class {
1864
- constructor(_p) {
1865
- this._p = _p;
1866
- }
1867
- serialize(node) {
1868
- return serialize$1(this._p, node);
1869
- }
1870
- };
1871
2106
  /**
1872
2107
  * Creates the reference param (identifier) from the given reference ID
1873
2108
  * Calling this function means the value has been referenced somewhere
@@ -1975,7 +2210,7 @@ function createArrayAssign(ctx, ref, index, value) {
1975
2210
  createAssignment(ctx.base, getRefParam(ctx, ref) + "[" + index + "]", value);
1976
2211
  }
1977
2212
  function createObjectAssign(ctx, ref, key, value) {
1978
- if (!isValidKey(key)) {
2213
+ if (key === "__proto__") {
1979
2214
  ctx.base.assignments.push({
1980
2215
  t: 4,
1981
2216
  s: getRefParam(ctx, ref),
@@ -1993,17 +2228,42 @@ function createSequenceAssign(ctx, ref, index, value) {
1993
2228
  * Checks if the value is in the stack. Stack here is a reference
1994
2229
  * structure to know if a object is to be accessed in a TDZ.
1995
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
+ }
1996
2240
  function isIndexedValueInStack(ctx, node) {
1997
2241
  return node.t === 4 && ctx.stack.includes(node.i);
1998
2242
  }
1999
2243
  /**
2244
+ * Checks if the node, or any node inside it, is read from more than one
2245
+ * place. Such a node must not be created inside a deferred assignment,
2246
+ * because the places that read it may run before the assignment does.
2247
+ */
2248
+ function hasMarkedNode(ctx, node) {
2249
+ if (Array.isArray(node)) {
2250
+ for (let i = 0, len = node.length; i < len; i++) if (hasMarkedNode(ctx, node[i])) return true;
2251
+ return false;
2252
+ }
2253
+ if (node == null || typeof node !== "object") return false;
2254
+ const current = node;
2255
+ if (current.t !== 4 && typeof current.i === "number" && isSerializerRefMarked(ctx, current.i)) return true;
2256
+ for (const key in current) if (hasMarkedNode(ctx, current[key])) return true;
2257
+ return false;
2258
+ }
2259
+ /**
2000
2260
  * Produces an assignment expression. `id` generates a reference
2001
2261
  * parameter (through `getRefParam`) and has the option to
2002
2262
  * return the reference parameter directly or assign a value to
2003
2263
  * it.
2004
2264
  */
2005
2265
  function assignIndexedValue(ctx, index, value) {
2006
- if (ctx.mode === 1 && !isSerializerRefMarked(ctx.base, index)) return value;
2266
+ if (!ctx.base.assignAll && !isSerializerRefMarked(ctx.base, index)) return value;
2007
2267
  /**
2008
2268
  * In cross-reference, we have to assume that
2009
2269
  * every reference are going to be referenced
@@ -2011,12 +2271,13 @@ function assignIndexedValue(ctx, index, value) {
2011
2271
  * all of it into the reference array.
2012
2272
  *
2013
2273
  * otherwise in vanilla, we only do this if it
2014
- * is actually referenced
2274
+ * is actually referenced. `assignSharedRefsOnly` gives cross-reference
2275
+ * output the vanilla behavior.
2015
2276
  */
2016
2277
  return getRefParam(ctx, index) + "=" + value;
2017
2278
  }
2018
2279
  function serializeReference(node) {
2019
- return "__SEROVAL_REFS__.get(\"" + node.s + "\")";
2280
+ return REFERENCES_KEY + ".get(\"" + node.s + "\")";
2020
2281
  }
2021
2282
  function serializeArrayItem(ctx, id, item, index) {
2022
2283
  if (item) {
@@ -2050,16 +2311,15 @@ function serializeArray(ctx, node) {
2050
2311
  }
2051
2312
  function serializeProperty(ctx, source, key, val) {
2052
2313
  if (typeof key === "string") {
2053
- const check = Number(key);
2054
- const isIdentifier = check >= 0 && check.toString() === key || isValidIdentifier(key);
2314
+ const kind = getKeyKind(key);
2055
2315
  if (isIndexedValueInStack(ctx.base, val)) {
2056
2316
  const refParam = getRefParam(ctx, val.i);
2057
2317
  markSerializerRef(ctx.base, source.i);
2058
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, refParam);
2059
- 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);
2060
2320
  return "";
2061
2321
  }
2062
- if (isValidKey(key)) return (isIdentifier ? key : "\"" + key + "\"") + ":" + serialize$1(ctx, val);
2322
+ if (key !== "__proto__") return (kind === 0 ? "\"" + key + "\"" : key) + ":" + serialize$1(ctx, val);
2063
2323
  return "[\"" + key + "\"]:" + serialize$1(ctx, val);
2064
2324
  }
2065
2325
  return "[" + serialize$1(ctx, key) + "]:" + serialize$1(ctx, val);
@@ -2071,7 +2331,7 @@ function serializeProperties(ctx, source, record) {
2071
2331
  const values = record.v;
2072
2332
  ctx.base.stack.push(source.i);
2073
2333
  let result = serializeProperty(ctx, source, keys[0], values[0]);
2074
- for (let i = 1, item = result; i < len; i++) {
2334
+ for (let i = 1, item; i < len; i++) {
2075
2335
  item = serializeProperty(ctx, source, keys[i], values[i]);
2076
2336
  result += (item && result && ",") + item;
2077
2337
  }
@@ -2092,18 +2352,14 @@ function serializeWithObjectAssign(ctx, source, value, serialized) {
2092
2352
  function serializeStringKeyAssignment(ctx, source, mainAssignments, key, value) {
2093
2353
  const base = ctx.base;
2094
2354
  const serialized = serialize$1(ctx, value);
2095
- const check = Number(key);
2096
- const isIdentifier = check >= 0 && check.toString() === key || isValidIdentifier(key);
2097
- if (isIndexedValueInStack(base, value)) {
2098
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
2099
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
2100
- } else {
2101
- const parentAssignment = base.assignments;
2102
- base.assignments = mainAssignments;
2103
- if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
2104
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
2105
- base.assignments = parentAssignment;
2106
- }
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);
2107
2363
  }
2108
2364
  function serializeAssignment(ctx, source, mainAssignments, key, value) {
2109
2365
  if (typeof key === "string") serializeStringKeyAssignment(ctx, source, mainAssignments, key, value);
@@ -2134,7 +2390,7 @@ function serializeAssignments(ctx, source, node) {
2134
2390
  function serializeDictionary(ctx, node, init) {
2135
2391
  if (node.p) {
2136
2392
  const base = ctx.base;
2137
- 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);
2138
2394
  else {
2139
2395
  markSerializerRef(base, node.i);
2140
2396
  const assignments = serializeAssignments(ctx, node, node.p);
@@ -2150,18 +2406,8 @@ function serializeNullConstructor(ctx, node) {
2150
2406
  function serializeDate(node) {
2151
2407
  return "new Date(\"" + node.s + "\")";
2152
2408
  }
2153
- const TEMPORAL_CONSTRUCTOR = {
2154
- [0]: "Temporal.Instant",
2155
- [1]: "Temporal.Duration",
2156
- [2]: "Temporal.PlainDate",
2157
- [3]: "Temporal.PlainDateTime",
2158
- [4]: "Temporal.PlainMonthDay",
2159
- [5]: "Temporal.PlainTime",
2160
- [6]: "Temporal.PlainYearMonth",
2161
- [7]: "Temporal.ZonedDateTime"
2162
- };
2163
2409
  function serializeTemporal(ctx, node) {
2164
- 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 + "\")";
2165
2411
  throw new SerovalUnsupportedNodeError(node);
2166
2412
  }
2167
2413
  function serializeRegExp(ctx, node) {
@@ -2188,7 +2434,7 @@ function serializeSet(ctx, node) {
2188
2434
  if (size > 0) {
2189
2435
  ctx.base.stack.push(id);
2190
2436
  let result = serializeSetItem(ctx, id, items[0]);
2191
- for (let i = 1, item = result; i < size; i++) {
2437
+ for (let i = 1, item; i < size; i++) {
2192
2438
  item = serializeSetItem(ctx, id, items[i]);
2193
2439
  result += (item && result && ",") + item;
2194
2440
  }
@@ -2197,7 +2443,7 @@ function serializeSet(ctx, node) {
2197
2443
  }
2198
2444
  return serialized;
2199
2445
  }
2200
- function serializeMapEntry(ctx, id, key, val, sentinel) {
2446
+ function serializeMapEntry(ctx, id, key, val, getSentinel) {
2201
2447
  const base = ctx.base;
2202
2448
  if (isIndexedValueInStack(base, key)) {
2203
2449
  const keyRef = getRefParam(ctx, key.i);
@@ -2206,7 +2452,9 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
2206
2452
  createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
2207
2453
  return "";
2208
2454
  }
2209
- if (val.t !== 4 && val.i != null && isSerializerRefMarked(base, val.i)) {
2455
+ if (val.t !== 4 && val.i != null && hasMarkedNode(base, val)) {
2456
+ markSerializerRef(base, val.i);
2457
+ const sentinel = getSentinel();
2210
2458
  const serialized = "(" + serialize$1(ctx, val) + ",[" + sentinel + "," + sentinel + "])";
2211
2459
  createSetAssignment(ctx, id, keyRef, getRefParam(ctx, val.i));
2212
2460
  createDeleteAssignment(ctx, id, sentinel);
@@ -2221,7 +2469,9 @@ function serializeMapEntry(ctx, id, key, val, sentinel) {
2221
2469
  if (isIndexedValueInStack(base, val)) {
2222
2470
  const valueRef = getRefParam(ctx, val.i);
2223
2471
  markSerializerRef(base, id);
2224
- if (key.t !== 4 && key.i != null && isSerializerRefMarked(base, key.i)) {
2472
+ if (key.t !== 4 && key.i != null && hasMarkedNode(base, key)) {
2473
+ markSerializerRef(base, key.i);
2474
+ const sentinel = getSentinel();
2225
2475
  const serialized = "(" + serialize$1(ctx, key) + ",[" + sentinel + "," + sentinel + "])";
2226
2476
  createSetAssignment(ctx, id, getRefParam(ctx, key.i), valueRef);
2227
2477
  createDeleteAssignment(ctx, id, sentinel);
@@ -2241,20 +2491,27 @@ function serializeMap(ctx, node) {
2241
2491
  const size = keys.length;
2242
2492
  const id = node.i;
2243
2493
  const sentinel = node.f;
2244
- 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
+ };
2245
2502
  const base = ctx.base;
2246
2503
  if (size > 0) {
2247
2504
  const vals = node.e.v;
2248
2505
  base.stack.push(id);
2249
- let result = serializeMapEntry(ctx, id, keys[0], vals[0], sentinelId);
2250
- for (let i = 1, item = result; i < size; i++) {
2251
- 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);
2252
2509
  result += (item && result && ",") + item;
2253
2510
  }
2254
2511
  base.stack.pop();
2255
2512
  if (result) serialized += "([" + result + "])";
2256
2513
  }
2257
- if (sentinel.t === 26) {
2514
+ if (ctx.mode === 2 && sentinel.t === 26) {
2258
2515
  markSerializerRef(base, sentinel.i);
2259
2516
  serialized = "(" + serialize$1(ctx, sentinel) + "," + serialized + ")";
2260
2517
  }
@@ -2263,11 +2520,8 @@ function serializeMap(ctx, node) {
2263
2520
  function serializeArrayBuffer(ctx, node) {
2264
2521
  return getConstructor(ctx, node.f) + "(\"" + node.s + "\")";
2265
2522
  }
2266
- function serializeTypedArray(ctx, node) {
2267
- return "new " + node.c + "(" + serialize$1(ctx, node.f) + "," + node.b + "," + node.l + ")";
2268
- }
2269
- function serializeDataView(ctx, node) {
2270
- 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 + ")";
2271
2525
  }
2272
2526
  function serializeAggregateError(ctx, node) {
2273
2527
  const id = node.i;
@@ -2307,11 +2561,7 @@ function serializePromiseConstructor(ctx, node) {
2307
2561
  if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2308
2562
  return "(" + assignIndexedValue(ctx, node.s, getConstructor(ctx, node.f) + "()") + ").p";
2309
2563
  }
2310
- function serializePromiseResolve(ctx, node) {
2311
- if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2312
- return getConstructor(ctx, node.a[0]) + "(" + getRefParam(ctx, node.i) + "," + serialize$1(ctx, node.a[1]) + ")";
2313
- }
2314
- function serializePromiseReject(ctx, node) {
2564
+ function serializePromiseResult(ctx, node) {
2315
2565
  if (ctx.mode === 1) throw new SerovalUnsupportedNodeError(node);
2316
2566
  return getConstructor(ctx, node.a[0]) + "(" + getRefParam(ctx, node.i) + "," + serialize$1(ctx, node.a[1]) + ")";
2317
2567
  }
@@ -2319,10 +2569,7 @@ function serializePlugin(ctx, node) {
2319
2569
  const currentPlugins = ctx.base.plugins;
2320
2570
  if (currentPlugins) for (let i = 0, len = currentPlugins.length; i < len; i++) {
2321
2571
  const plugin = currentPlugins[i];
2322
- if (plugin.tag === node.c) {
2323
- if (ctx.child == null) ctx.child = new SerializePluginContext(ctx);
2324
- return plugin.serialize(node.s, ctx.child, { id: node.i });
2325
- }
2572
+ if (plugin.tag === node.c) return plugin.serialize(node.s, { serialize: (current) => serialize$1(ctx, current) }, { id: node.i });
2326
2573
  }
2327
2574
  throw new SerovalMissingPluginError(node.c);
2328
2575
  }
@@ -2359,11 +2606,8 @@ function serializeAsyncIteratorFactory(ctx, node) {
2359
2606
  if (result) return result + iterator + ")";
2360
2607
  return iterator;
2361
2608
  }
2362
- function serializeAsyncIteratorFactoryInstance(ctx, node) {
2363
- return getConstructor(ctx, node.a[0]) + "(" + serialize$1(ctx, node.a[1]) + ")";
2364
- }
2365
2609
  function serializeStreamConstructor(ctx, node) {
2366
- 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)" : "()"));
2367
2611
  const len = node.a.length;
2368
2612
  if (len) {
2369
2613
  let values = serialize$1(ctx, node.a[0]);
@@ -2372,14 +2616,8 @@ function serializeStreamConstructor(ctx, node) {
2372
2616
  }
2373
2617
  return result;
2374
2618
  }
2375
- function serializeStreamNext(ctx, node) {
2376
- return getRefParam(ctx, node.i) + ".next(" + serialize$1(ctx, node.f) + ")";
2377
- }
2378
- function serializeStreamThrow(ctx, node) {
2379
- return getRefParam(ctx, node.i) + ".throw(" + serialize$1(ctx, node.f) + ")";
2380
- }
2381
- function serializeStreamReturn(ctx, node) {
2382
- 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) + ")";
2383
2621
  }
2384
2622
  function serializeSequenceItem(ctx, id, index, item) {
2385
2623
  const base = ctx.base;
@@ -2397,7 +2635,7 @@ function serializeSequence(ctx, node) {
2397
2635
  if (size > 0) {
2398
2636
  ctx.base.stack.push(id);
2399
2637
  let result = serializeSequenceItem(ctx, id, 0, items[0]);
2400
- for (let i = 1, item = result; i < size; i++) {
2638
+ for (let i = 1, item; i < size; i++) {
2401
2639
  item = serializeSequenceItem(ctx, id, i, items[i]);
2402
2640
  result += (item && result && ",") + item;
2403
2641
  }
@@ -2419,8 +2657,8 @@ function serializeAssignable(ctx, node) {
2419
2657
  case 8: return serializeMap(ctx, node);
2420
2658
  case 19: return serializeArrayBuffer(ctx, node);
2421
2659
  case 16:
2422
- case 15: return serializeTypedArray(ctx, node);
2423
- case 20: return serializeDataView(ctx, node);
2660
+ case 15:
2661
+ case 20: return serializeView(ctx, node);
2424
2662
  case 14: return serializeAggregateError(ctx, node);
2425
2663
  case 13: return serializeError(ctx, node);
2426
2664
  case 12: return serializePromise(ctx, node);
@@ -2440,20 +2678,20 @@ function serialize$1(ctx, node) {
2440
2678
  case 1: return "\"" + node.s + "\"";
2441
2679
  case 3: return node.s + "n";
2442
2680
  case 4: return getRefParam(ctx, node.i);
2443
- case 23: return serializePromiseResolve(ctx, node);
2444
- case 24: return serializePromiseReject(ctx, node);
2681
+ case 23:
2682
+ case 24: return serializePromiseResult(ctx, node);
2445
2683
  case 27: return serializeIteratorFactory(ctx, node);
2446
- case 28: return serializeIteratorFactoryInstance(ctx, node);
2684
+ case 28:
2685
+ case 30: return serializeIteratorFactoryInstance(ctx, node);
2447
2686
  case 29: return serializeAsyncIteratorFactory(ctx, node);
2448
- case 30: return serializeAsyncIteratorFactoryInstance(ctx, node);
2449
2687
  case 31: return serializeStreamConstructor(ctx, node);
2450
- case 32: return serializeStreamNext(ctx, node);
2451
- case 33: return serializeStreamThrow(ctx, node);
2452
- 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");
2453
2691
  default: return assignIndexedValue(ctx, node.i, serializeAssignable(ctx, node));
2454
2692
  }
2455
2693
  }
2456
- function serializeTopVanilla(ctx, tree) {
2694
+ function serializeVanilla(ctx, tree) {
2457
2695
  const result = serialize$1(ctx, tree);
2458
2696
  if (tree.i != null && ctx.state.vars.length) {
2459
2697
  const patches = resolvePatches(ctx.base);
@@ -2464,12 +2702,18 @@ function serializeTopVanilla(ctx, tree) {
2464
2702
  if (!result.startsWith(index + "=")) body = index + "=" + body;
2465
2703
  body = "(" + body + ")";
2466
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
+ }
2467
2711
  return "(" + createFunction(ctx.state.vars, body) + ")()";
2468
2712
  }
2469
2713
  if (tree.t === 10) return "(" + result + ")";
2470
2714
  return result;
2471
2715
  }
2472
- function serializeTopCross(ctx, tree) {
2716
+ function serializeCross(ctx, tree) {
2473
2717
  const result = serialize$1(ctx, tree);
2474
2718
  const id = tree.i;
2475
2719
  if (id == null) return result;
@@ -2477,7 +2721,11 @@ function serializeTopCross(ctx, tree) {
2477
2721
  const ref = getRefParam(ctx, id);
2478
2722
  const scopeId = ctx.state.scopeId;
2479
2723
  const params = scopeId == null ? "" : "$R";
2480
- 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
+ }
2481
2729
  if (params === "") {
2482
2730
  if (tree.t === 10 && !patches) return "(" + body + ")";
2483
2731
  return body;
@@ -2485,76 +2733,35 @@ function serializeTopCross(ctx, tree) {
2485
2733
  const args = scopeId == null ? "()" : "($R[\"" + serializeString(scopeId) + "\"])";
2486
2734
  return "(" + createFunction([params], body) + ")" + args;
2487
2735
  }
2488
- //#endregion
2489
- //#region src/core/context/sync-parser.ts
2490
- function createSyncParserContext(mode, options) {
2491
- return {
2492
- type: 1,
2493
- base: createBaseParserContext(mode, options),
2494
- child: void 0
2495
- };
2736
+ function wrapSerializationError(error) {
2737
+ return error instanceof SerovalSerializationError ? error : new SerovalSerializationError(error);
2496
2738
  }
2497
- var SyncParsePluginContext = class {
2498
- constructor(_p, depth) {
2499
- this._p = _p;
2500
- this.depth = depth;
2501
- }
2502
- parse(current) {
2503
- return parseSOS(this._p, this.depth, current);
2504
- }
2505
- };
2506
- var StreamParsePluginContext = class {
2507
- constructor(_p, depth) {
2508
- this._p = _p;
2509
- this.depth = depth;
2510
- }
2511
- parse(current) {
2512
- return parseSOS(this._p, this.depth, current);
2513
- }
2514
- parseWithError(current) {
2515
- return parseWithError(this._p, this.depth, current);
2516
- }
2517
- isAlive() {
2518
- return this._p.state.alive;
2519
- }
2520
- pushPendingState() {
2521
- pushPendingState(this._p);
2522
- }
2523
- popPendingState() {
2524
- popPendingState(this._p);
2525
- }
2526
- onParse(node) {
2527
- onParse(this._p, node);
2528
- }
2529
- onError(error) {
2530
- onError(this._p, error);
2739
+ function serializeTopVanilla(ctx, tree) {
2740
+ try {
2741
+ return serializeVanilla(ctx, tree);
2742
+ } catch (error) {
2743
+ throw wrapSerializationError(error);
2531
2744
  }
2532
- addCleanup(callback) {
2533
- 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);
2534
2751
  }
2535
- };
2536
- function createStreamParserState(options) {
2537
- return {
2538
- alive: true,
2539
- pending: 0,
2540
- initial: true,
2541
- buffer: [],
2542
- onParse: options.onParse,
2543
- onError: options.onError,
2544
- onDone: options.onDone,
2545
- cleanups: []
2546
- };
2547
2752
  }
2548
- function createStreamParserContext(options) {
2753
+ //#endregion
2754
+ //#region src/core/context/sync-parser.ts
2755
+ function createSyncParserContext(options) {
2549
2756
  return {
2550
- type: 2,
2551
- base: createBaseParserContext(2, options),
2552
- state: createStreamParserState(options)
2757
+ type: 1,
2758
+ base: createBaseParserContext(options)
2553
2759
  };
2554
2760
  }
2555
2761
  function parseItems(ctx, depth, current) {
2556
- const nodes = [];
2557
- 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]);
2558
2765
  else nodes[i] = 0;
2559
2766
  return nodes;
2560
2767
  }
@@ -2562,20 +2769,22 @@ function parseArray(ctx, depth, id, current) {
2562
2769
  return createArrayNode(id, current, parseItems(ctx, depth, current));
2563
2770
  }
2564
2771
  function parseProperties(ctx, depth, properties) {
2565
- const entries = Object.entries(properties);
2566
- const keyNodes = [];
2567
- const valueNodes = [];
2568
- for (let i = 0, len = entries.length; i < len; i++) {
2569
- keyNodes.push(serializeString(entries[i][0]));
2570
- 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]);
2571
2780
  }
2572
2781
  if (SYM_ITERATOR in properties) {
2573
2782
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ITERATOR));
2574
- valueNodes.push(createIteratorFactoryInstanceNode(parseIteratorFactory(ctx.base), parseSOS(ctx, depth, createSequenceFromIterable(properties))));
2783
+ valueNodes.push(createIteratorFactoryInstanceNode(28, parseIteratorFactory(ctx.base), parseSOS(ctx, depth, createSequenceFromIterable(properties))));
2575
2784
  }
2576
2785
  if (SYM_ASYNC_ITERATOR in properties) {
2577
2786
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_ASYNC_ITERATOR));
2578
- 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)));
2579
2788
  }
2580
2789
  if (SYM_TO_STRING_TAG in properties) {
2581
2790
  keyNodes.push(parseWellKnownSymbol(ctx.base, SYM_TO_STRING_TAG));
@@ -2590,187 +2799,111 @@ function parseProperties(ctx, depth, properties) {
2590
2799
  v: valueNodes
2591
2800
  };
2592
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
+ }
2593
2808
  function parsePlainObject(ctx, depth, id, current, empty) {
2594
2809
  return createObjectNode(id, current, empty, parseProperties(ctx, depth, current));
2595
2810
  }
2596
2811
  function parseBoxed(ctx, depth, id, current) {
2597
2812
  return createBoxedNode(id, parseSOS(ctx, depth, current.valueOf()));
2598
2813
  }
2599
- function parseTypedArray(ctx, depth, id, current) {
2600
- current = getArrayBufferView(ctx.base, current);
2601
- return createTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2602
- }
2603
- function parseBigIntTypedArray(ctx, depth, id, current) {
2814
+ function parseView(ctx, depth, type, id, current) {
2604
2815
  current = getArrayBufferView(ctx.base, current);
2605
- return createBigIntTypedArrayNode(id, current, parseSOS(ctx, depth, current.buffer));
2606
- }
2607
- function parseDataView(ctx, depth, id, current) {
2608
- current = getArrayBufferView(ctx.base, current);
2609
- return createDataViewNode(id, current, parseSOS(ctx, depth, current.buffer));
2610
- }
2611
- function parseError(ctx, depth, id, current) {
2612
- const options = getErrorOptions(current, ctx.base.features);
2613
- return createErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
2816
+ return createViewNode(type, id, current, parseSOS(ctx, depth, current.buffer));
2614
2817
  }
2615
- function parseAggregateError(ctx, depth, id, current) {
2818
+ function parseError(ctx, depth, type, id, current) {
2616
2819
  const options = getErrorOptions(current, ctx.base.features);
2617
- return createAggregateErrorNode(id, current, options ? parseProperties(ctx, depth, options) : void 0);
2820
+ return createErrorNode(type, id, current, options ? parseProperties(ctx, depth, options) : void 0);
2618
2821
  }
2619
2822
  function parseMap(ctx, depth, id, current) {
2620
- const keyNodes = [];
2621
- const valueNodes = [];
2823
+ const sentinel = parseMapSentinel(ctx.base);
2824
+ const keyNodes = new Array(current.size);
2825
+ const valueNodes = new Array(current.size);
2826
+ let i = 0;
2622
2827
  for (const [key, value] of current.entries()) {
2623
- keyNodes.push(parseSOS(ctx, depth, key));
2624
- valueNodes.push(parseSOS(ctx, depth, value));
2828
+ keyNodes[i] = parseSOS(ctx, depth, key);
2829
+ valueNodes[i] = parseSOS(ctx, depth, value);
2830
+ i++;
2625
2831
  }
2626
- return createMapNode(ctx.base, id, keyNodes, valueNodes);
2832
+ return createMapNode(id, sentinel, keyNodes, valueNodes);
2627
2833
  }
2628
2834
  function parseSet(ctx, depth, id, current) {
2629
- const items = [];
2630
- 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);
2631
2838
  return createSetNode(id, items);
2632
2839
  }
2633
2840
  function parseStream(ctx, depth, id, current) {
2634
2841
  const result = createStreamConstructorNode(id, parseSpecialReference(ctx.base, 4), []);
2635
- if (ctx.type === 1) return result;
2636
- pushPendingState(ctx);
2637
- current.on({
2638
- next: (value) => {
2639
- if (ctx.state.alive) {
2640
- const parsed = parseWithError(ctx, depth, value);
2641
- if (parsed) onParse(ctx, createStreamNextNode(id, parsed));
2642
- }
2643
- },
2644
- throw: (value) => {
2645
- if (ctx.state.alive) {
2646
- const parsed = parseWithError(ctx, depth, value);
2647
- if (parsed) onParse(ctx, createStreamThrowNode(id, parsed));
2648
- }
2649
- popPendingState(ctx);
2650
- },
2651
- return: (value) => {
2652
- if (ctx.state.alive) {
2653
- const parsed = parseWithError(ctx, depth, value);
2654
- if (parsed) onParse(ctx, createStreamReturnNode(id, parsed));
2655
- }
2656
- popPendingState(ctx);
2657
- }
2658
- });
2842
+ if (ctx.type === 2) ctx.state.stream(ctx, depth, id, current);
2659
2843
  return result;
2660
2844
  }
2661
- function handlePromiseSuccess(id, depth, data) {
2662
- if (this.state.alive) {
2663
- const parsed = parseWithError(this, depth, data);
2664
- 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));
2665
- popPendingState(this);
2666
- }
2667
- }
2668
- function handlePromiseFailure(id, depth, data) {
2669
- if (this.state.alive) {
2670
- const parsed = parseWithError(this, depth, data);
2671
- 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));
2672
- }
2673
- 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;
2674
2850
  }
2675
2851
  function parsePromise(ctx, depth, id, current) {
2852
+ if (ctx.type !== 2) throw new SerovalUnsupportedTypeError(current);
2676
2853
  const resolver = createIndexForValue(ctx.base, {});
2677
- if (ctx.type === 2) {
2678
- pushPendingState(ctx);
2679
- current.then(handlePromiseSuccess.bind(ctx, resolver, depth), handlePromiseFailure.bind(ctx, resolver, depth));
2680
- }
2854
+ ctx.state.promise(ctx, resolver, depth, current);
2681
2855
  return createPromiseConstructorNode(ctx.base, id, resolver);
2682
2856
  }
2683
2857
  function parsePluginSync(ctx, depth, id, current, currentPlugins) {
2684
2858
  for (let i = 0, len = currentPlugins.length; i < len; i++) {
2685
2859
  const plugin = currentPlugins[i];
2686
- 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 }));
2687
2861
  }
2688
2862
  }
2689
- function parsePluginStream(ctx, depth, id, current, currentPlugins) {
2690
- for (let i = 0, len = currentPlugins.length; i < len; i++) {
2691
- const plugin = currentPlugins[i];
2692
- if (plugin.parse.stream && plugin.test(current)) return createPluginNode(id, plugin.tag, plugin.parse.stream(current, new StreamParsePluginContext(ctx, depth), { id }));
2693
- }
2694
- }
2695
- function parsePlugin(ctx, depth, id, current) {
2696
- const currentPlugins = ctx.base.plugins;
2697
- 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);
2698
2865
  }
2699
2866
  function parseSequence(ctx, depth, id, current) {
2700
- const nodes = [];
2701
- 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]);
2702
2870
  return createSequenceNode(id, nodes, current.t, current.d);
2703
2871
  }
2704
2872
  function parseObjectPhase2(ctx, depth, id, current, currentClass) {
2705
- switch (currentClass) {
2706
- case Object: return parsePlainObject(ctx, depth, id, current, false);
2707
- case void 0: return parsePlainObject(ctx, depth, id, current, true);
2708
- case Date: return createDateNode(id, current);
2709
- case Error:
2710
- case EvalError:
2711
- case RangeError:
2712
- case ReferenceError:
2713
- case SyntaxError:
2714
- case TypeError:
2715
- case URIError: return parseError(ctx, depth, id, current);
2716
- case Number:
2717
- case Boolean:
2718
- case String:
2719
- case BigInt: return parseBoxed(ctx, depth, id, current);
2720
- case ArrayBuffer: return createArrayBufferNode(ctx.base, id, current);
2721
- case Int8Array:
2722
- case Int16Array:
2723
- case Int32Array:
2724
- case Uint8Array:
2725
- case Uint16Array:
2726
- case Uint32Array:
2727
- case Uint8ClampedArray:
2728
- case Float32Array:
2729
- case Float64Array: return parseTypedArray(ctx, depth, id, current);
2730
- case DataView: return parseDataView(ctx, depth, id, current);
2731
- case Map: return parseMap(ctx, depth, id, current);
2732
- case Set: return parseSet(ctx, depth, id, current);
2733
- }
2734
- if (currentClass === Promise || current instanceof Promise) return parsePromise(ctx, depth, id, current);
2735
- const currentFeatures = ctx.base.features;
2736
- if (currentFeatures & 32 && currentClass === RegExp) return createRegExpNode(id, current);
2737
- if (currentFeatures & 16) switch (currentClass) {
2738
- case BigInt64Array:
2739
- case BigUint64Array: return parseBigIntTypedArray(ctx, depth, id, current);
2740
- }
2741
- if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError(ctx, depth, id, current);
2742
- if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
2743
- case Temporal.Instant: return createTemporalNode(id, 0, current);
2744
- case Temporal.Duration: return createTemporalNode(id, 1, current);
2745
- case Temporal.PlainDate: return createTemporalNode(id, 2, current);
2746
- case Temporal.PlainDateTime: return createTemporalNode(id, 3, current);
2747
- case Temporal.PlainMonthDay: return createTemporalNode(id, 4, current);
2748
- case Temporal.PlainTime: return createTemporalNode(id, 5, current);
2749
- case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
2750
- case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
2751
- }
2752
- if (current instanceof Error) return parseError(ctx, depth, id, current);
2753
- if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject(ctx, depth, id, current, !!currentClass);
2754
- 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
+ }
2755
2892
  }
2756
2893
  function parseObject(ctx, depth, id, current) {
2757
2894
  if (Array.isArray(current)) return parseArray(ctx, depth, id, current);
2758
- 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);
2759
2896
  if (isSequence(current)) return parseSequence(ctx, depth, id, current);
2760
- let currentClass = current.constructor;
2761
- if (currentClass !== void 0 && typeof currentClass !== "function") {
2762
- const proto = Object.getPrototypeOf(current);
2763
- currentClass = proto === null ? void 0 : proto.constructor;
2764
- }
2897
+ const currentClass = getObjectClass(current);
2765
2898
  if (currentClass === OpaqueReference) return parseSOS(ctx, depth, current.replacement);
2766
- const parsed = parsePlugin(ctx, depth, id, current);
2899
+ const parsed = parsePlugin(ctx, depth, id, current, getObjectPlugins(ctx.base, current, currentClass));
2767
2900
  if (parsed) return parsed;
2768
2901
  return parseObjectPhase2(ctx, depth, id, current, currentClass);
2769
2902
  }
2770
2903
  function parseFunction(ctx, depth, current) {
2771
2904
  const ref = getReferenceNode(ctx.base, current);
2772
- if (ref.type !== 0) return ref.value;
2773
- 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);
2774
2907
  if (plugin) return plugin;
2775
2908
  throw new SerovalUnsupportedTypeError(current);
2776
2909
  }
@@ -2785,7 +2918,7 @@ function parseSOS(ctx, depth, current) {
2785
2918
  case "object":
2786
2919
  if (current) {
2787
2920
  const ref = getReferenceNode(ctx.base, current);
2788
- 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;
2789
2922
  }
2790
2923
  return NULL_NODE;
2791
2924
  case "symbol": return parseWellKnownSymbol(ctx.base, current);
@@ -2800,63 +2933,431 @@ function parseTop(ctx, current) {
2800
2933
  throw error instanceof SerovalParserError ? error : new SerovalParserError(error);
2801
2934
  }
2802
2935
  }
2803
- function onParse(ctx, node) {
2804
- if (ctx.state.initial) ctx.state.buffer.push(node);
2805
- 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));
2806
3005
  }
2807
- function onError(ctx, error) {
2808
- if (ctx.state.onError) ctx.state.onError(error);
2809
- else throw error instanceof SerovalParserError ? error : new SerovalParserError(error);
3006
+ function addCleanup(ctx, callback) {
3007
+ if (ctx.state.alive) ctx.state.cleanups.push(callback);
3008
+ else callback();
2810
3009
  }
2811
- function onDone(ctx) {
2812
- if (ctx.state.onDone) ctx.state.onDone();
2813
- for (let i = 0, len = ctx.state.cleanups.length; i < len; i++) ctx.state.cleanups[i]();
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
+ }
3015
+ }
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
+ };
2814
3045
  }
2815
- 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
+ }
2816
3058
  try {
2817
- ctx.state.onParse(node, initial);
3059
+ addCleanup(ctx, cleanup);
2818
3060
  } catch (error) {
2819
- onError(ctx, error);
3061
+ subscription.failure ?? (subscription.failure = { value: error });
2820
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
+ };
2821
3155
  }
2822
3156
  function pushPendingState(ctx) {
2823
- ctx.state.pending++;
3157
+ if (ctx.state.alive) ctx.state.pending++;
2824
3158
  }
2825
3159
  function popPendingState(ctx) {
2826
- if (--ctx.state.pending <= 0) onDone(ctx);
3160
+ if (ctx.state.alive) {
3161
+ ctx.state.pending--;
3162
+ checkStreamParse(ctx);
3163
+ }
2827
3164
  }
2828
- 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++;
2829
3181
  try {
2830
- return parseSOS(ctx, depth, current);
2831
- } catch (err) {
2832
- onError(ctx, err);
2833
- 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);
2834
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?.();
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);
2835
3260
  }
2836
3261
  function startStreamParse(ctx, current) {
2837
- const parsed = parseWithError(ctx, 0, current);
2838
- if (parsed) {
2839
- onParseInternal(ctx, parsed, true);
2840
- ctx.state.initial = false;
2841
- flushStreamParse(ctx, ctx.state);
2842
- 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 });
2843
3298
  }
3299
+ if (failure) throw failure.value;
2844
3300
  }
2845
- function flushStreamParse(ctx, state) {
2846
- 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;
2847
3304
  }
2848
- function destroyStreamParse(ctx) {
2849
- if (ctx.state.alive) {
2850
- onDone(ctx);
2851
- 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;
2852
3349
  }
2853
3350
  }
3351
+ function destroyStreamParse(ctx, reason) {
3352
+ stopStreamParse(ctx, 2, reason);
3353
+ }
2854
3354
  //#endregion
2855
3355
  //#region src/core/cross/index.ts
2856
3356
  function crossSerialize(source, options = {}) {
2857
3357
  const plugins = resolvePlugins(options.plugins);
2858
- const ctx = createSyncParserContext(2, {
3358
+ const ctx = createSyncParserContext({
2859
3359
  compactArrayBufferViews: options.compactArrayBufferViews,
3360
+ depthLimit: options.depthLimit,
2860
3361
  plugins,
2861
3362
  disabledFeatures: options.disabledFeatures,
2862
3363
  refs: options.refs
@@ -2866,13 +3367,15 @@ function crossSerialize(source, options = {}) {
2866
3367
  plugins,
2867
3368
  features: ctx.base.features,
2868
3369
  scopeId: options.scopeId,
2869
- markedRefs: ctx.base.marked
3370
+ markedRefs: ctx.base.marked,
3371
+ assignSharedRefsOnly: options.assignSharedRefsOnly
2870
3372
  }), tree);
2871
3373
  }
2872
3374
  async function crossSerializeAsync(source, options = {}) {
2873
3375
  const plugins = resolvePlugins(options.plugins);
2874
- const ctx = createAsyncParserContext(2, {
3376
+ const ctx = createAsyncParserContext({
2875
3377
  compactArrayBufferViews: options.compactArrayBufferViews,
3378
+ depthLimit: options.depthLimit,
2876
3379
  plugins,
2877
3380
  disabledFeatures: options.disabledFeatures,
2878
3381
  refs: options.refs
@@ -2882,13 +3385,15 @@ async function crossSerializeAsync(source, options = {}) {
2882
3385
  plugins,
2883
3386
  features: ctx.base.features,
2884
3387
  scopeId: options.scopeId,
2885
- markedRefs: ctx.base.marked
3388
+ markedRefs: ctx.base.marked,
3389
+ assignSharedRefsOnly: options.assignSharedRefsOnly
2886
3390
  }), tree);
2887
3391
  }
2888
3392
  function toCrossJSON(source, options = {}) {
2889
3393
  const plugins = resolvePlugins(options.plugins);
2890
- return parseTop(createSyncParserContext(2, {
3394
+ return parseTop(createSyncParserContext({
2891
3395
  compactArrayBufferViews: options.compactArrayBufferViews,
3396
+ depthLimit: options.depthLimit,
2892
3397
  plugins,
2893
3398
  disabledFeatures: options.disabledFeatures,
2894
3399
  refs: options.refs
@@ -2896,8 +3401,9 @@ function toCrossJSON(source, options = {}) {
2896
3401
  }
2897
3402
  async function toCrossJSONAsync(source, options = {}) {
2898
3403
  const plugins = resolvePlugins(options.plugins);
2899
- return await parseTopAsync(createAsyncParserContext(2, {
3404
+ return await parseTopAsync(createAsyncParserContext({
2900
3405
  compactArrayBufferViews: options.compactArrayBufferViews,
3406
+ depthLimit: options.depthLimit,
2901
3407
  plugins,
2902
3408
  disabledFeatures: options.disabledFeatures,
2903
3409
  refs: options.refs
@@ -2905,8 +3411,11 @@ async function toCrossJSONAsync(source, options = {}) {
2905
3411
  }
2906
3412
  function crossSerializeStream(source, options) {
2907
3413
  const plugins = resolvePlugins(options.plugins);
3414
+ const onSerialize = options.onSerialize;
3415
+ const scopeId = options.scopeId;
2908
3416
  const ctx = createStreamParserContext({
2909
3417
  compactArrayBufferViews: options.compactArrayBufferViews,
3418
+ depthLimit: options.depthLimit,
2910
3419
  plugins,
2911
3420
  refs: options.refs,
2912
3421
  disabledFeatures: options.disabledFeatures,
@@ -2914,17 +3423,10 @@ function crossSerializeStream(source, options) {
2914
3423
  const serial = createCrossSerializerContext({
2915
3424
  plugins,
2916
3425
  features: ctx.base.features,
2917
- scopeId: options.scopeId,
3426
+ scopeId,
2918
3427
  markedRefs: ctx.base.marked
2919
3428
  });
2920
- let serialized;
2921
- try {
2922
- serialized = serializeTopCross(serial, node);
2923
- } catch (err) {
2924
- if (options.onError) options.onError(err);
2925
- return;
2926
- }
2927
- options.onSerialize(serialized, initial);
3429
+ return onSerialize(serializeTopCross(serial, node), initial);
2928
3430
  },
2929
3431
  onError: options.onError,
2930
3432
  onDone: options.onDone
@@ -2947,22 +3449,39 @@ function toCrossJSONStream(source, options) {
2947
3449
  startStreamParse(ctx, source);
2948
3450
  return destroyStreamParse.bind(null, ctx);
2949
3451
  }
2950
- function fromCrossJSON(source, options) {
2951
- const plugins = resolvePlugins(options.plugins);
2952
- return deserializeTop(createCrossDeserializerContext({
3452
+ function createFromCrossJSONContext(options) {
3453
+ return createCrossDeserializerContext({
2953
3454
  maxBase64Length: options.maxBase64Length,
2954
- plugins,
3455
+ plugins: resolvePlugins(options.plugins),
2955
3456
  refs: options.refs,
2956
3457
  features: options.features,
2957
3458
  disabledFeatures: options.disabledFeatures,
2958
3459
  depthLimit: options.depthLimit
2959
- }), 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
+ };
2960
3480
  }
2961
3481
  //#endregion
2962
3482
  //#region src/core/Serializer.ts
2963
3483
  var Serializer = class {
2964
3484
  constructor(options) {
2965
- this.options = options;
2966
3485
  this.alive = true;
2967
3486
  this.flushed = false;
2968
3487
  this.done = false;
@@ -2971,32 +3490,52 @@ var Serializer = class {
2971
3490
  this.refs = /* @__PURE__ */ new Map();
2972
3491
  this.keys = /* @__PURE__ */ new Set();
2973
3492
  this.ids = 0;
3493
+ this.options = options;
2974
3494
  this.plugins = resolvePlugins(options.plugins);
2975
3495
  }
2976
3496
  write(key, value) {
2977
- if (this.alive && !this.flushed) {
3497
+ const options = this.options;
3498
+ if (this.alive && !this.flushed && options) {
2978
3499
  this.pending++;
2979
3500
  this.keys.add(key);
2980
- this.cleanups.push(crossSerializeStream(value, {
3501
+ const cleanup = crossSerializeStream(value, {
2981
3502
  plugins: this.plugins,
2982
- scopeId: this.options.scopeId,
3503
+ scopeId: options.scopeId,
2983
3504
  refs: this.refs,
2984
- disabledFeatures: this.options.disabledFeatures,
2985
- compactArrayBufferViews: this.options.compactArrayBufferViews,
2986
- 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
+ },
2987
3523
  onSerialize: (data, initial) => {
2988
- 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);
2989
3526
  },
2990
3527
  onDone: () => {
2991
- if (this.alive) {
2992
- this.pending--;
2993
- if (this.pending <= 0 && this.flushed && !this.done && this.options.onDone) {
2994
- this.options.onDone();
2995
- this.done = true;
2996
- }
2997
- }
3528
+ this.finishWrite();
2998
3529
  }
2999
- }));
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();
3000
3539
  }
3001
3540
  }
3002
3541
  getNextID() {
@@ -3011,20 +3550,36 @@ var Serializer = class {
3011
3550
  flush() {
3012
3551
  if (this.alive) {
3013
3552
  this.flushed = true;
3014
- if (this.pending <= 0 && !this.done && this.options.onDone) {
3015
- this.options.onDone();
3016
- this.done = true;
3017
- }
3553
+ if (this.pending <= 0 && !this.done) this.close();
3018
3554
  }
3019
3555
  }
3020
3556
  close() {
3557
+ this.finish();
3558
+ }
3559
+ finish() {
3021
3560
  if (this.alive) {
3022
- for (let i = 0, len = this.cleanups.length; i < len; i++) this.cleanups[i]();
3023
- if (!this.done && this.options.onDone) {
3024
- 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) {
3025
3575
  this.done = true;
3576
+ try {
3577
+ options?.onDone?.();
3578
+ } catch (error) {
3579
+ failure ?? (failure = { value: error });
3580
+ }
3026
3581
  }
3027
- this.alive = false;
3582
+ if (failure) throw failure.value;
3028
3583
  }
3029
3584
  }
3030
3585
  };
@@ -3032,8 +3587,9 @@ var Serializer = class {
3032
3587
  //#region src/core/tree/index.ts
3033
3588
  function serialize(source, options = {}) {
3034
3589
  const plugins = resolvePlugins(options.plugins);
3035
- const ctx = createSyncParserContext(1, {
3590
+ const ctx = createSyncParserContext({
3036
3591
  compactArrayBufferViews: options.compactArrayBufferViews,
3592
+ depthLimit: options.depthLimit,
3037
3593
  plugins,
3038
3594
  disabledFeatures: options.disabledFeatures
3039
3595
  });
@@ -3046,8 +3602,9 @@ function serialize(source, options = {}) {
3046
3602
  }
3047
3603
  async function serializeAsync(source, options = {}) {
3048
3604
  const plugins = resolvePlugins(options.plugins);
3049
- const ctx = createAsyncParserContext(1, {
3605
+ const ctx = createAsyncParserContext({
3050
3606
  compactArrayBufferViews: options.compactArrayBufferViews,
3607
+ depthLimit: options.depthLimit,
3051
3608
  plugins,
3052
3609
  disabledFeatures: options.disabledFeatures
3053
3610
  });
@@ -3063,8 +3620,9 @@ function deserialize(source) {
3063
3620
  }
3064
3621
  function toJSON(source, options = {}) {
3065
3622
  const plugins = resolvePlugins(options.plugins);
3066
- const ctx = createSyncParserContext(1, {
3623
+ const ctx = createSyncParserContext({
3067
3624
  compactArrayBufferViews: options.compactArrayBufferViews,
3625
+ depthLimit: options.depthLimit,
3068
3626
  plugins,
3069
3627
  disabledFeatures: options.disabledFeatures
3070
3628
  });
@@ -3076,8 +3634,9 @@ function toJSON(source, options = {}) {
3076
3634
  }
3077
3635
  async function toJSONAsync(source, options = {}) {
3078
3636
  const plugins = resolvePlugins(options.plugins);
3079
- const ctx = createAsyncParserContext(1, {
3637
+ const ctx = createAsyncParserContext({
3080
3638
  compactArrayBufferViews: options.compactArrayBufferViews,
3639
+ depthLimit: options.depthLimit,
3081
3640
  plugins,
3082
3641
  disabledFeatures: options.disabledFeatures
3083
3642
  });
@@ -3095,11 +3654,11 @@ function compileJSON(source, options = {}) {
3095
3654
  }), source.t);
3096
3655
  }
3097
3656
  function fromJSON(source, options = {}) {
3098
- var _source$f;
3099
3657
  const plugins = resolvePlugins(options.plugins);
3100
- const disabledFeatures = options.disabledFeatures || 0;
3101
- 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;
3102
3660
  return deserializeTop(createVanillaDeserializerContext({
3661
+ depthLimit: options.depthLimit,
3103
3662
  maxBase64Length: options.maxBase64Length,
3104
3663
  plugins,
3105
3664
  markedRefs: source.m,
@@ -3109,12 +3668,16 @@ function fromJSON(source, options = {}) {
3109
3668
  }
3110
3669
  //#endregion
3111
3670
  exports.Feature = Feature;
3671
+ exports.LiveStream = LiveStream;
3112
3672
  exports.OpaqueReference = OpaqueReference;
3673
+ exports.Sequence = Sequence;
3113
3674
  exports.Serializer = Serializer;
3675
+ exports.SerovalAbortedError = SerovalAbortedError;
3114
3676
  exports.SerovalConflictedNodeIdError = SerovalConflictedNodeIdError;
3115
3677
  exports.SerovalDepthLimitError = SerovalDepthLimitError;
3116
3678
  exports.SerovalDeserializationError = SerovalDeserializationError;
3117
3679
  exports.SerovalError = SerovalError;
3680
+ exports.SerovalLiveStreamError = SerovalLiveStreamError;
3118
3681
  exports.SerovalMalformedNodeError = SerovalMalformedNodeError;
3119
3682
  exports.SerovalMissingInstanceError = SerovalMissingInstanceError;
3120
3683
  exports.SerovalMissingPluginError = SerovalMissingPluginError;
@@ -3126,7 +3689,10 @@ exports.SerovalSerializationError = SerovalSerializationError;
3126
3689
  exports.SerovalUnknownTypedArrayError = SerovalUnknownTypedArrayError;
3127
3690
  exports.SerovalUnsupportedNodeError = SerovalUnsupportedNodeError;
3128
3691
  exports.SerovalUnsupportedTypeError = SerovalUnsupportedTypeError;
3692
+ exports.Stream = Stream;
3129
3693
  exports.compileJSON = compileJSON;
3694
+ exports.createCrossDeserializer = createCrossDeserializer;
3695
+ exports.createLiveStream = createLiveStream;
3130
3696
  exports.createPlugin = createPlugin;
3131
3697
  exports.createReference = createReference;
3132
3698
  exports.createStream = createStream;
@@ -3137,6 +3703,8 @@ exports.deserialize = deserialize;
3137
3703
  exports.fromCrossJSON = fromCrossJSON;
3138
3704
  exports.fromJSON = fromJSON;
3139
3705
  exports.getCrossReferenceHeader = getCrossReferenceHeader;
3706
+ exports.getPlainObjectPlugins = getPlainObjectPlugins;
3707
+ exports.isLiveStream = isLiveStream;
3140
3708
  exports.isStream = isStream;
3141
3709
  exports.resolvePlugins = resolvePlugins;
3142
3710
  exports.serialize = serialize;