seroval 1.6.12 → 1.7.0

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