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