msgpackr 1.9.9 → 1.10.1
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 +51 -8
- 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 +51 -8
- 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 +53 -8
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +82 -8
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +21 -2
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +1 -0
- package/index.d.ts +1 -0
- package/pack.js +30 -6
- package/package.json +1 -1
- package/struct.js +2 -0
- package/test-worker.js +3 -0
- package/unpack.js +21 -2
package/README.md
CHANGED
|
@@ -184,6 +184,7 @@ The following options properties can be provided to the Packr or Unpackr constru
|
|
|
184
184
|
* `useTimestamp32` - Encode JS `Date`s in 32-bit format when possible by dropping the milliseconds. This is a more efficient encoding of dates. You can also cause dates to use 32-bit format by manually setting the milliseconds to zero (`date.setMilliseconds(0)`).
|
|
185
185
|
* `sequential` - Encode structures in serialized data, and reference previously encoded structures with expectation that decoder will read the encoded structures in the same order as encoded, with `unpackMultiple`.
|
|
186
186
|
* `largeBigIntToFloat` - If a bigint needs to be encoded that is larger than will fit in 64-bit integers, it will be encoded as a float-64 (otherwise will throw a RangeError).
|
|
187
|
+
* `useBigIntExtension` - If a bigint needs to be encoded that is larger than will fit in 64-bit integers, it will be encoded using a custom extension that supports up to about 1000-bits of integer precision.
|
|
187
188
|
* `encodeUndefinedAsNil` - Encodes a value of `undefined` as a MessagePack `nil`, the same as a `null`.
|
|
188
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).
|
|
189
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).
|
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,15 @@
|
|
|
911
911
|
return entry.string = readFixedString(length)
|
|
912
912
|
}
|
|
913
913
|
|
|
914
|
+
function asSafeString(property) {
|
|
915
|
+
if (typeof property === 'string') return property;
|
|
916
|
+
if (typeof property === 'number') return property.toString();
|
|
917
|
+
throw new Error('Invalid property type for record', typeof property);
|
|
918
|
+
}
|
|
914
919
|
// the registration of the record definition extension (as "r")
|
|
915
920
|
const recordDefinition = (id, highByte) => {
|
|
916
|
-
let structure = read().map(
|
|
921
|
+
let structure = read().map(asSafeString); // ensure that all keys are strings and
|
|
922
|
+
// that the array is mutable
|
|
917
923
|
let firstByte = id;
|
|
918
924
|
if (highByte !== undefined) {
|
|
919
925
|
id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
|
|
@@ -933,6 +939,17 @@
|
|
|
933
939
|
currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
934
940
|
currentExtensions[0].noBuffer = true;
|
|
935
941
|
|
|
942
|
+
currentExtensions[0x42] = (data) => {
|
|
943
|
+
// decode bigint
|
|
944
|
+
let length = data.length;
|
|
945
|
+
let value = BigInt(data[0] & 0x80 ? data[0] - 0x100 : data[0]);
|
|
946
|
+
for (let i = 1; i < length; i++) {
|
|
947
|
+
value <<= 8n;
|
|
948
|
+
value += BigInt(data[i]);
|
|
949
|
+
}
|
|
950
|
+
return value;
|
|
951
|
+
};
|
|
952
|
+
|
|
936
953
|
let errors = { Error, TypeError, ReferenceError };
|
|
937
954
|
currentExtensions[0x65] = () => {
|
|
938
955
|
let data = read();
|
|
@@ -941,6 +958,7 @@
|
|
|
941
958
|
|
|
942
959
|
currentExtensions[0x69] = (data) => {
|
|
943
960
|
// id extension (for structured clones)
|
|
961
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
944
962
|
let id = dataView.getUint32(position$1 - 4);
|
|
945
963
|
if (!referenceMap)
|
|
946
964
|
referenceMap = new Map();
|
|
@@ -964,6 +982,7 @@
|
|
|
964
982
|
|
|
965
983
|
currentExtensions[0x70] = (data) => {
|
|
966
984
|
// pointer extension (for structured clones)
|
|
985
|
+
if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
|
|
967
986
|
let id = dataView.getUint32(position$1 - 4);
|
|
968
987
|
let refEntry = referenceMap.get(id);
|
|
969
988
|
refEntry.used = true;
|
|
@@ -1207,6 +1226,7 @@
|
|
|
1207
1226
|
}
|
|
1208
1227
|
if (hasSharedUpdate)
|
|
1209
1228
|
hasSharedUpdate = false;
|
|
1229
|
+
let encodingError;
|
|
1210
1230
|
try {
|
|
1211
1231
|
if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
|
|
1212
1232
|
writeStruct(value);
|
|
@@ -1257,6 +1277,9 @@
|
|
|
1257
1277
|
return target
|
|
1258
1278
|
}
|
|
1259
1279
|
return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1280
|
+
} catch(error) {
|
|
1281
|
+
encodingError = error;
|
|
1282
|
+
throw error;
|
|
1260
1283
|
} finally {
|
|
1261
1284
|
if (structures) {
|
|
1262
1285
|
resetStructures();
|
|
@@ -1265,12 +1288,14 @@
|
|
|
1265
1288
|
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1266
1289
|
let returnBuffer = target.subarray(start, position);
|
|
1267
1290
|
let newSharedData = prepareStructures(structures, packr);
|
|
1268
|
-
if (
|
|
1269
|
-
|
|
1270
|
-
|
|
1291
|
+
if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time
|
|
1292
|
+
if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
|
|
1293
|
+
// get updated structures and try again if the update failed
|
|
1294
|
+
return packr.pack(value, encodeOptions)
|
|
1295
|
+
}
|
|
1296
|
+
packr.lastNamedStructuresLength = sharedLength;
|
|
1297
|
+
return returnBuffer
|
|
1271
1298
|
}
|
|
1272
|
-
packr.lastNamedStructuresLength = sharedLength;
|
|
1273
|
-
return returnBuffer
|
|
1274
1299
|
}
|
|
1275
1300
|
}
|
|
1276
1301
|
if (encodeOptions & RESET_BUFFER_MODE)
|
|
@@ -1612,8 +1637,26 @@
|
|
|
1612
1637
|
if (this.largeBigIntToFloat) {
|
|
1613
1638
|
target[position++] = 0xcb;
|
|
1614
1639
|
targetView.setFloat64(position, Number(value));
|
|
1640
|
+
} else if (this.useBigIntExtension && value < 2n**(1023n) && value > -(2n**(1023n))) {
|
|
1641
|
+
target[position++] = 0xc7;
|
|
1642
|
+
position++;
|
|
1643
|
+
target[position++] = 0x42; // "B" for BigInt
|
|
1644
|
+
let bytes = [];
|
|
1645
|
+
let alignedSign;
|
|
1646
|
+
do {
|
|
1647
|
+
let byte = value & 0xffn;
|
|
1648
|
+
alignedSign = (byte & 0x80n) === (value < 0n ? 0x80n : 0n);
|
|
1649
|
+
bytes.push(byte);
|
|
1650
|
+
value >>= 8n;
|
|
1651
|
+
} while (!((value === 0n || value === -1n) && alignedSign));
|
|
1652
|
+
target[position-2] = bytes.length;
|
|
1653
|
+
for (let i = bytes.length; i > 0;) {
|
|
1654
|
+
target[position++] = Number(bytes[--i]);
|
|
1655
|
+
}
|
|
1656
|
+
return
|
|
1615
1657
|
} else {
|
|
1616
|
-
throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format,
|
|
1658
|
+
throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
|
|
1659
|
+
' useBigIntExtension or set largeBigIntToFloat to convert to float-64')
|
|
1617
1660
|
}
|
|
1618
1661
|
}
|
|
1619
1662
|
position += 8;
|