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/dist/index.js CHANGED
@@ -911,8 +911,10 @@
911
911
  }
912
912
 
913
913
  function asSafeString(property) {
914
+ // protect against expensive (DoS) string conversions
914
915
  if (typeof property === 'string') return property;
915
- if (typeof property === 'number') return property.toString();
916
+ if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
917
+ if (property == null) return property + '';
916
918
  throw new Error('Invalid property type for record', typeof property);
917
919
  }
918
920
  // the registration of the record definition extension (as "r")
@@ -952,7 +954,7 @@
952
954
  let errors = { Error, TypeError, ReferenceError };
953
955
  currentExtensions[0x65] = () => {
954
956
  let data = read();
955
- return (errors[data[0]] || Error)(data[1])
957
+ return (errors[data[0]] || Error)(data[1], { cause: data[2] })
956
958
  };
957
959
 
958
960
  currentExtensions[0x69] = (data) => {
@@ -996,8 +998,15 @@
996
998
  currentExtensions[0x74] = (data) => {
997
999
  let typeCode = data[0];
998
1000
  let typedArrayName = typedArrays[typeCode];
999
- if (!typedArrayName)
1001
+ if (!typedArrayName) {
1002
+ if (typeCode === 16) {
1003
+ let ab = new ArrayBuffer(data.length - 1);
1004
+ let u8 = new Uint8Array(ab);
1005
+ u8.set(data.subarray(1));
1006
+ return ab;
1007
+ }
1000
1008
  throw new Error('Could not find typed array for code ' + typeCode)
1009
+ }
1001
1010
  // we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
1002
1011
  return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
1003
1012
  };
@@ -1157,7 +1166,7 @@
1157
1166
  if (!this.structures && options.useRecords != false)
1158
1167
  this.structures = [];
1159
1168
  // two byte record ids for shared structures
1160
- let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
1169
+ let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
1161
1170
  let sharedLimitId = maxSharedStructures + 0x40;
1162
1171
  let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
1163
1172
  if (maxStructureId > 8256) {
@@ -1175,7 +1184,7 @@
1175
1184
  }
1176
1185
  safeEnd = target.length - 10;
1177
1186
  if (safeEnd - position < 0x800) {
1178
- // don't start too close to the end,
1187
+ // don't start too close to the end,
1179
1188
  target = new ByteArrayAllocate(target.length);
1180
1189
  targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length));
1181
1190
  safeEnd = target.length - 10;
@@ -1293,10 +1302,14 @@
1293
1302
  return packr.pack(value, encodeOptions)
1294
1303
  }
1295
1304
  packr.lastNamedStructuresLength = sharedLength;
1305
+ // don't keep large buffers around
1306
+ if (target.length > 0x40000000) target = null;
1296
1307
  return returnBuffer
1297
1308
  }
1298
1309
  }
1299
1310
  }
1311
+ // don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
1312
+ if (target.length > 0x40000000) target = null;
1300
1313
  if (encodeOptions & RESET_BUFFER_MODE)
1301
1314
  position = start;
1302
1315
  }
@@ -1514,12 +1527,12 @@
1514
1527
  targetView.setUint32(position, referee.id);
1515
1528
  position += 4;
1516
1529
  return
1517
- } else
1530
+ } else
1518
1531
  referenceMap.set(value, { offset: position - start });
1519
1532
  }
1520
1533
  let constructor = value.constructor;
1521
1534
  if (constructor === Object) {
1522
- writeObject(value, true);
1535
+ writeObject(value);
1523
1536
  } else if (constructor === Array) {
1524
1537
  packArray(value);
1525
1538
  } else if (constructor === Map) {
@@ -1542,7 +1555,7 @@
1542
1555
  pack(entryValue);
1543
1556
  }
1544
1557
  }
1545
- } else {
1558
+ } else {
1546
1559
  for (let i = 0, l = extensions.length; i < l; i++) {
1547
1560
  let extensionClass = extensionClasses[i];
1548
1561
  if (value instanceof extensionClass) {
@@ -1610,13 +1623,13 @@
1610
1623
  if (json !== value)
1611
1624
  return pack(json)
1612
1625
  }
1613
-
1626
+
1614
1627
  // if there is a writeFunction, use it, otherwise just encode as undefined
1615
1628
  if (type === 'function')
1616
1629
  return pack(this.writeFunction && this.writeFunction(value));
1617
-
1618
- // no extension found, write as object
1619
- writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
1630
+
1631
+ // no extension found, write as plain object
1632
+ writeObject(value);
1620
1633
  }
1621
1634
  }
1622
1635
  }
@@ -1672,9 +1685,19 @@
1672
1685
  }
1673
1686
  };
1674
1687
 
1675
- const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber) ? (object) => {
1688
+ const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues) ? (object) => {
1676
1689
  // this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
1677
- let keys = Object.keys(object);
1690
+ let keys;
1691
+ if (this.skipValues) {
1692
+ keys = [];
1693
+ for (let key in object) {
1694
+ if ((typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) &&
1695
+ !this.skipValues.includes(object[key]))
1696
+ keys.push(key);
1697
+ }
1698
+ } else {
1699
+ keys = Object.keys(object);
1700
+ }
1678
1701
  let length = keys.length;
1679
1702
  if (length < 0x10) {
1680
1703
  target[position++] = 0x80 | length;
@@ -1703,13 +1726,13 @@
1703
1726
  }
1704
1727
  }
