seroval 1.6.12 → 1.7.1

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