msgpackr 1.11.2 → 1.11.4

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/node.cjs CHANGED
@@ -971,7 +971,10 @@ function asSafeString(property) {
971
971
  if (typeof property === 'string') return property;
972
972
  if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
973
973
  if (property == null) return property + '';
974
- throw new Error('Invalid property type for record', typeof property);
974
+ if (currentUnpackr.allowArraysInMapKeys && Array.isArray(property) && property.flat().every(item => ['string', 'number', 'boolean', 'bigint'].includes(typeof item))) {
975
+ return property.flat().toString();
976
+ }
977
+ throw new Error(`Invalid property type for record: ${typeof property}`);
975
978
  }
976
979
  // the registration of the record definition extension (as "r")
977
980
  const recordDefinition = (id, highByte) => {
@@ -1021,20 +1024,33 @@ currentExtensions[0x69] = (data) => {
1021
1024
  referenceMap = new Map();
1022
1025
  let token = src[position$1];
1023
1026
  let target;
1024
- // TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
1025
- // ahead past references to record structure definitions
1027
+ // TODO: handle any other types that can cycle and make the code more robust if there are other extensions
1026
1028
  if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
1027
1029
  target = [];
1030
+ else if (token >= 0x80 && token < 0x90 || token == 0xde || token == 0xdf)
1031
+ target = new Map();
1032
+ else if ((token >= 0xc7 && token <= 0xc9 || token >= 0xd4 && token <= 0xd8) && src[position$1 + 1] === 0x73)
1033
+ target = new Set();
1028
1034
  else
1029
1035
  target = {};
1030
1036
 
1031
1037
  let refEntry = { target }; // a placeholder object
1032
1038
  referenceMap.set(id, refEntry);
1033
1039
  let targetProperties = read(); // read the next value as the target object to id
1034
- if (refEntry.used) // there is a cycle, so we have to assign properties to original target
1035
- return Object.assign(target, targetProperties)
1036
- refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
1037
- return targetProperties // no cycle, can just use the returned read object
1040
+ if (!refEntry.used) {
1041
+ // no cycle, can just use the returned read object
1042
+ return refEntry.target = targetProperties // replace the placeholder with the real one
1043
+ } else {
1044
+ // there is a cycle, so we have to assign properties to original target
1045
+ Object.assign(target, targetProperties);
1046
+ }
1047
+
1048
+ // copy over map/set entries if we're able to
1049
+ if (target instanceof Map)
1050
+ for (let [k, v] of targetProperties.entries()) target.set(k, v);
1051
+ if (target instanceof Set)
1052
+ for (let i of Array.from(targetProperties)) target.add(i);
1053
+ return target
1038
1054
  };
1039
1055
 
1040
1056
  currentExtensions[0x70] = (data) => {
@@ -1053,18 +1069,16 @@ const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uin
1053
1069
  let glbl = typeof globalThis === 'object' ? globalThis : window;
1054
1070
  currentExtensions[0x74] = (data) => {
1055
1071
  let typeCode = data[0];
1072
+ // we always have to slice to get a new ArrayBuffer that is aligned
1073
+ let buffer = Uint8Array.prototype.slice.call(data, 1).buffer;
1074
+
1056
1075
  let typedArrayName = typedArrays[typeCode];
1057
1076
  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
- }
1077
+ if (typeCode === 16) return buffer
1078
+ if (typeCode === 17) return new DataView(buffer)
1064
1079
  throw new Error('Could not find typed array for code ' + typeCode)
1065
1080
  }
1066
- // we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
1067
- return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
1081
+ return new glbl[typedArrayName](buffer)
1068
1082
  };
