msgpackr 1.10.1 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index-no-eval.cjs +61 -29
- 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 +61 -29
- 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 +61 -29
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +143 -30
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +12 -3
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +19 -9
- package/index.d.ts +19 -9
- package/index.js +1 -1
- package/pack.js +47 -32
- package/package.json +1 -1
- package/struct.js +2 -0
- package/unpack.js +12 -3
package/dist/node.cjs
CHANGED
|
@@ -967,8 +967,10 @@ function readKey() {
|
|
|
967
967
|
}
|
|
968
968
|
|
|
969
969
|
function asSafeString(property) {
|
|
970
|
+
// protect against expensive (DoS) string conversions
|
|
970
971
|
if (typeof property === 'string') return property;
|
|
971
|
-
if (typeof property === 'number') return property.toString();
|
|
972
|
+
if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
|
|
973
|
+
if (property == null) return property + '';
|
|
972
974
|
throw new Error('Invalid property type for record', typeof property);
|
|
973
975
|
}
|
|
974
976
|
// the registration of the record definition extension (as "r")
|
|
@@ -1008,7 +1010,7 @@ currentExtensions[0x42] = (data) => {
|
|
|
1008
1010
|
let errors = { Error, TypeError, ReferenceError };
|
|
1009
1011
|
currentExtensions[0x65] = () => {
|
|
1010
1012
|
let data = read();
|
|
1011
|
-
return (errors[data[0]] || Error)(data[1])
|
|
1013
|
+
return (errors[data[0]] || Error)(data[1], { cause: data[2] })
|
|
1012
1014
|
};
|
|
1013
1015
|
|
|
1014
1016
|
currentExtensions[0x69] = (data) => {
|
|
@@ -1052,8 +1054,15 @@ let glbl = typeof globalThis === 'object' ? globalThis : window;
|
|
|
1052
1054
|
currentExtensions[0x74] = (data) => {
|
|
1053
1055
|
let typeCode = data[0];
|
|
1054
1056
|
let typedArrayName = typedArrays[typeCode];
|
|
1055
|
-
if (!typedArrayName)
|
|
1057
|
+
if (!typedArrayName) {
|
|
1058
|
+
if (typeCode === 16) {
|
|
1059
|
+
let ab = new ArrayBuffer(data.length - 1);
|
|
1060
|
+
let u8 = new Uint8Array(ab);
|
|
1061
|
+
u8.set(data.subarray(1));
|
|
1062
|
+
return ab;
|
|
1063
|
+
}
|
|
1056
1064
|
throw new Error('Could not find typed array for code ' + typeCode)
|
|
1065
|
+
}
|
|
1057
1066
|
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
1058
1067
|
return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
1059
1068
|
};
|
|
@@ -1224,7 +1233,7 @@ class Packr extends Unpackr {
|
|
|
1224
1233
|
if (!this.structures && options.useRecords != false)
|
|
1225
1234
|
this.structures = [];
|
|
1226
1235
|
// two byte record ids for shared structures
|
|
1227
|
-
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
|
|
1236
|
+
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
|
|
1228
1237
|
let sharedLimitId = maxSharedStructures + 0x40;
|
|
1229
1238
|
let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
|
|
1230
1239
|
if (maxStructureId > 8256) {
|
|
@@ -1242,7 +1251,7 @@ class Packr extends Unpackr {
|
|
|
1242
1251
|
}
|
|
1243
1252
|
safeEnd = target.length - 10;
|
|
1244
1253
|
if (safeEnd - position < 0x800) {
|
|
1245
|
-
// don't start too close to the end,
|
|
1254
|
+
// don't start too close to the end,
|
|
1246
1255
|
target = new ByteArrayAllocate(target.length);
|
|
1247
1256
|
targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length));
|
|
1248
1257
|
safeEnd = target.length - 10;
|
|
@@ -1360,10 +1369,14 @@ class Packr extends Unpackr {
|
|
|
1360
1369
|
return packr.pack(value, encodeOptions)
|
|
1361
1370
|
}
|
|
1362
1371
|
packr.lastNamedStructuresLength = sharedLength;
|
|
1372
|
+
// don't keep large buffers around
|
|
1373
|
+
if (target.length > 0x40000000) target = null;
|
|
1363
1374
|
return returnBuffer
|
|
1364
1375
|
}
|
|
1365
1376
|
}
|
|
1366
1377
|
}
|
|
1378
|
+
// don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
|
|
1379
|
+
if (target.length > 0x40000000) target = null;
|
|
1367
1380
|
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1368
1381
|
position = start;
|
|
1369
1382
|
}
|
|
@@ -1581,12 +1594,12 @@ class Packr extends Unpackr {
|
|
|
1581
1594
|
targetView.setUint32(position, referee.id);
|
|
1582
1595
|
position += 4;
|
|
1583
1596
|
return
|
|
1584
|
-
} else
|
|
1597
|
+
} else
|
|
1585
1598
|
referenceMap.set(value, { offset: position - start });
|
|
1586
1599
|
}
|
|
1587
1600
|
let constructor = value.constructor;
|
|
1588
1601
|
if (constructor === Object) {
|
|
1589
|
-
writeObject(value
|
|
1602
|
+
writeObject(value);
|
|
1590
1603
|
} else if (constructor === Array) {
|
|
1591
1604
|
packArray(value);
|
|
1592
1605
|
} else if (constructor === Map) {
|
|
@@ -1609,7 +1622,7 @@ class Packr extends Unpackr {
|
|
|
1609
1622
|
pack(entryValue);
|
|
1610
1623
|
}
|
|
1611
1624
|
}
|
|
1612
|
-
} else {
|
|
1625
|
+
} else {
|
|
1613
1626
|
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
1614
1627
|
let extensionClass = extensionClasses[i];
|
|
1615
1628
|
if (value instanceof extensionClass) {
|
|
@@ -1677,13 +1690,13 @@ class Packr extends Unpackr {
|
|
|
1677
1690
|
if (json !== value)
|
|
1678
1691
|
return pack(json)
|
|
1679
1692
|
}
|
|
1680
|
-
|
|
1693
|
+
|
|
1681
1694
|
// if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1682
1695
|
if (type === 'function')
|
|
1683
1696
|
return pack(this.writeFunction && this.writeFunction(value));
|
|
1684
|
-
|
|
1685
|
-
// no extension found, write as object
|
|
1686
|
-
writeObject(value
|
|
1697
|
+
|
|
1698
|
+
// no extension found, write as plain object
|
|
1699
|
+
writeObject(value);
|
|
1687
1700
|
}
|
|
1688
1701
|
}
|
|
1689
1702
|
}
|
|
@@ -1739,9 +1752,19 @@ class Packr extends Unpackr {
|
|
|
1739
1752
|
}
|
|
1740
1753
|
};
|
|
1741
1754
|
|
|
1742
|
-
const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber) ? (object) => {
|
|
1755
|
+
const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues) ? (object) => {
|
|
1743
1756
|
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1744
|
-
let keys
|
|
1757
|
+
let keys;
|
|
1758
|
+
if (this.skipValues) {
|
|
1759
|
+
keys = [];
|
|
1760
|
+
for (let key in object) {
|
|
1761
|
+
if ((typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) &&
|
|
1762
|
+
!this.skipValues.includes(object[key]))
|
|
1763
|
+
keys.push(key);
|
|
1764
|
+
}
|
|
1765
|
+
} else {
|
|
1766
|
+
keys = Object.keys(object);
|
|
1767
|
+
}
|
|
1745
1768
|
let length = keys.length;
|
|
1746
1769
|
if (length < 0x10) {
|
|
1747
1770
|
target[position++] = 0x80 | length;
|
|
@@ -1770,13 +1793,13 @@ class Packr extends Unpackr {
|
|
|
1770
1793
|
}
|
|
1771
1794
|
}
|
|
1772
1795
|
} :
|
|
1773
|
-
(object
|
|
1796
|
+
(object) => {
|
|
1774
1797
|
target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
|
|
1775
1798
|
let objectOffset = position - start;
|
|
1776
1799
|
position += 2;
|
|
1777
1800
|
let size = 0;
|
|
1778
1801
|
for (let key in object) {
|
|
1779
|
-
if (
|
|
1802
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1780
1803
|
pack(key);
|
|
1781
1804
|
pack(object[key]);
|
|
1782
1805
|
size++;
|
|
@@ -1788,12 +1811,12 @@ class Packr extends Unpackr {
|
|
|
1788
1811
|
|
|
1789
1812
|
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
1790
1813
|
(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)
|
|
1791
|
-
(object
|
|
1814
|
+
(object) => {
|
|
1792
1815
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1793
1816
|
let objectOffset = position++ - start;
|
|
1794
1817
|
let wroteKeys;
|
|
1795
1818
|
for (let key in object) {
|
|
1796
|
-
if (
|
|
1819
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1797
1820
|
nextTransition = transition[key];
|
|
1798
1821
|
if (nextTransition)
|
|
1799
1822
|
transition = nextTransition;
|
|
@@ -1832,10 +1855,10 @@ class Packr extends Unpackr {
|
|
|
1832
1855
|
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1833
1856
|
}
|
|
1834
1857
|
} :
|
|
1835
|
-
(object
|
|
1858
|
+
(object) => {
|
|
1836
1859
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1837
1860
|
let newTransitions = 0;
|
|
1838
|
-
for (let key in object) if (
|
|
1861
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1839
1862
|
nextTransition = transition[key];
|
|
1840
1863
|
if (!nextTransition) {
|
|
1841
1864
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1855,16 +1878,16 @@ class Packr extends Unpackr {
|
|
|
1855
1878
|
}
|
|
1856
1879
|
// now write the values
|
|
1857
1880
|
for (let key in object)
|
|
1858
|
-
if (
|
|
1881
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1859
1882
|
pack(object[key]);
|
|
1860
1883
|
}
|
|
1861
1884
|
};
|
|
1862
1885
|
|
|
1863
|
-
//
|
|
1886
|
+
// create reference to useRecords if useRecords is a function
|
|
1864
1887
|
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
1865
|
-
|
|
1866
|
-
const writeObject = checkUseRecords ? (object
|
|
1867
|
-
checkUseRecords(object) ? writeRecord(object
|
|
1888
|
+
|
|
1889
|
+
const writeObject = checkUseRecords ? (object) => {
|
|
1890
|
+
checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
|
|
1868
1891
|
} : writeRecord;
|
|
1869
1892
|
|
|
1870
1893
|
const makeRoom = (end) => {
|
|
@@ -1969,7 +1992,7 @@ class Packr extends Unpackr {
|
|
|
1969
1992
|
target[insertionOffset + start] = keysTarget[0];
|
|
1970
1993
|
}
|
|
1971
1994
|
};
|
|
1972
|
-
const writeStruct = (object
|
|
1995
|
+
const writeStruct = (object) => {
|
|
1973
1996
|
let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
|
|
1974
1997
|
if (notifySharedUpdate)
|
|
1975
1998
|
return hasSharedUpdate = true;
|
|
@@ -1983,16 +2006,22 @@ class Packr extends Unpackr {
|
|
|
1983
2006
|
return position;
|
|
1984
2007
|
}, this);
|
|
1985
2008
|
if (newPosition === 0) // bail and go to a msgpack object
|
|
1986
|
-
return writeObject(object
|
|
2009
|
+
return writeObject(object);
|
|
1987
2010
|
position = newPosition;
|
|
1988
2011
|
};
|
|
1989
2012
|
}
|
|
1990
2013
|
useBuffer(buffer) {
|
|
1991
2014
|
// this means we are finished using our own buffer and we can write over it safely
|
|
1992
2015
|
target = buffer;
|
|
1993
|
-
|
|
2016
|
+
target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength));
|
|
1994
2017
|
position = 0;
|
|
1995
2018
|
}
|
|
2019
|
+
set position (value) {
|
|
2020
|
+
position = value;
|
|
2021
|
+
}
|
|
2022
|
+
get position() {
|
|
2023
|
+
return position;
|
|
2024
|
+
}
|
|
1996
2025
|
clearSharedData() {
|
|
1997
2026
|
if (this.structures)
|
|
1998
2027
|
this.structures = [];
|
|
@@ -2061,7 +2090,7 @@ extensions = [{
|
|
|
2061
2090
|
target[position++] = 0x65; // 'e' for error
|
|
2062
2091
|
target[position++] = 0;
|
|
2063
2092
|
}
|
|
2064
|
-
pack([ error.name, error.message ]);
|
|
2093
|
+
pack([ error.name, error.message, error.cause ]);
|
|
2065
2094
|
}
|
|
2066
2095
|
}, {
|
|
2067
2096
|
pack(regex, allocateForWrite, pack) {
|
|
@@ -2114,6 +2143,7 @@ function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
|
|
|
2114
2143
|
}
|
|
2115
2144
|
target[position++] = 0x74; // "t" for typed array
|
|
2116
2145
|
target[position++] = type;
|
|
2146
|
+
if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
|
|
2117
2147
|
target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
|
|
2118
2148
|
}
|
|
2119
2149
|
function writeBuffer(buffer, allocateForWrite) {
|
|
@@ -2708,6 +2738,8 @@ function readStruct(src, position, srcEnd, unpackr) {
|
|
|
2708
2738
|
src = Uint8Array.prototype.slice.call(src, position, srcEnd);
|
|
2709
2739
|
srcEnd -= position;
|
|
2710
2740
|
position = 0;
|
|
2741
|
+
if (!unpackr.getStructures)
|
|
2742
|
+
throw new Error(`Reference to shared structure ${recordId} without getStructures method`);
|
|
2711
2743
|
unpackr._mergeStructures(unpackr.getStructures());
|
|
2712
2744
|
if (!unpackr.typedStructs)
|
|
2713
2745
|
throw new Error('Could not find any shared typed structures');
|