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/README.md
CHANGED
|
@@ -188,6 +188,7 @@ The following options properties can be provided to the Packr or Unpackr constru
|
|
|
188
188
|
* `encodeUndefinedAsNil` - Encodes a value of `undefined` as a MessagePack `nil`, the same as a `null`.
|
|
189
189
|
* `int64AsType` - This will decode uint64 and int64 numbers as the specified type. The type can be `bigint` (default), `number`, `string`, or `auto` (where range [-2^53...2^53] is represented by number and everything else by a bigint).
|
|
190
190
|
* `onInvalidDate` - This can be provided as function that will be called when an invalid date is provided. The function can throw an error, or return a value that will be encoded in place of the invalid date. If not provided, an invalid date will be encoded as an invalid timestamp (which decodes with msgpackr back to an invalid date).
|
|
191
|
+
* `writeFunction` - This can be provided as function that will be called when a function is encountered. The function can throw an error, or return a value that will be encoded in place of the function. If not provided, a function will be encoded as undefined (similar to `JSON.stringify`).
|
|
191
192
|
* `mapAsEmptyObject` - Encodes JS `Map`s as empty objects (for back-compat with older libraries).
|
|
192
193
|
* `setAsEmptyObject` - Encodes JS `Set`s as empty objects (for back-compat with older libraries).
|
|
193
194
|
|
package/dist/index-no-eval.cjs
CHANGED
|
@@ -859,7 +859,7 @@
|
|
|
859
859
|
return readFixedString(length)
|
|
860
860
|
} else { // not cacheable, go back and do a standard read
|
|
861
861
|
position$1--;
|
|
862
|
-
return read()
|
|
862
|
+
return asSafeString(read())
|
|
863
863
|
}
|
|
864
864
|
let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
|
|
865
865
|
let entry = keyCache[key];
|
|
@@ -911,9 +911,17 @@
|
|
|
911
911
|
return entry.string = readFixedString(length)
|
|
912
912
|
}
|
|
913
913
|
|
|
914
|
+
function asSafeString(property) {
|
|
915
|
+
// protect against expensive (DoS) string conversions
|
|
916
|
+
if (typeof property === 'string') return property;
|
|
917
|
+
if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
|
|
918
|
+
if (property == null) return property + '';
|
|
919
|
+
throw new Error('Invalid property type for record', typeof property);
|
|
920
|
+
}
|
|
914
921
|
// the registration of the record definition extension (as "r")
|
|
915
922
|
const recordDefinition = (id, highByte) => {
|
|
916
|
-
let structure = read().map(
|
|
923
|
+
let structure = read().map(asSafeString); // ensure that all keys are strings and
|
|
924
|
+
// that the array is mutable
|
|
917
925
|
let firstByte = id;
|
|
918
926
|
if (highByte !== undefined) {
|
|
919
927
|
id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
|
|
@@ -947,11 +955,12 @@
|
|
|
947
955
|
let errors = { Error, TypeError, ReferenceError };
|
|
948
956
|
currentExtensions[0x65] = () => {
|
|
949
957
|
let data = read();
|
|
950
|
-
return (errors[data[0]] || Error)(data[1])
|
|
958
|
+
return (errors[data[0]] || Error)(data[1], { cause: data[2] })
|
|
951
959
|
};
|
|
952
960
|
|
|
953
961
|
currentExtensions[0x69] = (data) => {
|
|
954
962
|
// id extension (for structured clones)
|
|
963
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
955
964
|
let id = dataView.getUint32(position$1 - 4);
|
|
956
965
|
if (!referenceMap)
|
|
957
966
|
referenceMap = new Map();
|
|
@@ -975,6 +984,7 @@
|
|
|
975
984
|
|
|
976
985
|
currentExtensions[0x70] = (data) => {
|
|
977
986
|
// pointer extension (for structured clones)
|
|
987
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
978
988
|
let id = dataView.getUint32(position$1 - 4);
|
|
979
989
|
let refEntry = referenceMap.get(id);
|
|
980
990
|
refEntry.used = true;
|
|
@@ -989,8 +999,15 @@
|
|
|
989
999
|
currentExtensions[0x74] = (data) => {
|
|
990
1000
|
let typeCode = data[0];
|
|
991
1001
|
let typedArrayName = typedArrays[typeCode];
|
|
992
|
-
if (!typedArrayName)
|
|
1002
|
+
if (!typedArrayName) {
|
|
1003
|
+
if (typeCode === 16) {
|
|
1004
|
+
let ab = new ArrayBuffer(data.length - 1);
|
|
1005
|
+
let u8 = new Uint8Array(ab);
|
|
1006
|
+
u8.set(data.subarray(1));
|
|
1007
|
+
return ab;
|
|
1008
|
+
}
|
|
993
1009
|
throw new Error('Could not find typed array for code ' + typeCode)
|
|
1010
|
+
}
|
|
994
1011
|
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
995
1012
|
return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
996
1013
|
};
|
|
@@ -1286,10 +1303,14 @@
|
|
|
1286
1303
|
return packr.pack(value, encodeOptions)
|
|
1287
1304
|
}
|
|
1288
1305
|
packr.lastNamedStructuresLength = sharedLength;
|
|
1306
|
+
// don't keep large buffers around
|
|
1307
|
+
if (target.length > 0x40000000) target = null;
|
|
1289
1308
|
return returnBuffer
|
|
1290
1309
|
}
|
|
1291
1310
|
}
|
|
1292
1311
|
}
|
|
1312
|
+
// don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
|
|
1313
|
+
if (target.length > 0x40000000) target = null;
|
|
1293
1314
|
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1294
1315
|
position = start;
|
|
1295
1316
|
}
|
|
@@ -1512,7 +1533,7 @@
|
|
|
1512
1533
|
}
|
|
1513
1534
|
let constructor = value.constructor;
|
|
1514
1535
|
if (constructor === Object) {
|
|
1515
|
-
writeObject(value
|
|
1536
|
+
writeObject(value);
|
|
1516
1537
|
} else if (constructor === Array) {
|
|
1517
1538
|
packArray(value);
|
|
1518
1539
|
} else if (constructor === Map) {
|
|
@@ -1608,8 +1629,8 @@
|
|
|
1608
1629
|
if (type === 'function')
|
|
1609
1630
|
return pack(this.writeFunction && this.writeFunction(value));
|
|
1610
1631
|
|
|
1611
|
-
// no extension found, write as object
|
|
1612
|
-
writeObject(value
|
|
1632
|
+
// no extension found, write as plain object
|
|
1633
|
+
writeObject(value);
|
|
1613
1634
|
}
|
|
1614
1635
|
}
|
|
1615
1636
|
}
|
|
@@ -1696,13 +1717,13 @@
|
|
|
1696
1717
|
}
|
|
1697
1718
|
}
|
|
1698
1719
|
} :
|
|
1699
|
-
(object
|
|
1720
|
+
(object) => {
|
|
1700
1721
|
target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
|
|
1701
1722
|
let objectOffset = position - start;
|
|
1702
1723
|
position += 2;
|
|
1703
1724
|
let size = 0;
|
|
1704
1725
|
for (let key in object) {
|
|
1705
|
-
if (
|
|
1726
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1706
1727
|
pack(key);
|
|
1707
1728
|
pack(object[key]);
|
|
1708
1729
|
size++;
|
|
@@ -1714,12 +1735,12 @@
|
|
|
1714
1735
|
|
|
1715
1736
|
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
1716
1737
|
(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)
|
|
1717
|
-
(object
|
|
1738
|
+
(object) => {
|
|
1718
1739
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1719
1740
|
let objectOffset = position++ - start;
|
|
1720
1741
|
let wroteKeys;
|
|
1721
1742
|
for (let key in object) {
|
|
1722
|
-
if (
|
|
1743
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1723
1744
|
nextTransition = transition[key];
|
|
1724
1745
|
if (nextTransition)
|
|
1725
1746
|
transition = nextTransition;
|
|
@@ -1758,10 +1779,10 @@
|
|
|
1758
1779
|
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1759
1780
|
}
|
|
1760
1781
|
} :
|
|
1761
|
-
(object
|
|
1782
|
+
(object) => {
|
|
1762
1783
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1763
1784
|
let newTransitions = 0;
|
|
1764
|
-
for (let key in object) if (
|
|
1785
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1765
1786
|
nextTransition = transition[key];
|
|
1766
1787
|
if (!nextTransition) {
|
|
1767
1788
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1781,7 +1802,7 @@
|
|
|
1781
1802
|
}
|
|
1782
1803
|
// now write the values
|
|
1783
1804
|
for (let key in object)
|
|
1784
|
-
if (
|
|
1805
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1785
1806
|
pack(object[key]);
|
|
1786
1807
|
}
|
|
1787
1808
|
};
|
|
@@ -1789,8 +1810,8 @@
|
|
|
1789
1810
|
// craete reference to useRecords if useRecords is a function
|
|
1790
1811
|
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
1791
1812
|
|
|
1792
|
-
const writeObject = checkUseRecords ? (object
|
|
1793
|
-
checkUseRecords(object) ? writeRecord(object
|
|
1813
|
+
const writeObject = checkUseRecords ? (object) => {
|
|
1814
|
+
checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
|
|
1794
1815
|
} : writeRecord;
|
|
1795
1816
|
|
|
1796
1817
|
const makeRoom = (end) => {
|
|
@@ -1895,7 +1916,7 @@
|
|
|
1895
1916
|
target[insertionOffset + start] = keysTarget[0];
|
|
1896
1917
|
}
|
|
1897
1918
|
};
|
|
1898
|
-
const writeStruct = (object
|
|
1919
|
+
const writeStruct = (object) => {
|
|
1899
1920
|
let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
|
|
1900
1921
|
if (notifySharedUpdate)
|
|
1901
1922
|
return hasSharedUpdate = true;
|
|
@@ -1909,7 +1930,7 @@
|
|
|
1909
1930
|
return position;
|
|
1910
1931
|
}, this);
|
|
1911
1932
|
if (newPosition === 0) // bail and go to a msgpack object
|
|
1912
|
-
return writeObject(object
|
|
1933
|
+
return writeObject(object);
|
|
1913
1934
|
position = newPosition;
|
|
1914
1935
|
};
|
|
1915
1936
|
}
|
|
@@ -1987,7 +2008,7 @@
|
|
|
1987
2008
|
target[position++] = 0x65; // 'e' for error
|
|
1988
2009
|
target[position++] = 0;
|
|
1989
2010
|
}
|
|
1990
|
-
pack([ error.name, error.message ]);
|
|
2011
|
+
pack([ error.name, error.message, error.cause ]);
|
|
1991
2012
|
}
|
|
1992
2013
|
}, {
|
|
1993
2014
|
pack(regex, allocateForWrite, pack) {
|
|
@@ -2040,6 +2061,7 @@
|
|
|
2040
2061
|
}
|
|
2041
2062
|
target[position++] = 0x74; // "t" for typed array
|
|
2042
2063
|
target[position++] = type;
|
|
2064
|
+
if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
|
|
2043
2065
|
target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
|
|
2044
2066
|
}
|
|
2045
2067
|
function writeBuffer(buffer, allocateForWrite) {
|