msgpackr 1.10.2 → 1.11.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 CHANGED
@@ -184,9 +184,11 @@ 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
+ * `largeBigIntToString` - If a bigint needs to be encoded that is larger than will fit in 64-bit integers, it will be encoded as a string (otherwise will throw a RangeError).
187
188
  * `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.
188
189
  * `encodeUndefinedAsNil` - Encodes a value of `undefined` as a MessagePack `nil`, the same as a `null`.
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
+ * `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).
191
+ * `skipValues` - This can be an array of property values that will indicate properties that should be skipped when serializing objects. For example, to mimic `JSON.stringify`'s behavior of skipping properties with a value of `undefined`, you can provide `skipValues: [undefined]`. Note, that this will only apply to serializing objects as standard MessagePack maps, not to records. Also, the array is checked by calling the `include` method, so you can provide an object with an `includes` if you want a custom function to skip values.
190
192
  * `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
193
  * `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`).
192
194
  * `mapAsEmptyObject` - Encodes JS `Map`s as empty objects (for back-compat with older libraries).
@@ -271,7 +273,7 @@ addExtension({
271
273
  pack(instance) {
272
274
  // define how your custom class should be encoded
273
275
  return Buffer.from([instance.myData]); // return a buffer
274
- }
276
+ },
275
277
  unpack(buffer) {
276
278
  // define how your custom class should be decoded
277
279
  let instance = new MyCustomClass();
@@ -946,7 +946,7 @@
946
946
  let length = data.length;
947
947
  let value = BigInt(data[0] & 0x80 ? data[0] - 0x100 : data[0]);
948
948
  for (let i = 1; i < length; i++) {
949
- value <<= 8n;
949
+ value <<= BigInt(8);
950
950
  value += BigInt(data[i]);
951
951
  }
952
952
  return value;
@@ -1142,7 +1142,7 @@
1142
1142
  let structures;
1143
1143
  let referenceMap;
1144
1144
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1145
- return target.utf8Write(string, position, 0xffffffff)
1145
+ return target.utf8Write(string, position, target.byteLength - position)
1146
1146
  } : (textEncoder && textEncoder.encodeInto) ?
1147
1147
  function(string, position) {
1148
1148
  return textEncoder.encodeInto(string, target.subarray(position)).written
@@ -1167,7 +1167,7 @@
1167
1167
  if (!this.structures && options.useRecords != false)
1168
1168
  this.structures = [];
1169
1169
  // two byte record ids for shared structures
1170
- let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
1170
+ let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
1171
1171
  let sharedLimitId = maxSharedStructures + 0x40;
1172
1172
  let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
1173
1173
  if (maxStructureId > 8256) {
@@ -1185,7 +1185,7 @@
1185
1185
  }
1186
1186
  safeEnd = target.length - 10;
1187
1187
  if (safeEnd - position < 0x800) {
1188
- // don't start too close to the end,
1188
+ // don't start too close to the end,
1189
1189
  target = new ByteArrayAllocate(target.length);
1190
1190
  targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length));
1191
1191
  safeEnd = target.length - 10;
@@ -1528,7 +1528,7 @@
1528
1528
  targetView.setUint32(position, referee.id);
1529
1529
  position += 4;
1530
1530
  return
1531
- } else
1531
+ } else
1532
1532
  referenceMap.set(value, { offset: position - start });
1533
1533
  }
1534
1534
  let constructor = value.constructor;
@@ -1556,7 +1556,7 @@
1556
1556
  pack(entryValue);
1557
1557
  }
1558
1558
  }
1559
- } else {
1559
+ } else {
1560
1560
  for (let i = 0, l = extensions.length; i < l; i++) {
1561
1561
  let extensionClass = extensionClasses[i];
1562
1562
  if (value instanceof extensionClass) {
@@ -1624,11 +1624,11 @@
1624
1624
  if (json !== value)
1625
1625
  return pack(json)
1626
1626
  }
1627
-
1627
+
1628
1628
  // if there is a writeFunction, use it, otherwise just encode as undefined
1629
1629
  if (type === 'function')
1630
1630
  return pack(this.writeFunction && this.writeFunction(value));
1631
-
1631
+
1632
1632
  // no extension found, write as plain object
1633
1633
  writeObject(value);
1634
1634
  }
@@ -1650,18 +1650,20 @@
1650
1650
  if (this.largeBigIntToFloat) {
1651
1651
  target[position++] = 0xcb;
1652
1652
  targetView.setFloat64(position, Number(value));
1653
- } else if (this.useBigIntExtension && value < 2n**(1023n) && value > -(2n**(1023n))) {
1653
+ } else if (this.largeBigIntToString) {
1654
+ return pack(value.toString());
1655
+ } else if (this.useBigIntExtension && value < BigInt(2)**BigInt(1023) && value > -(BigInt(2)**BigInt(1023))) {
1654
1656
  target[position++] = 0xc7;
1655
1657
  position++;
1656
1658
  target[position++] = 0x42; // "B" for BigInt
1657
1659
  let bytes = [];
1658
1660
  let alignedSign;
1659
1661
  do {
1660
- let byte = value & 0xffn;
1661
- alignedSign = (byte & 0x80n) === (value < 0n ? 0x80n : 0n);
1662
+ let byte = value & BigInt(0xff);
1663
+ alignedSign = (byte & BigInt(0x80)) === (value < BigInt(0) ? BigInt(0x80) : BigInt(0));
1662
1664
  bytes.push(byte);
1663
- value >>= 8n;
1664
- } while (!((value === 0n || value === -1n) && alignedSign));
1665
+ value >>= BigInt(8);
1666
+ } while (!((value === BigInt(0) || value === BigInt(-1)) && alignedSign));
1665
1667
  target[position-2] = bytes.length;
1666
1668
  for (let i = bytes.length; i > 0;) {
1667
1669
  target[position++] = Number(bytes[--i]);
@@ -1669,7 +1671,8 @@
1669
1671
  return
1670
1672
  } else {
1671
1673
  throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
1672
- ' useBigIntExtension or set largeBigIntToFloat to convert to float-64')
1674
+ ' useBigIntExtension, or set largeBigIntToFloat to convert to float-64, or set' +
1675
+ ' largeBigIntToString to convert to string')
1673
1676
  }
1674
1677
  }
1675
1678
  position += 8;
@@ -1686,9 +1689,19 @@
1686
1689
  }
1687
1690
  };
1688
1691
 
1689
- const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber) ? (object) => {
1692
+ const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues) ? (object) => {
1690
1693
  // this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
1691
- let keys = Object.keys(object);
1694
+ let keys;
1695
+ if (this.skipValues) {
1696
+ keys = [];
1697
+ for (let key in object) {
1698
+ if ((typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) &&
1699
+ !this.skipValues.includes(object[key]))
1700
+ keys.push(key);
1701
+ }
1702
+ } else {
1703
+ keys = Object.keys(object);
1704
+ }
1692
1705
  let length = keys.length;
1693
1706
  if (length < 0x10) {
1694
1707
  target[position++] = 0x80 | length;
@@ -1729,6 +1742,10 @@
1729
1742
  size++;
1730
1743
  }
1731
1744
  }
1745
+ if (size > 0xffff) {
1746
+ throw new Error('Object is too large to serialize with fast 16-bit map size,' +
1747
+ ' use the "variableMapSize" option to serialize this object');
1748
+ }
1732
1749
  target[objectOffset++ + start] = size >> 8;
1733
1750
  target[objectOffset + start] = size & 0xff;
1734
1751
  };
@@ -1807,9 +1824,9 @@
1807
1824
  }
1808
1825
  };
1809
1826
 
1810
- // craete reference to useRecords if useRecords is a function
1827
+ // create reference to useRecords if useRecords is a function
1811
1828
  const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
1812
-
1829
+
1813
1830
  const writeObject = checkUseRecords ? (object) => {
1814
1831
  checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
1815
1832
  } : writeRecord;
@@ -1937,9 +1954,15 @@
1937
1954
  useBuffer(buffer) {
1938
1955
  // this means we are finished using our own buffer and we can write over it safely
1939
1956
  target = buffer;
1940
- targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
1957
+ target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength));
1941
1958
  position = 0;
1942
1959
  }
1960
+ set position (value) {
1961
+ position = value;
1962
+ }
1963
+ get position() {
1964
+ return position;
1965
+ }
1943
1966
  clearSharedData() {
1944
1967
  if (this.structures)
1945
1968
  this.structures = [];
@@ -2077,7 +2100,7 @@
2077
2100
  target[position++] = length >> 8;
2078
2101
  target[position++] = length & 0xff;
2079
2102
  } else {
2080
- var { target, position, targetView } = allocateForWrite(length + 5);
2103
+ let { target, position, targetView } = allocateForWrite(length + 5);
2081
2104
  target[position++] = 0xc6;
2082
2105
  targetView.setUint32(position, length);
2083
2106
  position += 4;
@@ -2285,6 +2308,8 @@
2285
2308
  exports.FLOAT32_OPTIONS = FLOAT32_OPTIONS;
2286
2309
  exports.NEVER = NEVER;
2287
2310
  exports.Packr = Packr;
2311
+ exports.RESERVE_START_SPACE = RESERVE_START_SPACE;
2312
+ exports.RESET_BUFFER_MODE = RESET_BUFFER_MODE;
2288
2313
  exports.REUSE_BUFFER_MODE = REUSE_BUFFER_MODE;
2289
2314
  exports.Unpackr = Unpackr;
2290
2315
  exports.addExtension = addExtension;