seroval 1.6.7 → 1.6.9

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.
@@ -700,16 +700,26 @@ const ARRAY_BUFFER_CONSTRUCTOR = (b64) => {
700
700
  const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR = /* @__PURE__ */ ARRAY_BUFFER_CONSTRUCTOR.toString();
701
701
  //#endregion
702
702
  //#region src/core/sequence.ts
703
+ /**
704
+ * An internal class rather than a tagged POJO: identity is checked with
705
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
706
+ * The eval-based `deserialize` path still rebuilds a `{__SEROVAL_SEQUENCE__…}`
707
+ * POJO from embedded source - it has no access to this class - so a value read
708
+ * back through `deserialize` is not an instance and, by design, is not treated
709
+ * as a genuine Sequence on re-serialization.
710
+ */
711
+ var Sequence = class {
712
+ constructor(values, throwAt, doneAt) {
713
+ this.v = values;
714
+ this.t = throwAt;
715
+ this.d = doneAt;
716
+ }
717
+ };
703
718
  function isSequence(value) {
704
- return "__SEROVAL_SEQUENCE__" in value;
719
+ return value instanceof Sequence;
705
720
  }
706
721
  function createSequence(values, throwAt, doneAt) {
707
- return {
708
- __SEROVAL_SEQUENCE__: true,
709
- v: values,
710
- t: throwAt,
711
- d: doneAt
712
- };
722
+ return new Sequence(values, throwAt, doneAt);
713
723
  }
714
724
  function createSequenceFromIterable(source) {
715
725
  const values = [];
@@ -725,7 +735,9 @@ function createSequenceFromIterable(source) {
725
735
  }
726
736
  } catch (error) {
727
737
  throwsAt = values.length;
738
+ doneAt = throwsAt;
728
739
  values.push(error);
740
+ break;
729
741
  }
730
742
  return createSequence(values, throwsAt, doneAt);
731
743
  }
@@ -758,11 +770,86 @@ const SPECIAL_REF_STRING = {
758
770
  };
759
771
  //#endregion
760
772
  //#region src/core/stream.ts
773
+ /**
774
+ * An internal class rather than a tagged POJO: identity is checked with
775
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
776
+ *
777
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
778
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
779
+ * output, which has no access to this class, so the two cannot be shared. A
780
+ * stream read back through `deserialize` is therefore a plain POJO and, by
781
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
782
+ * implementations in sync.
783
+ */
784
+ var Stream = class {
785
+ constructor() {
786
+ this.buffer = [];
787
+ this.listeners = [];
788
+ this.alive = true;
789
+ this.success = false;
790
+ this.count = 0;
791
+ }
792
+ flush(value, mode) {
793
+ for (let x = 0; x < this.count; x++) {
794
+ var _this$listeners$x;
795
+ (_this$listeners$x = this.listeners[x]) === null || _this$listeners$x === void 0 || _this$listeners$x[mode](value);
796
+ }
797
+ }
798
+ replay(listener) {
799
+ for (let x = 0, z = this.buffer.length; x < z; x++) {
800
+ const current = this.buffer[x];
801
+ if (!this.alive && x === z - 1) listener[this.success ? "return" : "throw"](current);
802
+ else listener.next(current);
803
+ }
804
+ }
805
+ on(listener) {
806
+ let subscribed = this.alive;
807
+ let temp = 0;
808
+ if (subscribed) {
809
+ for (; temp < this.count; temp++) if (!this.listeners[temp]) break;
810
+ if (temp === this.count) this.count++;
811
+ this.listeners[temp] = listener;
812
+ }
813
+ this.replay(listener);
814
+ return () => {
815
+ if (this.alive && subscribed) {
816
+ subscribed = false;
817
+ this.listeners[temp] = void 0;
818
+ while (this.count > 0 && !this.listeners[this.count - 1]) this.count--;
819
+ this.listeners.length = this.count;
820
+ }
821
+ };
822
+ }
823
+ next(value) {
824
+ if (this.alive) {
825
+ this.buffer.push(value);
826
+ this.flush(value, "next");
827
+ }
828
+ }
829
+ throw(value) {
830
+ if (this.alive) {
831
+ this.buffer.push(value);
832
+ this.flush(value, "throw");
833
+ this.alive = false;
834
+ this.success = false;
835
+ this.listeners.length = 0;
836
+ }
837
+ }
838
+ return(value) {
839
+ if (this.alive) {
840
+ this.buffer.push(value);
841
+ this.flush(value, "return");
842
+ this.alive = false;
843
+ this.success = true;
844
+ this.listeners.length = 0;
845
+ }
846
+ }
847
+ };
761
848
  function isStream(value) {
762
- return "__SEROVAL_STREAM__" in value;
849
+ return value instanceof Stream;
763
850
  }
764
851
  function createStream() {
765
- return STREAM_CONSTRUCTOR();
852
+ return new Stream();
766
853
  }
