seroval 1.6.1 → 1.6.3

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.
@@ -197,6 +197,101 @@ function deserializeString(str) {
197
197
  return str.replace(/(\\\\|\\"|\\n|\\r|\\b|\\t|\\f|\\u2028|\\u2029|\\x3C)/g, deserializeReplacer);
198
198
  }
199
199
  //#endregion
200
+ //#region src/core/errors.ts
201
+ const { toString: objectToString } = Object.prototype;
202
+ function getErrorMessageDev(type, cause) {
203
+ if (cause instanceof Error) return `Seroval caught an error during the ${type} process.
204
+
205
+ ${cause.name}
206
+ ${cause.message}
207
+
208
+ - For more information, please check the "cause" property of this error.
209
+ - If you believe this is an error in Seroval, please submit an issue at https://github.com/lxsmnsyc/seroval/issues/new`;
210
+ return `Seroval caught an error during the ${type} process.
211
+
212
+ "${objectToString.call(cause)}"
213
+
214
+ For more information, please check the "cause" property of this error.`;
215
+ }
216
+ const getErrorMessage = (type, cause) => getErrorMessageDev(type, cause);
217
+ var SerovalError = class extends Error {
218
+ constructor(type, cause) {
219
+ super(getErrorMessage(type, cause));
220
+ this.cause = cause;
221
+ }
222
+ };
223
+ var SerovalParserError = class extends SerovalError {
224
+ constructor(cause) {
225
+ super("parsing", cause);
226
+ }
227
+ };
228
+ var SerovalSerializationError = class extends SerovalError {
229
+ constructor(cause) {
230
+ super("serialization", cause);
231
+ }
232
+ };
233
+ var SerovalDeserializationError = class extends SerovalError {
234
+ constructor(cause) {
235
+ super("deserialization", cause);
236
+ }
237
+ };
238
+ var SerovalUnsupportedTypeError = class extends Error {
239
+ constructor(value) {
240
+ super(`The value ${objectToString.call(value)} of type "${typeof value}" cannot be parsed/serialized.
241
+
242
+ There are few workarounds for this problem:
243
+ - Transform the value in a way that it can be serialized.
244
+ - If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.`);
245
+ this.value = value;
246
+ }
247
+ };
248
+ var SerovalUnsupportedNodeError = class extends Error {
249
+ constructor(node) {
250
+ super("Unsupported node type \"" + node.t + "\".");
251
+ }
252
+ };
253
+ var SerovalMissingPluginError = class extends Error {
254
+ constructor(tag) {
255
+ super("Missing plugin for tag \"" + tag + "\".");
256
+ }
257
+ };
258
+ var SerovalMissingInstanceError = class extends Error {
259
+ constructor(tag) {
260
+ super("Missing \"" + tag + "\" instance.");
261
+ }
262
+ };
263
+ var SerovalMissingReferenceError = class extends Error {
264
+ constructor(value) {
265
+ super("Missing reference for the value \"" + objectToString.call(value) + "\" of type \"" + typeof value + "\"");
266
+ this.value = value;
267
+ }
268
+ };
269
+ var SerovalMissingReferenceForIdError = class extends Error {
270
+ constructor(id) {
271
+ super("Missing reference for id \"" + serializeString(id) + "\"");
272
+ }
273
+ };
274
+ var SerovalUnknownTypedArrayError = class extends Error {
275
+ constructor(name) {
276
+ super("Unknown TypedArray \"" + name + "\"");
277
+ }
278
+ };
279
+ var SerovalMalformedNodeError = class extends Error {
280
+ constructor(node) {
281
+ super("Malformed node type \"" + node.t + "\".");
282
+ }
283
+ };
284
+ var SerovalConflictedNodeIdError = class extends Error {
285
+ constructor(node) {
286
+ super("Conflicted node id \"" + node.i + "\".");
287
+ }
288
+ };
289
+ var SerovalDepthLimitError = class extends Error {
290
+ constructor(limit) {
291
+ super("Depth limit of " + limit + " reached");
292
+ }
293
+ };
294
+ //#endregion
200
295
  //#region src/core/keys.ts
201
296
  const REFERENCES_KEY = "__SEROVAL_REFS__";
202
297
  const GLOBAL_CONTEXT_R = `self.\$R`;
@@ -273,14 +368,16 @@ function getErrorOptions(error, features) {
273
368
  const names = Object.getOwnPropertyNames(error);
274
369
  for (let i = 0, len = names.length, name; i < len; i++) {
275
370
  name = names[i];
276
- if (name !== "name" && name !== "message") if (name === "stack") {
277
- if (features & 4) {
371
+ if (name !== "name" && name !== "message") {
372
+ if (name === "stack") {
373
+ if (features & 4) {
374
+ options = options || {};
375
+ options[name] = error[name];
376
+ }
377
+ } else {
278
378
  options = options || {};
279
379
  options[name] = error[name];
280
380
  }
281
- } else {
282
- options = options || {};
283
- options[name] = error[name];
284
381
  }
285
382
  }
286
383
  return options;
@@ -338,13 +435,17 @@ function createArrayNode(id, current, parsedItems) {
338
435
  function createBoxedNode(id, boxed) {
339
436
  return createSerovalNode(21, id, void 0, void 0, void 0, void 0, void 0, void 0, boxed, void 0, void 0, void 0);
340
437
  }
438
+ const MAX_TYPED_ARRAY_LENGTH = 1e6;
341
439
  function createTypedArrayNode(id, current, buffer) {
440
+ if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
342
441
  return createSerovalNode(15, id, void 0, current.constructor.name, void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
343
442
  }
344
443
  function createBigIntTypedArrayNode(id, current, buffer) {
444
+ if (current.length > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
345
445
  return createSerovalNode(16, id, void 0, current.constructor.name, void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.length);
346
446
  }
347
447
  function createDataViewNode(id, current, buffer) {
448
+ if (current.byteLength > MAX_TYPED_ARRAY_LENGTH) throw new SerovalUnsupportedTypeError(current);
348
449
  return createSerovalNode(20, id, void 0, void 0, void 0, void 0, void 0, void 0, buffer, current.byteOffset, void 0, current.byteLength);
349
450
  }
350
451
  function createErrorNode(id, current, options) {
@@ -378,101 +479,6 @@ function createSequenceNode(id, sequence, throwAt, doneAt) {
378
479
  return createSerovalNode(35, id, throwAt, void 0, void 0, void 0, void 0, sequence, void 0, void 0, void 0, doneAt);
379
480
  }
380
481
  //#endregion
381
- //#region src/core/errors.ts
382
- const { toString: objectToString } = Object.prototype;
383
- function getErrorMessageDev(type, cause) {
384
- if (cause instanceof Error) return `Seroval caught an error during the ${type} process.
385
-
386
- ${cause.name}
387
- ${cause.message}
388
-
389
- - For more information, please check the "cause" property of this error.
390
- - If you believe this is an error in Seroval, please submit an issue at https://github.com/lxsmnsyc/seroval/issues/new`;
391
- return `Seroval caught an error during the ${type} process.
392
-
393
- "${objectToString.call(cause)}"
394
-
395
- For more information, please check the "cause" property of this error.`;
396
- }
397
- const getErrorMessage = (type, cause) => getErrorMessageDev(type, cause);
398
- var SerovalError = class extends Error {
399
- constructor(type, cause) {
400
- super(getErrorMessage(type, cause));
401
- this.cause = cause;
402
- }
403
- };
404
- var SerovalParserError = class extends SerovalError {
405
- constructor(cause) {
406
- super("parsing", cause);
407
- }
408
- };
409
- var SerovalSerializationError = class extends SerovalError {
410
- constructor(cause) {
411
- super("serialization", cause);
412
- }
413
- };
414
- var SerovalDeserializationError = class extends SerovalError {
415
- constructor(cause) {
416
- super("deserialization", cause);
417
- }
418
- };
419
- var SerovalUnsupportedTypeError = class extends Error {
420
- constructor(value) {
421
- super(`The value ${objectToString.call(value)} of type "${typeof value}" cannot be parsed/serialized.
422
-
423
- There are few workarounds for this problem:
424
- - Transform the value in a way that it can be serialized.
425
- - If the reference is present on multiple runtimes (isomorphic), you can use the Reference API to map the references.`);
426
- this.value = value;
427
- }
428
- };
429
- var SerovalUnsupportedNodeError = class extends Error {
430
- constructor(node) {
431
- super("Unsupported node type \"" + node.t + "\".");
432
- }
433
- };
434
- var SerovalMissingPluginError = class extends Error {
435
- constructor(tag) {
436
- super("Missing plugin for tag \"" + tag + "\".");
437
- }
438
- };
439
- var SerovalMissingInstanceError = class extends Error {
440
- constructor(tag) {
441
- super("Missing \"" + tag + "\" instance.");
442
- }
443
- };
444
- var SerovalMissingReferenceError = class extends Error {
445
- constructor(value) {
446
- super("Missing reference for the value \"" + objectToString.call(value) + "\" of type \"" + typeof value + "\"");
447
- this.value = value;
448
- }
449
- };
450
- var SerovalMissingReferenceForIdError = class extends Error {
451
- constructor(id) {
452
- super("Missing reference for id \"" + serializeString(id) + "\"");
453
- }
454
- };
455
- var SerovalUnknownTypedArrayError = class extends Error {
456
- constructor(name) {
457
- super("Unknown TypedArray \"" + name + "\"");
458
- }
459
- };
460
- var SerovalMalformedNodeError = class extends Error {
461
- constructor(node) {
462
- super("Malformed node type \"" + node.t + "\".");
463
- }
464
- };
465
- var SerovalConflictedNodeIdError = class extends Error {
466
- constructor(node) {
467
- super("Conflicted node id \"" + node.i + "\".");
468
- }
469
- };
470
- var SerovalDepthLimitError = class extends Error {
471
- constructor(limit) {
472
- super("Depth limit of " + limit + " reached");
473
- }
474
- };
475
- //#endregion
476
482
  //#region src/core/opaque-reference.ts
477
483
  /**
478
484
  * An opaque reference allows hiding values from the serializer.
@@ -1060,7 +1066,6 @@ async function parseObjectAsync(ctx, depth, id, current) {
1060
1066
  case DataView: return parseDataView$1(ctx, depth, id, current);
1061
1067
  case Map: return parseMap$1(ctx, depth, id, current);
1062
1068
  case Set: return parseSet$1(ctx, depth, id, current);
1063
- default: break;
1064
1069
  }
1065
1070
  if (currentClass === Promise || current instanceof Promise) return parsePromise$1(ctx, depth, id, current);
1066
1071
  const currentFeatures = ctx.base.features;
@@ -1068,7 +1073,6 @@ async function parseObjectAsync(ctx, depth, id, current) {
1068
1073
  if (currentFeatures & 16) switch (currentClass) {
1069
1074
  case BigInt64Array:
1070
1075
  case BigUint64Array: return parseBigIntTypedArray$1(ctx, depth, id, current);
1071
- default: break;
1072
1076
  }
1073
1077
  if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError$1(ctx, depth, id, current);
1074
1078
  if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
@@ -1080,7 +1084,6 @@ async function parseObjectAsync(ctx, depth, id, current) {
1080
1084
  case Temporal.PlainTime: return createTemporalNode(id, 5, current);
1081
1085
  case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
1082
1086
  case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
1083
- default: break;
1084
1087
  }
1085
1088
  if (current instanceof Error) return parseError$1(ctx, depth, id, current);
1086
1089
  if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject$1(ctx, depth, id, current, !!currentClass);
@@ -1243,6 +1246,9 @@ function guardIndexedValue(ctx, id) {
1243
1246
  });
1244
1247
  if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1245
1248
  }
1249
+ function isThennable(value) {
1250
+ return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
1251
+ }
1246
1252
  function assignIndexedValueVanilla(ctx, id, value) {
1247
1253
  guardIndexedValue(ctx.base, id);
1248
1254
  if (ctx.state.marked.has(id)) ctx.base.refs.set(id, value);
@@ -1377,14 +1383,14 @@ function deserializeTypedArray(ctx, depth, node) {
1377
1383
  const construct = getTypedArrayConstructor(node.c);
1378
1384
  const source = deserialize$1(ctx, depth, node.f);
1379
1385
  const offset = (_node$b = node.b) !== null && _node$b !== void 0 ? _node$b : 0;
1380
- if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1386
+ if (offset < 0 || offset > source.byteLength || node.l > MAX_BASE64_LENGTH) throw new SerovalMalformedNodeError(node);
1381
1387
  return assignIndexedValue$1(ctx, node.i, new construct(source, offset, node.l));
1382
1388
  }
1383
1389
  function deserializeDataView(ctx, depth, node) {
1384
1390
  var _node$b2;
1385
1391
  const source = deserialize$1(ctx, depth, node.f);
1386
1392
  const offset = (_node$b2 = node.b) !== null && _node$b2 !== void 0 ? _node$b2 : 0;
1387
- if (offset < 0 || offset > source.byteLength) throw new SerovalMalformedNodeError(node);
1393
+ if (offset < 0 || offset > source.byteLength || node.l > MAX_BASE64_LENGTH) throw new SerovalMalformedNodeError(node);
1388
1394
  return assignIndexedValue$1(ctx, node.i, new DataView(source, offset, node.l));
1389
1395
  }
1390
1396
  function deserializeDictionary(ctx, depth, node, result) {
@@ -1405,6 +1411,7 @@ function deserializePromise(ctx, depth, node) {
1405
1411
  const deferred = PROMISE_CONSTRUCTOR();
1406
1412
  const result = assignIndexedValue$1(ctx, node.i, deferred.p);
1407
1413
  const deserialized = deserialize$1(ctx, depth, node.f);
1414
+ if (isThennable(deserialized)) throw new SerovalMalformedNodeError(node.f);
1408
1415
  if (node.s) deferred.s(deserialized);
1409
1416
  else deferred.f(deserialized);
1410
1417
  return result;
@@ -1428,20 +1435,14 @@ function deserializePromiseConstructor(ctx, node) {
1428
1435
  assignNodeType(ctx, node.s, 22);
1429
1436
  return value;
1430
1437
  }
1431
- function deserializePromiseResolve(ctx, depth, node) {
1432
- const deferred = ctx.base.refs.get(node.i);
1433
- if (deferred) {
1434
- validateNodeType(ctx, node, node.i, 22);
1435
- deferred.s(deserialize$1(ctx, depth, node.a[1]));
1436
- return;
1437
- }
1438
- throw new SerovalMissingInstanceError("Promise");
1439
- }
1440
- function deserializePromiseReject(ctx, depth, node) {
1438
+ function deserializePromiseFulfill(ctx, depth, node) {
1441
1439
  const deferred = ctx.base.refs.get(node.i);
1442
1440
  if (deferred) {
1443
1441
  validateNodeType(ctx, node, node.i, 22);
1444
- deferred.f(deserialize$1(ctx, depth, node.a[1]));
1442
+ const deserialized = deserialize$1(ctx, depth, node.a[1]);
1443
+ if (isThennable(deserialized)) throw new SerovalMalformedNodeError(node.a[1]);
1444
+ if (node.t === 23) deferred.s(deserialized);
1445
+ else deferred.f(deserialized);
1445
1446
  return;
1446
1447
  }
1447
1448
  throw new SerovalMissingInstanceError("Promise");
@@ -1530,8 +1531,8 @@ function deserialize$1(ctx, depth, node) {
1530
1531
  case 21: return deserializeBoxed(ctx, depth, node);
1531
1532
  case 25: return deserializePlugin(ctx, depth, node);
1532
1533
  case 22: return deserializePromiseConstructor(ctx, node);
1533
- case 23: return deserializePromiseResolve(ctx, depth, node);
1534
- case 24: return deserializePromiseReject(ctx, depth, node);
1534
+ case 23:
1535
+ case 24: return deserializePromiseFulfill(ctx, depth, node);
1535
1536
  case 28: return deserializeIteratorFactoryInstance(ctx, depth, node);
1536
1537
  case 30: return deserializeAsyncIteratorFactoryInstance(ctx, depth, node);
1537
1538
  case 31: return deserializeStreamConstructor(ctx, depth, node);
@@ -1924,9 +1925,10 @@ function serializeStringKeyAssignment(ctx, source, mainAssignments, key, value)
1924
1925
  const serialized = serialize$1(ctx, value);
1925
1926
  const check = Number(key);
1926
1927
  const isIdentifier = check >= 0 && check.toString() === key || isValidIdentifier(key);
1927
- if (isIndexedValueInStack(base, value)) if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
1928
- else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
1929
- else {
1928
+ if (isIndexedValueInStack(base, value)) {
1929
+ if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
1930
+ else createArrayAssign(ctx, source.i, isIdentifier ? key : "\"" + key + "\"", serialized);
1931
+ } else {
1930
1932
  const parentAssignment = base.assignments;
1931
1933
  base.assignments = mainAssignments;
1932
1934
  if (isIdentifier && check !== check) createObjectAssign(ctx, source.i, key, serialized);
@@ -2553,7 +2555,6 @@ function parseObjectPhase2(ctx, depth, id, current, currentClass) {
2553
2555
  case DataView: return parseDataView(ctx, depth, id, current);
2554
2556
  case Map: return parseMap(ctx, depth, id, current);
2555
2557
  case Set: return parseSet(ctx, depth, id, current);
2556
- default: break;
2557
2558
  }
2558
2559
  if (currentClass === Promise || current instanceof Promise) return parsePromise(ctx, depth, id, current);
2559
2560
  const currentFeatures = ctx.base.features;
@@ -2561,7 +2562,6 @@ function parseObjectPhase2(ctx, depth, id, current, currentClass) {
2561
2562
  if (currentFeatures & 16) switch (currentClass) {
2562
2563
  case BigInt64Array:
2563
2564
  case BigUint64Array: return parseBigIntTypedArray(ctx, depth, id, current);
2564
- default: break;
2565
2565
  }
2566
2566
  if (currentFeatures & 1 && typeof AggregateError !== "undefined" && (currentClass === AggregateError || current instanceof AggregateError)) return parseAggregateError(ctx, depth, id, current);
2567
2567
  if (currentFeatures & 64 && typeof Temporal !== "undefined") switch (currentClass) {
@@ -2573,7 +2573,6 @@ function parseObjectPhase2(ctx, depth, id, current, currentClass) {
2573
2573
  case Temporal.PlainTime: return createTemporalNode(id, 5, current);
2574
2574
  case Temporal.PlainYearMonth: return createTemporalNode(id, 6, current);
2575
2575
  case Temporal.ZonedDateTime: return createTemporalNode(id, 7, current);
2576
- default: break;
2577
2576
  }
2578
2577
  if (current instanceof Error) return parseError(ctx, depth, id, current);
2579
2578
  if (SYM_ITERATOR in current || SYM_ASYNC_ITERATOR in current) return parsePlainObject(ctx, depth, id, current, !!currentClass);