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.
- package/dist/dev/index.cjs +116 -16
- package/dist/dev/index.d.cts +20 -3
- package/dist/dev/index.d.ts +20 -3
- package/dist/dev/index.js +116 -16
- package/dist/index.cjs +116 -16
- package/dist/index.d.cts +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.js +116 -16
- package/package.json +1 -1
package/dist/dev/index.cjs
CHANGED
|
@@ -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
|
|
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
|
|
849
|
+
return value instanceof Stream;
|
|
763
850
|
}
|
|
764
851
|
function createStream() {
|
|
765
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|
package/dist/dev/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
|
-
|
|
741
|
-
|
|
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:
|
|
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.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
|
-
|
|
741
|
-
|
|
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:
|
|
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
|
|
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
|
|
848
|
+
return value instanceof Stream;
|
|
762
849
|
}
|
|
763
850
|
function createStream() {
|
|
764
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
842
|
+
return value instanceof Stream;
|
|
756
843
|
}
|
|
757
844
|
function createStream() {
|
|
758
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
741
|
-
|
|
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:
|
|
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
|
-
|
|
741
|
-
|
|
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:
|
|
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
|
|
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
|
|
841
|
+
return value instanceof Stream;
|
|
755
842
|
}
|
|
756
843
|
function createStream() {
|
|
757
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|