msgpackr 1.10.0 → 1.10.2
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/README.md +1 -0
- package/dist/index-no-eval.cjs +41 -19
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +41 -19
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +41 -19
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +75 -20
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +21 -4
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +1 -0
- package/index.d.ts +1 -0
- package/pack.js +20 -15
- package/package.json +1 -1
- package/unpack.js +21 -4
package/dist/test.js
CHANGED
|
@@ -910,7 +910,7 @@
|
|
|
910
910
|
return readFixedString(length)
|
|
911
911
|
} else { // not cacheable, go back and do a standard read
|
|
912
912
|
position$1--;
|
|
913
|
-
return read()
|
|
913
|
+
return asSafeString(read())
|
|
914
914
|
}
|
|
915
915
|
let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
|
|
916
916
|
let entry = keyCache[key];
|
|
@@ -962,9 +962,17 @@
|
|
|
962
962
|
return entry.string = readFixedString(length)
|
|
963
963
|
}
|
|
964
964
|
|
|
965
|
+
function asSafeString(property) {
|
|
966
|
+
// protect against expensive (DoS) string conversions
|
|
967
|
+
if (typeof property === 'string') return property;
|
|
968
|
+
if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
|
|
969
|
+
if (property == null) return property + '';
|
|
970
|
+
throw new Error('Invalid property type for record', typeof property);
|
|
971
|
+
}
|
|
965
972
|
// the registration of the record definition extension (as "r")
|
|
966
973
|
const recordDefinition = (id, highByte) => {
|
|
967
|
-
let structure = read().map(
|
|
974
|
+
let structure = read().map(asSafeString); // ensure that all keys are strings and
|
|
975
|
+
// that the array is mutable
|
|
968
976
|
let firstByte = id;
|
|
969
977
|
if (highByte !== undefined) {
|
|
970
978
|
id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
|
|
@@ -998,11 +1006,12 @@
|
|
|
998
1006
|
let errors = { Error, TypeError, ReferenceError };
|
|
999
1007
|
currentExtensions[0x65] = () => {
|
|
1000
1008
|
let data = read();
|
|
1001
|
-
return (errors[data[0]] || Error)(data[1])
|
|
1009
|
+
return (errors[data[0]] || Error)(data[1], { cause: data[2] })
|
|
1002
1010
|
};
|
|
1003
1011
|
|
|
1004
1012
|
currentExtensions[0x69] = (data) => {
|
|
1005
1013
|
// id extension (for structured clones)
|
|
1014
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
1006
1015
|
let id = dataView.getUint32(position$1 - 4);
|
|
1007
1016
|
if (!referenceMap)
|
|
1008
1017
|
referenceMap = new Map();
|
|
@@ -1026,6 +1035,7 @@
|
|
|
1026
1035
|
|
|
1027
1036
|
currentExtensions[0x70] = (data) => {
|
|
1028
1037
|
// pointer extension (for structured clones)
|
|
1038
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
1029
1039
|
let id = dataView.getUint32(position$1 - 4);
|
|
1030
1040
|
let refEntry = referenceMap.get(id);
|
|
1031
1041
|
refEntry.used = true;
|
|
@@ -1040,8 +1050,15 @@
|
|
|
1040
1050
|
currentExtensions[0x74] = (data) => {
|
|
1041
1051
|
let typeCode = data[0];
|
|
1042
1052
|
let typedArrayName = typedArrays[typeCode];
|
|
1043
|
-
if (!typedArrayName)
|
|
1053
|
+
if (!typedArrayName) {
|
|
1054
|
+
if (typeCode === 16) {
|
|
1055
|
+
let ab = new ArrayBuffer(data.length - 1);
|
|
1056
|
+
let u8 = new Uint8Array(ab);
|
|
1057
|
+
u8.set(data.subarray(1));
|
|
1058
|
+
return ab;
|
|
1059
|
+
}
|
|
1044
1060
|
throw new Error('Could not find typed array for code ' + typeCode)
|
|
1061
|
+
}
|
|
1045
1062
|
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
1046
1063
|
return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
1047
1064
|
};
|
|
@@ -1347,10 +1364,14 @@
|
|
|
1347
1364
|
return packr.pack(value, encodeOptions)
|
|
1348
1365
|
}
|
|
1349
1366
|
packr.lastNamedStructuresLength = sharedLength;
|
|
1367
|
+
// don't keep large buffers around
|
|
1368
|
+
if (target.length > 0x40000000) target = null;
|
|
1350
1369
|
return returnBuffer
|
|
1351
1370
|
}
|
|
1352
1371
|
}
|
|
1353
1372
|
}
|
|
1373
|
+
// don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
|
|
1374
|
+
if (target.length > 0x40000000) target = null;
|
|
1354
1375
|
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1355
1376
|
position = start;
|
|
1356
1377
|
}
|
|
@@ -1573,7 +1594,7 @@
|
|
|
1573
1594
|
}
|
|
1574
1595
|
let constructor = value.constructor;
|
|
1575
1596
|
if (constructor === Object) {
|
|
1576
|
-
writeObject(value
|
|
1597
|
+
writeObject(value);
|
|
1577
1598
|
} else if (constructor === Array) {
|
|
1578
1599
|
packArray(value);
|
|
1579
1600
|
} else if (constructor === Map) {
|
|
@@ -1669,8 +1690,8 @@
|
|
|
1669
1690
|
if (type === 'function')
|
|
1670
1691
|
return pack(this.writeFunction && this.writeFunction(value));
|
|
1671
1692
|
|
|
1672
|
-
// no extension found, write as object
|
|
1673
|
-
writeObject(value
|
|
1693
|
+
// no extension found, write as plain object
|
|
1694
|
+
writeObject(value);
|
|
1674
1695
|
}
|
|
1675
1696
|
}
|
|
1676
1697
|
}
|
|
@@ -1757,13 +1778,13 @@
|
|
|
1757
1778
|
}
|
|
1758
1779
|
}
|
|
1759
1780
|
} :
|
|
1760
|
-
(object
|
|
1781
|
+
(object) => {
|
|
1761
1782
|
target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
|
|
1762
1783
|
let objectOffset = position - start;
|
|
1763
1784
|
position += 2;
|
|
1764
1785
|
let size = 0;
|
|
1765
1786
|
for (let key in object) {
|
|
1766
|
-
if (
|
|
1787
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1767
1788
|
pack(key);
|
|
1768
1789
|
pack(object[key]);
|
|
1769
1790
|
size++;
|
|
@@ -1775,12 +1796,12 @@
|
|
|
1775
1796
|
|
|
1776
1797
|
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
1777
1798
|
(options.progressiveRecords && !useTwoByteRecords) ? // this is about 2% faster for highly stable structures, since it only requires one for-in loop (but much more expensive when new structure needs to be written)
|
|
1778
|
-
(object
|
|
1799
|
+
(object) => {
|
|
1779
1800
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1780
1801
|
let objectOffset = position++ - start;
|
|
1781
1802
|
let wroteKeys;
|
|
1782
1803
|
for (let key in object) {
|
|
1783
|
-
if (
|
|
1804
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1784
1805
|
nextTransition = transition[key];
|
|
1785
1806
|
if (nextTransition)
|
|
1786
1807
|
transition = nextTransition;
|
|
@@ -1819,10 +1840,10 @@
|
|
|
1819
1840
|
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1820
1841
|
}
|
|
1821
1842
|
} :
|
|
1822
|
-
(object
|
|
1843
|
+
(object) => {
|
|
1823
1844
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1824
1845
|
let newTransitions = 0;
|
|
1825
|
-
for (let key in object) if (
|
|
1846
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1826
1847
|
nextTransition = transition[key];
|
|
1827
1848
|
if (!nextTransition) {
|
|
1828
1849
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1842,7 +1863,7 @@
|
|
|
1842
1863
|
}
|
|
1843
1864
|
// now write the values
|
|
1844
1865
|
for (let key in object)
|
|
1845
|
-
if (
|
|
1866
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1846
1867
|
pack(object[key]);
|
|
1847
1868
|
}
|
|
1848
1869
|
};
|
|
@@ -1850,8 +1871,8 @@
|
|
|
1850
1871
|
// craete reference to useRecords if useRecords is a function
|
|
1851
1872
|
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
1852
1873
|
|
|
1853
|
-
const writeObject = checkUseRecords ? (object
|
|
1854
|
-
checkUseRecords(object) ? writeRecord(object
|
|
1874
|
+
const writeObject = checkUseRecords ? (object) => {
|
|
1875
|
+
checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
|
|
1855
1876
|
} : writeRecord;
|
|
1856
1877
|
|
|
1857
1878
|
const makeRoom = (end) => {
|
|
@@ -1956,7 +1977,7 @@
|
|
|
1956
1977
|
target[insertionOffset + start] = keysTarget[0];
|
|
1957
1978
|
}
|
|
1958
1979
|
};
|
|
1959
|
-
const writeStruct = (object
|
|
1980
|
+
const writeStruct = (object) => {
|
|
1960
1981
|
let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
|
|
1961
1982
|
if (notifySharedUpdate)
|
|
1962
1983
|
return hasSharedUpdate = true;
|
|
@@ -1970,7 +1991,7 @@
|
|
|
1970
1991
|
return position;
|
|
1971
1992
|
}, this);
|
|
1972
1993
|
if (newPosition === 0) // bail and go to a msgpack object
|
|
1973
|
-
return writeObject(object
|
|
1994
|
+
return writeObject(object);
|
|
1974
1995
|
position = newPosition;
|
|
1975
1996
|
};
|
|
1976
1997
|
}
|
|
@@ -2048,7 +2069,7 @@
|
|
|
2048
2069
|
target[position++] = 0x65; // 'e' for error
|
|
2049
2070
|
target[position++] = 0;
|
|
2050
2071
|
}
|
|
2051
|
-
pack([ error.name, error.message ]);
|
|
2072
|
+
pack([ error.name, error.message, error.cause ]);
|
|
2052
2073
|
}
|
|
2053
2074
|
}, {
|
|
2054
2075
|
pack(regex, allocateForWrite, pack) {
|
|
@@ -2101,6 +2122,7 @@
|
|
|
2101
2122
|
}
|
|
2102
2123
|
target[position++] = 0x74; // "t" for typed array
|
|
2103
2124
|
target[position++] = type;
|
|
2125
|
+
if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
|
|
2104
2126
|
target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
|
|
2105
2127
|
}
|
|
2106
2128
|
function writeBuffer(buffer, allocateForWrite) {
|
|
@@ -3703,13 +3725,35 @@
|
|
|
3703
3725
|
}
|
|
3704
3726
|
});
|
|
3705
3727
|
|
|
3728
|
+
test('moreTyesp: Error with causes', function() {
|
|
3729
|
+
const object = {
|
|
3730
|
+
error: new Error('test'),
|
|
3731
|
+
errorWithCause: new Error('test-1', { cause: new Error('test-2')}),
|
|
3732
|
+
};
|
|
3733
|
+
const packr = new Packr({
|
|
3734
|
+
moreTypes: true,
|
|
3735
|
+
});
|
|
3736
|
+
|
|
3737
|
+
const serialized = packr.pack(object);
|
|
3738
|
+
const deserialized = packr.unpack(serialized);
|
|
3739
|
+
assert.equal(deserialized.error.message, object.error.message);
|
|
3740
|
+
assert.equal(deserialized.error.cause, object.error.cause);
|
|
3741
|
+
assert.equal(deserialized.errorWithCause.message, object.errorWithCause.message);
|
|
3742
|
+
assert.equal(deserialized.errorWithCause.cause.message, object.errorWithCause.cause.message);
|
|
3743
|
+
assert.equal(deserialized.errorWithCause.cause.cause, object.errorWithCause.cause.cause);
|
|
3744
|
+
});
|
|
3745
|
+
|
|
3706
3746
|
test('structured cloning: self reference', function() {
|
|
3707
3747
|
let object = {
|
|
3708
3748
|
test: 'string',
|
|
3709
3749
|
children: [
|
|
3710
3750
|
{ name: 'child' }
|
|
3711
|
-
]
|
|
3751
|
+
],
|
|
3752
|
+
value: new ArrayBuffer(10)
|
|
3712
3753
|
};
|
|
3754
|
+
let u8 = new Uint8Array(object.value);
|
|
3755
|
+
u8[0] = 1;
|
|
3756
|
+
u8[1] = 2;
|
|
3713
3757
|
object.self = object;
|
|
3714
3758
|
object.children[1] = object;
|
|
3715
3759
|
object.children[2] = object.children[0];
|
|
@@ -3725,6 +3769,10 @@
|
|
|
3725
3769
|
assert.equal(deserialized.children[1], deserialized);
|
|
3726
3770
|
assert.equal(deserialized.children[0], deserialized.children[2]);
|
|
3727
3771
|
assert.equal(deserialized.children, deserialized.childrenAgain);
|
|
3772
|
+
assert.equal(deserialized.value.constructor.name, 'ArrayBuffer');
|
|
3773
|
+
u8 = new Uint8Array(deserialized.value);
|
|
3774
|
+
assert.equal(u8[0], 1);
|
|
3775
|
+
assert.equal(u8[1], 2);
|
|
3728
3776
|
});
|
|
3729
3777
|
|
|
3730
3778
|
test('structured cloning: types', function() {
|
|
@@ -3805,6 +3853,13 @@
|
|
|
3805
3853
|
assert.deepEqual(deserialized, data);
|
|
3806
3854
|
});
|
|
3807
3855
|
|
|
3856
|
+
test('object with __proto__', function(){
|
|
3857
|
+
const data = { foo: 'bar', __proto__: { isAdmin: true } };
|
|
3858
|
+
var serialized = pack(data);
|
|
3859
|
+
var deserialized = unpack(serialized);
|
|
3860
|
+
assert.deepEqual(deserialized, { foo: 'bar' });
|
|
3861
|
+
});
|
|
3862
|
+
|
|
3808
3863
|
test('separate instances', function() {
|
|
3809
3864
|
const packr = new Packr({
|
|
3810
3865
|
structures: [['m', 'e'], ['action', 'share']]
|