1069
1083
  currentExtensions[0x78] = () => {
1070
1084
  let data = read();
@@ -1092,13 +1106,13 @@ currentExtensions[0xff] = (data) => {
1092
1106
  return new Date(
1093
1107
  ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
1094
1108
  ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
1095
- else if (data.length == 12)// TODO: Implement support for negative
1109
+ else if (data.length == 12)
1096
1110
  return new Date(
1097
1111
  ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
1098
1112
  (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
1099
1113
  else
1100
1114
  return new Date('invalid')
1101
- }; // notepack defines extension 0 to mean undefined, so use that as the default here
1115
+ };
1102
1116
  // registration of bulk record definition?
1103
1117
  // currentExtensions[0x52] = () =>
1104
1118
 
@@ -1703,11 +1717,11 @@ class Packr extends Unpackr {
1703
1717
  } else if (type === 'boolean') {
1704
1718
  target[position++] = value ? 0xc3 : 0xc2;
1705
1719
  } else if (type === 'bigint') {
1706
- if (value < (BigInt(1)<<BigInt(63)) && value >= -(BigInt(1)<<BigInt(63))) {
1720
+ if (value < 0x8000000000000000 && value >= -0x8000000000000000) {
1707
1721
  // use a signed int as long as it fits
1708
1722
  target[position++] = 0xd3;
1709
1723
  targetView.setBigInt64(position, value);
1710
- } else if (value < (BigInt(1)<<BigInt(64)) && value > 0) {
1724
+ } else if (value < 0x10000000000000000 && value > 0) {
1711
1725
  // if we can fit an unsigned int, use that
1712
1726
  target[position++] = 0xcf;
1713
1727
  targetView.setBigUint64(position, value);
@@ -1718,7 +1732,7 @@ class Packr extends Unpackr {
1718
1732
  targetView.setFloat64(position, Number(value));
1719
1733
  } else if (this.largeBigIntToString) {
1720
1734
  return pack(value.toString());
1721
- } else if (this.useBigIntExtension && value < BigInt(2)**BigInt(1023) && value > -(BigInt(2)**BigInt(1023))) {
1735
+ } else if ((this.useBigIntExtension || this.moreTypes) && value < BigInt(2)**BigInt(1023) && value > -(BigInt(2)**BigInt(1023))) {
1722
1736
  target[position++] = 0xc7;
1723
1737
  position++;
1724
1738
  target[position++] = 0x42; // "B" for BigInt
@@ -2037,7 +2051,7 @@ class Packr extends Unpackr {
2037
2051
  }
2038
2052
  }
2039
2053
 
2040
- extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
2054
+ extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, DataView, C1Type ];
2041
2055
  extensions = [{
2042
2056
  pack(date, allocateForWrite, pack) {
2043
2057
  let seconds = date.getTime() / 1000;
@@ -2124,6 +2138,13 @@ extensions = [{
2124
2138
  else
2125
2139
  writeBuffer(typedArray, allocateForWrite);
2126
2140
  }
2141
+ }, {
2142
+ pack(arrayBuffer, allocateForWrite) {
2143
+ if (this.moreTypes)
2144
+ writeExtBuffer(arrayBuffer, 0x11, allocateForWrite);
2145
+ else
2146
+ writeBuffer(hasNodeBuffer$1 ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
2147
+ }
2127
2148
  }, {
2128
2149
  pack(c1, allocateForWrite) { // specific 0xC1 object
2129
2150
  let { target, position} = allocateForWrite(1);
@@ -2756,10 +2777,14 @@ function readStruct(src, position, srcEnd, unpackr) {
2756
2777
  throw new Error('Could not find typed structure ' + recordId);
2757
2778
  }
2758
2779
  var construct = structure.construct;
2780
+ var fullConstruct = structure.fullConstruct;
2759
2781
  if (!construct) {
2760
2782
  construct = structure.construct = function LazyObject() {
2761
2783
  };
2762
- var prototype = construct.prototype;
2784
+ fullConstruct = structure.fullConstruct = function LoadedObject() {
2785
+ };
2786
+ fullConstruct.prototype = unpackr.structPrototype ?? {};
2787
+ var prototype = construct.prototype = unpackr.structPrototype ? Object.create(unpackr.structPrototype) : {};
2763
2788
  let properties = [];
2764
2789
  let currentOffset = 0;
2765
2790
  let lastRefProperty;
@@ -2960,12 +2985,12 @@ function readStruct(src, position, srcEnd, unpackr) {
2960
2985
  Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
2961
2986
  let valueFunction = 'v' + i++;
2962
2987
  args.push(valueFunction);
2963
- objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
2988
+ objectLiteralProperties.push('o[' + JSON.stringify(property.key) + ']=' + valueFunction + '(s)');
2964
2989
  }
2965
2990
  if (hasInheritedProperties) {
2966
2991
  objectLiteralProperties.push('__proto__:this');
2967
2992
  }
2968
- let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
2993
+ let toObject = (new Function(...args, 'var c=this;return function(s){var o=new c();' + objectLiteralProperties.join(';') + ';return o;}')).apply(fullConstruct, properties.map(prop => prop.get));
2969
2994
  Object.defineProperty(prototype, 'toJSON', {
2970
2995
  value(omitUnderscoredProperties) {
2971
2996
  return toObject.call(this, this[sourceSymbol]);