1705
1728
  } :
1706
- (object, safePrototype) => {
1729
+ (object) => {
1707
1730
  target[position++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
1708
1731
  let objectOffset = position - start;
1709
1732
  position += 2;
1710
1733
  let size = 0;
1711
1734
  for (let key in object) {
1712
- if (safePrototype || object.hasOwnProperty(key)) {
1735
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1713
1736
  pack(key);
1714
1737
  pack(object[key]);
1715
1738
  size++;
@@ -1721,12 +1744,12 @@
1721
1744
 
1722
1745
  const writeRecord = this.useRecords === false ? writePlainObject :
1723
1746
  (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)
1724
- (object, safePrototype) => {
1747
+ (object) => {
1725
1748
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1726
1749
  let objectOffset = position++ - start;
1727
1750
  let wroteKeys;
1728
1751
  for (let key in object) {
1729
- if (safePrototype || object.hasOwnProperty(key)) {
1752
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1730
1753
  nextTransition = transition[key];
1731
1754
  if (nextTransition)
1732
1755
  transition = nextTransition;
@@ -1765,10 +1788,10 @@
1765
1788
  insertNewRecord(transition, Object.keys(object), objectOffset, 0);
1766
1789
  }
1767
1790
  } :
1768
- (object, safePrototype) => {
1791
+ (object) => {
1769
1792
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1770
1793
  let newTransitions = 0;
1771
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1794
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1772
1795
  nextTransition = transition[key];
1773
1796
  if (!nextTransition) {
1774
1797
  nextTransition = transition[key] = Object.create(null);
@@ -1788,16 +1811,16 @@
1788
1811
  }
1789
1812
  // now write the values
1790
1813
  for (let key in object)
1791
- if (safePrototype || object.hasOwnProperty(key)) {
1814
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1792
1815
  pack(object[key]);
1793
1816
  }
1794
1817
  };
1795
1818
 
1796
- // craete reference to useRecords if useRecords is a function
1819
+ // create reference to useRecords if useRecords is a function
1797
1820
  const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
1798
-
1799
- const writeObject = checkUseRecords ? (object, safePrototype) => {
1800
- checkUseRecords(object) ? writeRecord(object,safePrototype) : writePlainObject(object,safePrototype);
1821
+
1822
+ const writeObject = checkUseRecords ? (object) => {
1823
+ checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
1801
1824
  } : writeRecord;
1802
1825
 
1803
1826
  const makeRoom = (end) => {
@@ -1902,7 +1925,7 @@
1902
1925
  target[insertionOffset + start] = keysTarget[0];
1903
1926
  }
1904
1927
  };
1905
- const writeStruct = (object, safePrototype) => {
1928
+ const writeStruct = (object) => {
1906
1929
  let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1907
1930
  if (notifySharedUpdate)
1908
1931
  return hasSharedUpdate = true;
@@ -1916,16 +1939,22 @@
1916
1939
  return position;
1917
1940
  }, this);
1918
1941
  if (newPosition === 0) // bail and go to a msgpack object
1919
- return writeObject(object, true);
1942
+ return writeObject(object);
1920
1943
  position = newPosition;
1921
1944
  };
1922
1945
  }
1923
1946
  useBuffer(buffer) {
1924
1947
  // this means we are finished using our own buffer and we can write over it safely
1925
1948
  target = buffer;
1926
- targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
1949
+ target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength));
1927
1950
  position = 0;
1928
1951
  }
1952
+ set position (value) {
1953
+ position = value;
1954
+ }
1955
+ get position() {
1956
+ return position;
1957
+ }
1929
1958
  clearSharedData() {
1930
1959
  if (this.structures)
1931
1960
  this.structures = [];
@@ -1994,7 +2023,7 @@
1994
2023
  target[position++] = 0x65; // 'e' for error
1995
2024
  target[position++] = 0;
1996
2025
  }
1997
- pack([ error.name, error.message ]);
2026
+ pack([ error.name, error.message, error.cause ]);
1998
2027
  }
1999
2028
  }, {
2000
2029
  pack(regex, allocateForWrite, pack) {
@@ -2047,6 +2076,7 @@
2047
2076
  }
2048
2077
  target[position++] = 0x74; // "t" for typed array
2049
2078
  target[position++] = type;
2079
+ if (!typedArray.buffer) typedArray = new Uint8Array(typedArray);
2050
2080
  target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
2051
2081
  }
2052
2082
  function writeBuffer(buffer, allocateForWrite) {
@@ -2270,6 +2300,8 @@
2270
2300
  exports.FLOAT32_OPTIONS = FLOAT32_OPTIONS;
2271
2301
  exports.NEVER = NEVER;
2272
2302
  exports.Packr = Packr;
2303
+ exports.RESERVE_START_SPACE = RESERVE_START_SPACE;
2304
+ exports.RESET_BUFFER_MODE = RESET_BUFFER_MODE;
2273
2305
  exports.REUSE_BUFFER_MODE = REUSE_BUFFER_MODE;
2274
2306
  exports.Unpackr = Unpackr;
2275
2307
  exports.addExtension = addExtension;