seroval 1.6.11 → 1.7.0

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