767
854
  function createStreamFromAsyncIterable(iterable, cleanups) {
768
855
  const stream = createStream();
@@ -1294,7 +1381,7 @@ function guardIndexedValue(ctx, id) {
1294
1381
  if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1295
1382
  }
1296
1383
  function isThennable(value) {
1297
- return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
1384
+ return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1298
1385
  }
1299
1386
  function assignIndexedValueVanilla(ctx, id, value) {
1300
1387
  guardIndexedValue(ctx.base, id);
@@ -1316,8 +1403,12 @@ function deserializeKnownValue(node, record, key) {
1316
1403
  function deserializeReference(ctx, node) {
1317
1404
  return assignIndexedValue$1(ctx, node.i, getReference(deserializeString(node.s)));
1318
1405
  }
1406
+ function validateNodeList(node, list) {
1407
+ if (!Array.isArray(list)) throw new SerovalMalformedNodeError(node);
1408
+ }
1319
1409
  function deserializeArray(ctx, depth, node) {
1320
1410
  const items = node.a;
1411
+ validateNodeList(node, items);
1321
1412
  const len = items.length;
1322
1413
  const result = assignIndexedValue$1(ctx, node.i, new Array(len));
1323
1414
  for (let i = 0, item; i < len; i++) {
@@ -1359,6 +1450,8 @@ function validateNodeType(ctx, node, id, type) {
1359
1450
  }
1360
1451
  function deserializeProperties(ctx, depth, node, result) {
1361
1452
  const keys = node.k;
1453
+ validateNodeList(node, keys);
1454
+ validateNodeList(node, node.v);
1362
1455
  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]);
1363
1456
  return result;
1364
1457
  }
@@ -1413,11 +1506,14 @@ function deserializeRegExp(ctx, node) {
1413
1506
  }
1414
1507
  function deserializeSet(ctx, depth, node) {
1415
1508
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Set());
1509
+ validateNodeList(node, node.a);
1416
1510
  for (let i = 0, items = node.a, len = items.length; i < len; i++) result.add(deserialize$1(ctx, depth, items[i]));
1417
1511
  return result;
1418
1512
  }
1419
1513
  function deserializeMap(ctx, depth, node) {
1420
1514
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Map());
1515
+ validateNodeList(node, node.e.k);
1516
+ validateNodeList(node, node.e.v);
1421
1517
  for (let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length; i < len; i++) result.set(deserialize$1(ctx, depth, keys[i]), deserialize$1(ctx, depth, vals[i]));
1422
1518
  return result;
1423
1519
  }
@@ -1508,21 +1604,20 @@ function deserializePromiseFulfill(ctx, depth, node) {
1508
1604
  function deserializeIteratorFactoryInstance(ctx, depth, node) {
1509
1605
  deserialize$1(ctx, depth, node.a[0]);
1510
1606
  const source = deserialize$1(ctx, depth, node.a[1]);
1511
- validateNodeType(ctx, node, node.a[1].i, 35);
1512
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1607
+ if (!isSequence(source)) throw new SerovalMalformedNodeError(node.a[1]);
1513
1608
  return sequenceToIterator(source);
1514
1609
  }
1515
1610
  function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1516
1611
  deserialize$1(ctx, depth, node.a[0]);
1517
1612
  const source = deserialize$1(ctx, depth, node.a[1]);
1518
- validateNodeType(ctx, node, node.a[1].i, 31);
1519
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1613
+ if (!isStream(source)) throw new SerovalMalformedNodeError(node.a[1]);
1520
1614
  return streamToAsyncIterable(source);
1521
1615
  }
1522
1616
  function deserializeStreamConstructor(ctx, depth, node) {
1523
1617
  const result = assignIndexedValue$1(ctx, node.i, createStream());
1524
1618
  assignNodeType(ctx, node.i, 31);
1525
1619
  const items = node.a;
1620
+ validateNodeList(node, items);
1526
1621
  const len = items.length;
1527
1622
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1528
1623
  return result;
@@ -1560,10 +1655,15 @@ function deserializeIteratorFactory(ctx, depth, node) {
1560
1655
  function deserializeAsyncIteratorFactory(ctx, depth, node) {
1561
1656
  deserialize$1(ctx, depth, node.a[1]);
1562
1657
  }
1658
+ function isSequenceIndex(value, size) {
1659
+ return Number.isInteger(value) && value >= -1 && value < size;
1660
+ }
1563
1661
  function deserializeSequence(ctx, depth, node) {
1662
+ validateNodeList(node, node.a);
1663
+ const size = node.a.length;
1664
+ if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1564
1665
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1565
- assignNodeType(ctx, node.i, 35);
1566
- for (let i = 0, len = node.a.length; i < len; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1666
+ for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1567
1667
  return result;
1568
1668
  }
1569
1669
  function deserialize$1(ctx, depth, node) {
@@ -737,14 +737,31 @@ interface StreamListener<T> {
737
737
  throw(value: unknown): void;
738
738
  return(value: T): void;
739
739
  }
740
- interface Stream<T> {
741
- __SEROVAL_STREAM__: true;
740
+ /**
741
+ * An internal class rather than a tagged POJO: identity is checked with
742
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
743
+ *
744
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
745
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
746
+ * output, which has no access to this class, so the two cannot be shared. A
747
+ * stream read back through `deserialize` is therefore a plain POJO and, by
748
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
749
+ * implementations in sync.
750
+ */
751
+ declare class Stream<T> {
752
+ private buffer;
753
+ private listeners;
754
+ private alive;
755
+ private success;
756
+ private count;
757
+ private flush;
758
+ private replay;
742
759
  on(listener: StreamListener<T>): () => void;
743
760
  next(value: T): void;
744
761
  throw(value: unknown): void;
745
762
  return(value: T): void;
746
763
  }
747
- declare function isStream<T>(value: object): value is Stream<T>;
764
+ declare function isStream<T>(value: unknown): value is Stream<T>;
748
765
  declare function createStream<T>(): Stream<T>;
749
766
  //#endregion
750
767
  //#region src/core/tree/index.d.ts
@@ -737,14 +737,31 @@ interface StreamListener<T> {
737
737
  throw(value: unknown): void;
738
738
  return(value: T): void;
739
739
  }
740
- interface Stream<T> {
741
- __SEROVAL_STREAM__: true;
740
+ /**
741
+ * An internal class rather than a tagged POJO: identity is checked with
742
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
743
+ *
744
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
745
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
746
+ * output, which has no access to this class, so the two cannot be shared. A
747
+ * stream read back through `deserialize` is therefore a plain POJO and, by
748
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
749
+ * implementations in sync.
750
+ */
751
+ declare class Stream<T> {
752
+ private buffer;
753
+ private listeners;
754
+ private alive;
755
+ private success;
756
+ private count;
757
+ private flush;
758
+ private replay;
742
759
  on(listener: StreamListener<T>): () => void;
743
760
  next(value: T): void;
744
761
  throw(value: unknown): void;
745
762
  return(value: T): void;
746
763
  }
747
- declare function isStream<T>(value: object): value is Stream<T>;
764
+ declare function isStream<T>(value: unknown): value is Stream<T>;
748
765
  declare function createStream<T>(): Stream<T>;
749
766
  //#endregion
750
767
  //#region src/core/tree/index.d.ts
package/dist/dev/index.js CHANGED
@@ -699,16 +699,26 @@ const ARRAY_BUFFER_CONSTRUCTOR = (b64) => {
699
699
  const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR = /* @__PURE__ */ ARRAY_BUFFER_CONSTRUCTOR.toString();
700
700
  //#endregion
701
701
  //#region src/core/sequence.ts
702
+ /**
703
+ * An internal class rather than a tagged POJO: identity is checked with
704
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
705
+ * The eval-based `deserialize` path still rebuilds a `{__SEROVAL_SEQUENCE__…}`
706
+ * POJO from embedded source - it has no access to this class - so a value read
707
+ * back through `deserialize` is not an instance and, by design, is not treated
708
+ * as a genuine Sequence on re-serialization.
709
+ */
710
+ var Sequence = class {
711
+ constructor(values, throwAt, doneAt) {
712
+ this.v = values;
713
+ this.t = throwAt;
714
+ this.d = doneAt;
715
+ }
716
+ };
702
717
  function isSequence(value) {
703
- return "__SEROVAL_SEQUENCE__" in value;
718
+ return value instanceof Sequence;
704
719
  }
705
720
  function createSequence(values, throwAt, doneAt) {
706
- return {
707
- __SEROVAL_SEQUENCE__: true,
708
- v: values,
709
- t: throwAt,
710
- d: doneAt
711
- };
721
+ return new Sequence(values, throwAt, doneAt);
712
722
  }
713
723
  function createSequenceFromIterable(source) {
714
724
  const values = [];
@@ -724,7 +734,9 @@ function createSequenceFromIterable(source) {
724
734
  }
725
735
  } catch (error) {
726
736
  throwsAt = values.length;
737
+ doneAt = throwsAt;
727
738
  values.push(error);
739
+ break;
728
740
  }
729
741
  return createSequence(values, throwsAt, doneAt);
730
742
  }
@@ -757,11 +769,86 @@ const SPECIAL_REF_STRING = {
757
769
  };
758
770
  //#endregion
759
771
  //#region src/core/stream.ts
772
+ /**
773
+ * An internal class rather than a tagged POJO: identity is checked with
774
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
775
+ *
776
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
777
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
778
+ * output, which has no access to this class, so the two cannot be shared. A
779
+ * stream read back through `deserialize` is therefore a plain POJO and, by
780
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
781
+ * implementations in sync.
782
+ */
783
+ var Stream = class {
784
+ constructor() {
785
+ this.buffer = [];
786
+ this.listeners = [];
787
+ this.alive = true;
788
+ this.success = false;
789
+ this.count = 0;
790
+ }
791
+ flush(value, mode) {
792
+ for (let x = 0; x < this.count; x++) {
793
+ var _this$listeners$x;
794
+ (_this$listeners$x = this.listeners[x]) === null || _this$listeners$x === void 0 || _this$listeners$x[mode](value);
795
+ }
796
+ }
797
+ replay(listener) {
798
+ for (let x = 0, z = this.buffer.length; x < z; x++) {
799
+ const current = this.buffer[x];
800
+ if (!this.alive && x === z - 1) listener[this.success ? "return" : "throw"](current);
801
+ else listener.next(current);
802
+ }
803
+ }
804
+ on(listener) {
805
+ let subscribed = this.alive;
806
+ let temp = 0;
807
+ if (subscribed) {
808
+ for (; temp < this.count; temp++) if (!this.listeners[temp]) break;
809
+ if (temp === this.count) this.count++;
810
+ this.listeners[temp] = listener;
811
+ }
812
+ this.replay(listener);
813
+ return () => {
814
+ if (this.alive && subscribed) {
815
+ subscribed = false;
816
+ this.listeners[temp] = void 0;
817
+ while (this.count > 0 && !this.listeners[this.count - 1]) this.count--;
818
+ this.listeners.length = this.count;
819
+ }
820
+ };
821
+ }
822
+ next(value) {
823
+ if (this.alive) {
824
+ this.buffer.push(value);
825
+ this.flush(value, "next");
826
+ }
827
+ }
828
+ throw(value) {
829
+ if (this.alive) {
830
+ this.buffer.push(value);
831
+ this.flush(value, "throw");
832
+ this.alive = false;
833
+ this.success = false;
834
+ this.listeners.length = 0;
835
+ }
836
+ }
837
+ return(value) {
838
+ if (this.alive) {
839
+ this.buffer.push(value);
840
+ this.flush(value, "return");
841
+ this.alive = false;
842
+ this.success = true;
843
+ this.listeners.length = 0;
844
+ }
845
+ }
846
+ };
760
847
  function isStream(value) {
761
- return "__SEROVAL_STREAM__" in value;
848
+ return value instanceof Stream;
762
849
  }
763
850
  function createStream() {
764
- return STREAM_CONSTRUCTOR();
851
+ return new Stream();
765
852
  }
766
853
  function createStreamFromAsyncIterable(iterable, cleanups) {
767
854
  const stream = createStream();
@@ -1293,7 +1380,7 @@ function guardIndexedValue(ctx, id) {
1293
1380
  if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1294
1381
  }
1295
1382
  function isThennable(value) {
1296
- return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
1383
+ return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1297
1384
  }
1298
1385
  function assignIndexedValueVanilla(ctx, id, value) {
1299
1386
  guardIndexedValue(ctx.base, id);
@@ -1315,8 +1402,12 @@ function deserializeKnownValue(node, record, key) {
1315
1402
  function deserializeReference(ctx, node) {
1316
1403
  return assignIndexedValue$1(ctx, node.i, getReference(deserializeString(node.s)));
1317
1404
  }
1405
+ function validateNodeList(node, list) {
1406
+ if (!Array.isArray(list)) throw new SerovalMalformedNodeError(node);
1407
+ }
1318
1408
  function deserializeArray(ctx, depth, node) {
1319
1409
  const items = node.a;
1410
+ validateNodeList(node, items);
1320
1411
  const len = items.length;
1321
1412
  const result = assignIndexedValue$1(ctx, node.i, new Array(len));
1322
1413
  for (let i = 0, item; i < len; i++) {
@@ -1358,6 +1449,8 @@ function validateNodeType(ctx, node, id, type) {
1358
1449
  }
1359
1450
  function deserializeProperties(ctx, depth, node, result) {
1360
1451
  const keys = node.k;
1452
+ validateNodeList(node, keys);
1453
+ validateNodeList(node, node.v);
1361
1454
  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]);
1362
1455
  return result;
1363
1456
  }
@@ -1412,11 +1505,14 @@ function deserializeRegExp(ctx, node) {
1412
1505
  }
1413
1506
  function deserializeSet(ctx, depth, node) {
1414
1507
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Set());
1508
+ validateNodeList(node, node.a);
1415
1509
  for (let i = 0, items = node.a, len = items.length; i < len; i++) result.add(deserialize$1(ctx, depth, items[i]));
1416
1510
  return result;
1417
1511
  }
1418
1512
  function deserializeMap(ctx, depth, node) {
1419
1513
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Map());
1514
+ validateNodeList(node, node.e.k);
1515
+ validateNodeList(node, node.e.v);
1420
1516
  for (let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length; i < len; i++) result.set(deserialize$1(ctx, depth, keys[i]), deserialize$1(ctx, depth, vals[i]));
1421
1517
  return result;
1422
1518
  }
@@ -1507,21 +1603,20 @@ function deserializePromiseFulfill(ctx, depth, node) {
1507
1603
  function deserializeIteratorFactoryInstance(ctx, depth, node) {
1508
1604
  deserialize$1(ctx, depth, node.a[0]);
1509
1605
  const source = deserialize$1(ctx, depth, node.a[1]);
1510
- validateNodeType(ctx, node, node.a[1].i, 35);
1511
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1606
+ if (!isSequence(source)) throw new SerovalMalformedNodeError(node.a[1]);
1512
1607
  return sequenceToIterator(source);
1513
1608
  }
1514
1609
  function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1515
1610
  deserialize$1(ctx, depth, node.a[0]);
1516
1611
  const source = deserialize$1(ctx, depth, node.a[1]);
1517
- validateNodeType(ctx, node, node.a[1].i, 31);
1518
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1612
+ if (!isStream(source)) throw new SerovalMalformedNodeError(node.a[1]);
1519
1613
  return streamToAsyncIterable(source);
1520
1614
  }
1521
1615
  function deserializeStreamConstructor(ctx, depth, node) {
1522
1616
  const result = assignIndexedValue$1(ctx, node.i, createStream());
1523
1617
  assignNodeType(ctx, node.i, 31);
1524
1618
  const items = node.a;
1619
+ validateNodeList(node, items);
1525
1620
  const len = items.length;
1526
1621
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1527
1622
  return result;
@@ -1559,10 +1654,15 @@ function deserializeIteratorFactory(ctx, depth, node) {
1559
1654
  function deserializeAsyncIteratorFactory(ctx, depth, node) {
1560
1655
  deserialize$1(ctx, depth, node.a[1]);
1561
1656
  }
1657
+ function isSequenceIndex(value, size) {
1658
+ return Number.isInteger(value) && value >= -1 && value < size;
1659
+ }
1562
1660
  function deserializeSequence(ctx, depth, node) {
1661
+ validateNodeList(node, node.a);
1662
+ const size = node.a.length;
1663
+ if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1563
1664
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1564
- assignNodeType(ctx, node.i, 35);
1565
- for (let i = 0, len = node.a.length; i < len; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1665
+ for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1566
1666
  return result;
1567
1667
  }
1568
1668
  function deserialize$1(ctx, depth, node) {
package/dist/index.cjs CHANGED
@@ -693,16 +693,26 @@ const ARRAY_BUFFER_CONSTRUCTOR = (b64) => {
693
693
  const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR = /* @__PURE__ */ ARRAY_BUFFER_CONSTRUCTOR.toString();
694
694
  //#endregion
695
695
  //#region src/core/sequence.ts
696
+ /**
697
+ * An internal class rather than a tagged POJO: identity is checked with
698
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
699
+ * The eval-based `deserialize` path still rebuilds a `{__SEROVAL_SEQUENCE__…}`
700
+ * POJO from embedded source - it has no access to this class - so a value read
701
+ * back through `deserialize` is not an instance and, by design, is not treated
702
+ * as a genuine Sequence on re-serialization.
703
+ */
704
+ var Sequence = class {
705
+ constructor(values, throwAt, doneAt) {
706
+ this.v = values;
707
+ this.t = throwAt;
708
+ this.d = doneAt;
709
+ }
710
+ };
696
711
  function isSequence(value) {
697
- return "__SEROVAL_SEQUENCE__" in value;
712
+ return value instanceof Sequence;
698
713
  }
699
714
  function createSequence(values, throwAt, doneAt) {
700
- return {
701
- __SEROVAL_SEQUENCE__: true,
702
- v: values,
703
- t: throwAt,
704
- d: doneAt
705
- };
715
+ return new Sequence(values, throwAt, doneAt);
706
716
  }
707
717
  function createSequenceFromIterable(source) {
708
718
  const values = [];
@@ -718,7 +728,9 @@ function createSequenceFromIterable(source) {
718
728
  }
719
729
  } catch (error) {
720
730
  throwsAt = values.length;
731
+ doneAt = throwsAt;
721
732
  values.push(error);
733
+ break;
722
734
  }
723
735
  return createSequence(values, throwsAt, doneAt);
724
736
  }
@@ -751,11 +763,86 @@ const SPECIAL_REF_STRING = {
751
763
  };
752
764
  //#endregion
753
765
  //#region src/core/stream.ts
766
+ /**
767
+ * An internal class rather than a tagged POJO: identity is checked with
768
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
769
+ *
770
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
771
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
772
+ * output, which has no access to this class, so the two cannot be shared. A
773
+ * stream read back through `deserialize` is therefore a plain POJO and, by
774
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
775
+ * implementations in sync.
776
+ */
777
+ var Stream = class {
778
+ constructor() {
779
+ this.buffer = [];
780
+ this.listeners = [];
781
+ this.alive = true;
782
+ this.success = false;
783
+ this.count = 0;
784
+ }
785
+ flush(value, mode) {
786
+ for (let x = 0; x < this.count; x++) {
787
+ var _this$listeners$x;
788
+ (_this$listeners$x = this.listeners[x]) === null || _this$listeners$x === void 0 || _this$listeners$x[mode](value);
789
+ }
790
+ }
791
+ replay(listener) {
792
+ for (let x = 0, z = this.buffer.length; x < z; x++) {
793
+ const current = this.buffer[x];
794
+ if (!this.alive && x === z - 1) listener[this.success ? "return" : "throw"](current);
795
+ else listener.next(current);
796
+ }
797
+ }
798
+ on(listener) {
799
+ let subscribed = this.alive;
800
+ let temp = 0;
801
+ if (subscribed) {
802
+ for (; temp < this.count; temp++) if (!this.listeners[temp]) break;
803
+ if (temp === this.count) this.count++;
804
+ this.listeners[temp] = listener;
805
+ }
806
+ this.replay(listener);
807
+ return () => {
808
+ if (this.alive && subscribed) {
809
+ subscribed = false;
810
+ this.listeners[temp] = void 0;
811
+ while (this.count > 0 && !this.listeners[this.count - 1]) this.count--;
812
+ this.listeners.length = this.count;
813
+ }
814
+ };
815
+ }
816
+ next(value) {
817
+ if (this.alive) {
818
+ this.buffer.push(value);
819
+ this.flush(value, "next");
820
+ }
821
+ }
822
+ throw(value) {
823
+ if (this.alive) {
824
+ this.buffer.push(value);
825
+ this.flush(value, "throw");
826
+ this.alive = false;
827
+ this.success = false;
828
+ this.listeners.length = 0;
829
+ }
830
+ }
831
+ return(value) {
832
+ if (this.alive) {
833
+ this.buffer.push(value);
834
+ this.flush(value, "return");
835
+ this.alive = false;
836
+ this.success = true;
837
+ this.listeners.length = 0;
838
+ }
839
+ }
840
+ };
754
841
  function isStream(value) {
755
- return "__SEROVAL_STREAM__" in value;
842
+ return value instanceof Stream;
756
843
  }
757
844
  function createStream() {
758
- return STREAM_CONSTRUCTOR();
845
+ return new Stream();
759
846
  }
760
847
  function createStreamFromAsyncIterable(iterable, cleanups) {
761
848
  const stream = createStream();
@@ -1287,7 +1374,7 @@ function guardIndexedValue(ctx, id) {
1287
1374
  if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1288
1375
  }
1289
1376
  function isThennable(value) {
1290
- return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
1377
+ return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1291
1378
  }
1292
1379
  function assignIndexedValueVanilla(ctx, id, value) {
1293
1380
  guardIndexedValue(ctx.base, id);
@@ -1309,8 +1396,12 @@ function deserializeKnownValue(node, record, key) {
1309
1396
  function deserializeReference(ctx, node) {
1310
1397
  return assignIndexedValue$1(ctx, node.i, getReference(deserializeString(node.s)));
1311
1398
  }
1399
+ function validateNodeList(node, list) {
1400
+ if (!Array.isArray(list)) throw new SerovalMalformedNodeError(node);
1401
+ }
1312
1402
  function deserializeArray(ctx, depth, node) {
1313
1403
  const items = node.a;
1404
+ validateNodeList(node, items);
1314
1405
  const len = items.length;
1315
1406
  const result = assignIndexedValue$1(ctx, node.i, new Array(len));
1316
1407
  for (let i = 0, item; i < len; i++) {
@@ -1352,6 +1443,8 @@ function validateNodeType(ctx, node, id, type) {
1352
1443
  }
1353
1444
  function deserializeProperties(ctx, depth, node, result) {
1354
1445
  const keys = node.k;
1446
+ validateNodeList(node, keys);
1447
+ validateNodeList(node, node.v);
1355
1448
  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]);
1356
1449
  return result;
1357
1450
  }
@@ -1406,11 +1499,14 @@ function deserializeRegExp(ctx, node) {
1406
1499
  }
1407
1500
  function deserializeSet(ctx, depth, node) {
1408
1501
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Set());
1502
+ validateNodeList(node, node.a);
1409
1503
  for (let i = 0, items = node.a, len = items.length; i < len; i++) result.add(deserialize$1(ctx, depth, items[i]));
1410
1504
  return result;
1411
1505
  }
1412
1506
  function deserializeMap(ctx, depth, node) {
1413
1507
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Map());
1508
+ validateNodeList(node, node.e.k);
1509
+ validateNodeList(node, node.e.v);
1414
1510
  for (let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length; i < len; i++) result.set(deserialize$1(ctx, depth, keys[i]), deserialize$1(ctx, depth, vals[i]));
1415
1511
  return result;
1416
1512
  }
@@ -1501,21 +1597,20 @@ function deserializePromiseFulfill(ctx, depth, node) {
1501
1597
  function deserializeIteratorFactoryInstance(ctx, depth, node) {
1502
1598
  deserialize$1(ctx, depth, node.a[0]);
1503
1599
  const source = deserialize$1(ctx, depth, node.a[1]);
1504
- validateNodeType(ctx, node, node.a[1].i, 35);
1505
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1600
+ if (!isSequence(source)) throw new SerovalMalformedNodeError(node.a[1]);
1506
1601
  return sequenceToIterator(source);
1507
1602
  }
1508
1603
  function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1509
1604
  deserialize$1(ctx, depth, node.a[0]);
1510
1605
  const source = deserialize$1(ctx, depth, node.a[1]);
1511
- validateNodeType(ctx, node, node.a[1].i, 31);
1512
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1606
+ if (!isStream(source)) throw new SerovalMalformedNodeError(node.a[1]);
1513
1607
  return streamToAsyncIterable(source);
1514
1608
  }
1515
1609
  function deserializeStreamConstructor(ctx, depth, node) {
1516
1610
  const result = assignIndexedValue$1(ctx, node.i, createStream());
1517
1611
  assignNodeType(ctx, node.i, 31);
1518
1612
  const items = node.a;
1613
+ validateNodeList(node, items);
1519
1614
  const len = items.length;
1520
1615
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1521
1616
  return result;
@@ -1553,10 +1648,15 @@ function deserializeIteratorFactory(ctx, depth, node) {
1553
1648
  function deserializeAsyncIteratorFactory(ctx, depth, node) {
1554
1649
  deserialize$1(ctx, depth, node.a[1]);
1555
1650
  }
1651
+ function isSequenceIndex(value, size) {
1652
+ return Number.isInteger(value) && value >= -1 && value < size;
1653
+ }
1556
1654
  function deserializeSequence(ctx, depth, node) {
1655
+ validateNodeList(node, node.a);
1656
+ const size = node.a.length;
1657
+ if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1557
1658
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1558
- assignNodeType(ctx, node.i, 35);
1559
- for (let i = 0, len = node.a.length; i < len; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1659
+ for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1560
1660
  return result;
1561
1661
  }
1562
1662
  function deserialize$1(ctx, depth, node) {
package/dist/index.d.cts CHANGED
@@ -737,14 +737,31 @@ interface StreamListener<T> {
737
737
  throw(value: unknown): void;
738
738
  return(value: T): void;
739
739
  }
740
- interface Stream<T> {
741
- __SEROVAL_STREAM__: true;
740
+ /**
741
+ * An internal class rather than a tagged POJO: identity is checked with
742
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
743
+ *
744
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
745
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
746
+ * output, which has no access to this class, so the two cannot be shared. A
747
+ * stream read back through `deserialize` is therefore a plain POJO and, by
748
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
749
+ * implementations in sync.
750
+ */
751
+ declare class Stream<T> {
752
+ private buffer;
753
+ private listeners;
754
+ private alive;
755
+ private success;
756
+ private count;
757
+ private flush;
758
+ private replay;
742
759
  on(listener: StreamListener<T>): () => void;
743
760
  next(value: T): void;
744
761
  throw(value: unknown): void;
745
762
  return(value: T): void;
746
763
  }
747
- declare function isStream<T>(value: object): value is Stream<T>;
764
+ declare function isStream<T>(value: unknown): value is Stream<T>;
748
765
  declare function createStream<T>(): Stream<T>;
749
766
  //#endregion
750
767
  //#region src/core/tree/index.d.ts
package/dist/index.d.ts CHANGED
@@ -737,14 +737,31 @@ interface StreamListener<T> {
737
737
  throw(value: unknown): void;
738
738
  return(value: T): void;
739
739
  }
740
- interface Stream<T> {
741
- __SEROVAL_STREAM__: true;
740
+ /**
741
+ * An internal class rather than a tagged POJO: identity is checked with
742
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
743
+ *
744
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
745
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
746
+ * output, which has no access to this class, so the two cannot be shared. A
747
+ * stream read back through `deserialize` is therefore a plain POJO and, by
748
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
749
+ * implementations in sync.
750
+ */
751
+ declare class Stream<T> {
752
+ private buffer;
753
+ private listeners;
754
+ private alive;
755
+ private success;
756
+ private count;
757
+ private flush;
758
+ private replay;
742
759
  on(listener: StreamListener<T>): () => void;
743
760
  next(value: T): void;
744
761
  throw(value: unknown): void;
745
762
  return(value: T): void;
746
763
  }
747
- declare function isStream<T>(value: object): value is Stream<T>;
764
+ declare function isStream<T>(value: unknown): value is Stream<T>;
748
765
  declare function createStream<T>(): Stream<T>;
749
766
  //#endregion
750
767
  //#region src/core/tree/index.d.ts
package/dist/index.js CHANGED
@@ -692,16 +692,26 @@ const ARRAY_BUFFER_CONSTRUCTOR = (b64) => {
692
692
  const SERIALIZED_ARRAY_BUFFER_CONSTRUCTOR = /* @__PURE__ */ ARRAY_BUFFER_CONSTRUCTOR.toString();
693
693
  //#endregion
694
694
  //#region src/core/sequence.ts
695
+ /**
696
+ * An internal class rather than a tagged POJO: identity is checked with
697
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
698
+ * The eval-based `deserialize` path still rebuilds a `{__SEROVAL_SEQUENCE__…}`
699
+ * POJO from embedded source - it has no access to this class - so a value read
700
+ * back through `deserialize` is not an instance and, by design, is not treated
701
+ * as a genuine Sequence on re-serialization.
702
+ */
703
+ var Sequence = class {
704
+ constructor(values, throwAt, doneAt) {
705
+ this.v = values;
706
+ this.t = throwAt;
707
+ this.d = doneAt;
708
+ }
709
+ };
695
710
  function isSequence(value) {
696
- return "__SEROVAL_SEQUENCE__" in value;
711
+ return value instanceof Sequence;
697
712
  }
698
713
  function createSequence(values, throwAt, doneAt) {
699
- return {
700
- __SEROVAL_SEQUENCE__: true,
701
- v: values,
702
- t: throwAt,
703
- d: doneAt
704
- };
714
+ return new Sequence(values, throwAt, doneAt);
705
715
  }
706
716
  function createSequenceFromIterable(source) {
707
717
  const values = [];
@@ -717,7 +727,9 @@ function createSequenceFromIterable(source) {
717
727
  }
718
728
  } catch (error) {
719
729
  throwsAt = values.length;
730
+ doneAt = throwsAt;
720
731
  values.push(error);
732
+ break;
721
733
  }
722
734
  return createSequence(values, throwsAt, doneAt);
723
735
  }
@@ -750,11 +762,86 @@ const SPECIAL_REF_STRING = {
750
762
  };
751
763
  //#endregion
752
764
  //#region src/core/stream.ts
765
+ /**
766
+ * An internal class rather than a tagged POJO: identity is checked with
767
+ * `instanceof`, which untrusted input cannot forge (the class is not exported).
768
+ *
769
+ * The behavior is intentionally duplicated from `STREAM_CONSTRUCTOR`. That
770
+ * constructor's source is embedded verbatim into the eval-based `deserialize`
771
+ * output, which has no access to this class, so the two cannot be shared. A
772
+ * stream read back through `deserialize` is therefore a plain POJO and, by
773
+ * design, is not treated as a genuine Stream on re-serialization. Keep the two
774
+ * implementations in sync.
775
+ */
776
+ var Stream = class {
777
+ constructor() {
778
+ this.buffer = [];
779
+ this.listeners = [];
780
+ this.alive = true;
781
+ this.success = false;
782
+ this.count = 0;
783
+ }
784
+ flush(value, mode) {
785
+ for (let x = 0; x < this.count; x++) {
786
+ var _this$listeners$x;
787
+ (_this$listeners$x = this.listeners[x]) === null || _this$listeners$x === void 0 || _this$listeners$x[mode](value);
788
+ }
789
+ }
790
+ replay(listener) {
791
+ for (let x = 0, z = this.buffer.length; x < z; x++) {
792
+ const current = this.buffer[x];
793
+ if (!this.alive && x === z - 1) listener[this.success ? "return" : "throw"](current);
794
+ else listener.next(current);
795
+ }
796
+ }
797
+ on(listener) {
798
+ let subscribed = this.alive;
799
+ let temp = 0;
800
+ if (subscribed) {
801
+ for (; temp < this.count; temp++) if (!this.listeners[temp]) break;
802
+ if (temp === this.count) this.count++;
803
+ this.listeners[temp] = listener;
804
+ }
805
+ this.replay(listener);
806
+ return () => {
807
+ if (this.alive && subscribed) {
808
+ subscribed = false;
809
+ this.listeners[temp] = void 0;
810
+ while (this.count > 0 && !this.listeners[this.count - 1]) this.count--;
811
+ this.listeners.length = this.count;
812
+ }
813
+ };
814
+ }
815
+ next(value) {
816
+ if (this.alive) {
817
+ this.buffer.push(value);
818
+ this.flush(value, "next");
819
+ }
820
+ }
821
+ throw(value) {
822
+ if (this.alive) {
823
+ this.buffer.push(value);
824
+ this.flush(value, "throw");
825
+ this.alive = false;
826
+ this.success = false;
827
+ this.listeners.length = 0;
828
+ }
829
+ }
830
+ return(value) {
831
+ if (this.alive) {
832
+ this.buffer.push(value);
833
+ this.flush(value, "return");
834
+ this.alive = false;
835
+ this.success = true;
836
+ this.listeners.length = 0;
837
+ }
838
+ }
839
+ };
753
840
  function isStream(value) {
754
- return "__SEROVAL_STREAM__" in value;
841
+ return value instanceof Stream;
755
842
  }
756
843
  function createStream() {
757
- return STREAM_CONSTRUCTOR();
844
+ return new Stream();
758
845
  }
759
846
  function createStreamFromAsyncIterable(iterable, cleanups) {
760
847
  const stream = createStream();
@@ -1286,7 +1373,7 @@ function guardIndexedValue(ctx, id) {
1286
1373
  if (ctx.refs.has(id)) throw new Error("Conflicted ref id: " + id);
1287
1374
  }
1288
1375
  function isThennable(value) {
1289
- return !!value && typeof value === "object" && "then" in value && typeof value.then === "function";
1376
+ return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
1290
1377
  }
1291
1378
  function assignIndexedValueVanilla(ctx, id, value) {
1292
1379
  guardIndexedValue(ctx.base, id);
@@ -1308,8 +1395,12 @@ function deserializeKnownValue(node, record, key) {
1308
1395
  function deserializeReference(ctx, node) {
1309
1396
  return assignIndexedValue$1(ctx, node.i, getReference(deserializeString(node.s)));
1310
1397
  }
1398
+ function validateNodeList(node, list) {
1399
+ if (!Array.isArray(list)) throw new SerovalMalformedNodeError(node);
1400
+ }
1311
1401
  function deserializeArray(ctx, depth, node) {
1312
1402
  const items = node.a;
1403
+ validateNodeList(node, items);
1313
1404
  const len = items.length;
1314
1405
  const result = assignIndexedValue$1(ctx, node.i, new Array(len));
1315
1406
  for (let i = 0, item; i < len; i++) {
@@ -1351,6 +1442,8 @@ function validateNodeType(ctx, node, id, type) {
1351
1442
  }
1352
1443
  function deserializeProperties(ctx, depth, node, result) {
1353
1444
  const keys = node.k;
1445
+ validateNodeList(node, keys);
1446
+ validateNodeList(node, node.v);
1354
1447
  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]);
1355
1448
  return result;
1356
1449
  }
@@ -1405,11 +1498,14 @@ function deserializeRegExp(ctx, node) {
1405
1498
  }
1406
1499
  function deserializeSet(ctx, depth, node) {
1407
1500
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Set());
1501
+ validateNodeList(node, node.a);
1408
1502
  for (let i = 0, items = node.a, len = items.length; i < len; i++) result.add(deserialize$1(ctx, depth, items[i]));
1409
1503
  return result;
1410
1504
  }
1411
1505
  function deserializeMap(ctx, depth, node) {
1412
1506
  const result = assignIndexedValue$1(ctx, node.i, /* @__PURE__ */ new Map());
1507
+ validateNodeList(node, node.e.k);
1508
+ validateNodeList(node, node.e.v);
1413
1509
  for (let i = 0, keys = node.e.k, vals = node.e.v, len = keys.length; i < len; i++) result.set(deserialize$1(ctx, depth, keys[i]), deserialize$1(ctx, depth, vals[i]));
1414
1510
  return result;
1415
1511
  }
@@ -1500,21 +1596,20 @@ function deserializePromiseFulfill(ctx, depth, node) {
1500
1596
  function deserializeIteratorFactoryInstance(ctx, depth, node) {
1501
1597
  deserialize$1(ctx, depth, node.a[0]);
1502
1598
  const source = deserialize$1(ctx, depth, node.a[1]);
1503
- validateNodeType(ctx, node, node.a[1].i, 35);
1504
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1599
+ if (!isSequence(source)) throw new SerovalMalformedNodeError(node.a[1]);
1505
1600
  return sequenceToIterator(source);
1506
1601
  }
1507
1602
  function deserializeAsyncIteratorFactoryInstance(ctx, depth, node) {
1508
1603
  deserialize$1(ctx, depth, node.a[0]);
1509
1604
  const source = deserialize$1(ctx, depth, node.a[1]);
1510
- validateNodeType(ctx, node, node.a[1].i, 31);
1511
- if (!source) throw new SerovalMalformedNodeError(node.a[1]);
1605
+ if (!isStream(source)) throw new SerovalMalformedNodeError(node.a[1]);
1512
1606
  return streamToAsyncIterable(source);
1513
1607
  }
1514
1608
  function deserializeStreamConstructor(ctx, depth, node) {
1515
1609
  const result = assignIndexedValue$1(ctx, node.i, createStream());
1516
1610
  assignNodeType(ctx, node.i, 31);
1517
1611
  const items = node.a;
1612
+ validateNodeList(node, items);
1518
1613
  const len = items.length;
1519
1614
  if (len) for (let i = 0; i < len; i++) deserialize$1(ctx, depth, items[i]);
1520
1615
  return result;
@@ -1552,10 +1647,15 @@ function deserializeIteratorFactory(ctx, depth, node) {
1552
1647
  function deserializeAsyncIteratorFactory(ctx, depth, node) {
1553
1648
  deserialize$1(ctx, depth, node.a[1]);
1554
1649
  }
1650
+ function isSequenceIndex(value, size) {
1651
+ return Number.isInteger(value) && value >= -1 && value < size;
1652
+ }
1555
1653
  function deserializeSequence(ctx, depth, node) {
1654
+ validateNodeList(node, node.a);
1655
+ const size = node.a.length;
1656
+ if (!(isSequenceIndex(node.s, size) && isSequenceIndex(node.l, size))) throw new SerovalMalformedNodeError(node);
1556
1657
  const result = assignIndexedValue$1(ctx, node.i, createSequence([], node.s, node.l));
1557
- assignNodeType(ctx, node.i, 35);
1558
- for (let i = 0, len = node.a.length; i < len; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1658
+ for (let i = 0; i < size; i++) result.v[i] = deserialize$1(ctx, depth, node.a[i]);
1559
1659
  return result;
1560
1660
  }
1561
1661
  function deserialize$1(ctx, depth, node) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "seroval",
3
3
  "type": "module",
4
- "version": "1.6.7",
4
+ "version": "1.6.9",
5
5
  "files": [
6
6
  "dist"
7
7
  ],