msgpackr 1.7.0-beta1 → 1.7.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/dist/node.cjs CHANGED
@@ -185,6 +185,7 @@ function checkedRead(options) {
185
185
  let result;
186
186
  if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
187
187
  result = readStruct(src, position, srcEnd, currentUnpackr);
188
+ src = null; // dispose of this so that recursive unpack calls don't save state
188
189
  if (!(options && options.lazy) && result)
189
190
  result = result.toJSON();
190
191
  position = srcEnd;
@@ -195,7 +196,7 @@ function checkedRead(options) {
195
196
 
196
197
  if (position == srcEnd) {
197
198
  // finished reading this source, cleanup references
198
- if (currentStructures.restoreStructures)
199
+ if (currentStructures && currentStructures.restoreStructures)
199
200
  restoreStructures();
200
201
  currentStructures = null;
201
202
  src = null;
@@ -210,7 +211,7 @@ function checkedRead(options) {
210
211
  // else more to read, but we are reading sequentially, so don't clear source yet
211
212
  return result
212
213
  } catch(error) {
213
- if (currentStructures?.restoreStructures)
214
+ if (currentStructures && currentStructures.restoreStructures)
214
215
  restoreStructures();
215
216
  clearSource();
216
217
  if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position > srcEnd) {
@@ -250,7 +251,10 @@ function read() {
250
251
  if (currentUnpackr.mapsAsObjects) {
251
252
  let object = {};
252
253
  for (let i = 0; i < token; i++) {
253
- object[readKey()] = read();
254
+ let key = readKey();
255
+ if (key === '__proto__')
256
+ key = '__proto_';
257
+ object[key] = read();
254
258
  }
255
259
  return object
256
260
  } else {
@@ -479,7 +483,7 @@ function createStructureReader(structure, firstId) {
479
483
  // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
480
484
  if (readObject.count++ > inlineObjectReadThreshold) {
481
485
  let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
482
- '({' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
486
+ '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
483
487
  if (structure.highByte === 0)
484
488
  structure.read = createSecondByteReader(firstId, structure.read);
485
489
  return readObject() // second byte is already read, if there is one so immediately read object
@@ -487,6 +491,8 @@ function createStructureReader(structure, firstId) {
487
491
  let object = {};
488
492
  for (let i = 0, l = structure.length; i < l; i++) {
489
493
  let key = structure[i];
494
+ if (key === '__proto__')
495
+ key = '__proto_';
490
496
  object[key] = read();
491
497
  }
492
498
  if (currentUnpackr.freezeData)
@@ -647,7 +653,10 @@ function readMap(length) {
647
653
  if (currentUnpackr.mapsAsObjects) {
648
654
  let object = {};
649
655
  for (let i = 0; i < length; i++) {
650
- object[readKey()] = read();
656
+ let key = readKey();
657
+ if (key === '__proto__')
658
+ key = '__proto_';
659
+ object[key] = read();
651
660
  }
652
661
  return object
653
662
  } else {
@@ -1245,12 +1254,11 @@ class Packr extends Unpackr {
1245
1254
  writeStruct(value);
1246
1255
  else
1247
1256
  pack(value);
1248
- if (bundledStrings$1) {
1249
- writeBundles(start, pack);
1250
- }
1251
- packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
1252
1257
  if (referenceMap && referenceMap.idsToInsert) {
1253
- position$1 += referenceMap.idsToInsert.length * 6;
1258
+ let incrementPosition = referenceMap.idsToInsert.length * 6;
1259
+ if (bundledStrings$1)
1260
+ writeBundles(start, pack, incrementPosition);
1261
+ position$1 += incrementPosition;
1254
1262
  if (position$1 > safeEnd)
1255
1263
  makeRoom(position$1);
1256
1264
  packr.offset = position$1;
@@ -1258,6 +1266,9 @@ class Packr extends Unpackr {
1258
1266
  referenceMap = null;
1259
1267
  return serialized
1260
1268
  }
1269
+ if (bundledStrings$1)
1270
+ writeBundles(start, pack, 0);
1271
+ packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
1261
1272
  if (encodeOptions & REUSE_BUFFER_MODE) {
1262
1273
  target.start = start;
1263
1274
  target.end = position$1;
@@ -2036,9 +2047,9 @@ function insertIds(serialized, idsToInsert) {
2036
2047
  return serialized
2037
2048
  }
2038
2049
 
2039
- function writeBundles(start, pack) {
2050
+ function writeBundles(start, pack, incrementPosition) {
2040
2051
  if (bundledStrings$1.length > 0) {
2041
- targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
2052
+ targetView.setUint32(bundledStrings$1.position + start, position$1 + incrementPosition - bundledStrings$1.position - start);
2042
2053
  let writeStrings = bundledStrings$1;
2043
2054
  bundledStrings$1 = null;
2044
2055
  pack(writeStrings[0]);
@@ -2087,6 +2098,14 @@ const DATE = 16;
2087
2098
  const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
2088
2099
  TYPE_NAMES[DATE] = 'date';
2089
2100
  const float32Headers = [false, true, true, false, false, true, true, false];
2101
+ let evalSupported;
2102
+ try {
2103
+ new Function('');
2104
+ evalSupported = true;
2105
+ } catch(error) {
2106
+ // if eval variants are not supported, do not create inline object readers ever
2107
+ }
2108
+
2090
2109
  let updatedPosition;
2091
2110
  const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
2092
2111
  let textEncoder$1, currentSource;
@@ -2523,7 +2542,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2523
2542
  case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
2524
2543
  }
2525
2544
  }
2526
- let structure = unpackr.typedStructs?.[recordId];
2545
+ let structure = unpackr.typedStructs && unpackr.typedStructs[recordId];
2527
2546
  if (!structure) {
2528
2547
  // copy src buffer because getStructures will override it
2529
2548
  src = Uint8Array.prototype.slice.call(src, position, srcEnd);
@@ -2543,23 +2562,13 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2543
2562
  };
2544
2563
  var prototype = construct.prototype;
2545
2564
  let properties = [];
2546
- Object.defineProperty(prototype, 'toJSON', {
2547
- value() {
2548
- // return an enumerable object with own properties to JSON stringify
2549
- let resolved = {};
2550
- for (let i = 0, l = properties.length; i < l; i++) {
2551
- let key = properties[i].key;
2552
- resolved[key] = this[key];
2553
- }
2554
- return resolved;
2555
- },
2556
- // not enumerable or anything
2557
- });
2558
2565
  let currentOffset = 0;
2559
2566
  let lastRefProperty;
2560
2567
  for (let i = 0, l = structure.length; i < l; i++) {
2561
2568
  let definition = structure[i];
2562
2569
  let [ type, size, key, enumerationOffset ] = definition;
2570
+ if (key === '__proto__')
2571
+ key = '__proto_';
2563
2572
  let property = {
2564
2573
  key,
2565
2574
  offset: currentOffset,
@@ -2603,8 +2612,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2603
2612
  lastRefProperty.next = property;
2604
2613
  lastRefProperty = property;
2605
2614
  property.multiGetCount = 0;
2606
- get = function() {
2607
- let source = this[sourceSymbol];
2615
+ get = function(source) {
2608
2616
  let src = source.bytes;
2609
2617
  let position = source.position;
2610
2618
  let refStart = currentOffset + position;
@@ -2655,8 +2663,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2655
2663
  if (lastRefProperty && !lastRefProperty.next)
2656
2664
  lastRefProperty.next = property;
2657
2665
  lastRefProperty = property;
2658
- get = function() {
2659
- let source = this[sourceSymbol];
2666
+ get = function(source) {
2660
2667
  let position = source.position;
2661
2668
  let refStart = currentOffset + position;
2662
2669
  let ref = getRef(source, position);
@@ -2688,8 +2695,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2688
2695
  case NUMBER:
2689
2696
  switch(size) {
2690
2697
  case 4:
2691
- get = function () {
2692
- let source = this[sourceSymbol];
2698
+ get = function (source) {
2693
2699
  let src = source.bytes;
2694
2700
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2695
2701
  let position = source.position + property.offset;
@@ -2707,8 +2713,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2707
2713
  };
2708
2714
  break;
2709
2715
  case 8:
2710
- get = function () {
2711
- let source = this[sourceSymbol];
2716
+ get = function (source) {
2712
2717
  let src = source.bytes;
2713
2718
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2714
2719
  let value = dataView.getFloat64(source.position + property.offset, true);
@@ -2721,8 +2726,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2721
2726
  };
2722
2727
  break;
2723
2728
  case 1:
2724
- get = function () {
2725
- let source = this[sourceSymbol];
2729
+ get = function (source) {
2726
2730
  let src = source.bytes;
2727
2731
  let value = src[source.position + property.offset];
2728
2732
  return value < 0xf6 ? value : toConstant(value);
@@ -2731,8 +2735,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2731
2735
  }
2732
2736
  break;
2733
2737
  case DATE:
2734
- get = function () {
2735
- let source = this[sourceSymbol];
2738
+ get = function (source) {
2736
2739
  let src = source.bytes;
2737
2740
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2738
2741
  return new Date(dataView.getFloat64(source.position + property.offset, true));
@@ -2742,8 +2745,38 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2742
2745
  }
2743
2746
  property.get = get;
2744
2747
  }
2745
- for (let property of properties) // assign in enumeration order
2746
- Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
2748
+ // TODO: load the srcString for faster string decoding on toJSON
2749
+ if (evalSupported) {
2750
+ let objectLiteralProperties = [];
2751
+ let args = [];
2752
+ let i = 0;
2753
+ for (let property of properties) { // assign in enumeration order
2754
+ Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
2755
+ let valueFunction = 'v' + i++;
2756
+ args.push(valueFunction);
2757
+ objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
2758
+ }
2759
+ let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
2760
+ Object.defineProperty(prototype, 'toJSON', {
2761
+ value() {
2762
+ return toObject(this[sourceSymbol]);
2763
+ }
2764
+ });
2765
+ } else {
2766
+ Object.defineProperty(prototype, 'toJSON', {
2767
+ value() {
2768
+ // return an enumerable object with own properties to JSON stringify
2769
+ let resolved = {};
2770
+ for (let i = 0, l = properties.length; i < l; i++) {
2771
+ let key = properties[i].key;
2772
+
2773
+ resolved[key] = this[key];
2774
+ }
2775
+ return resolved;
2776
+ },
2777
+ // not enumerable or anything
2778
+ });
2779
+ }
2747
2780
  }
2748
2781
  var instance = new construct();
2749
2782
  instance[sourceSymbol] = {
@@ -2763,6 +2796,11 @@ function toConstant(code) {
2763
2796
  }
2764
2797
  throw new Error('Unknown constant');
2765
2798
  }
2799
+ function withSource(get) {
2800
+ return function() {
2801
+ return get(this[sourceSymbol]);
2802
+ }
2803
+ }
2766
2804
 
2767
2805
  function saveState$1() {
2768
2806
  if (currentSource) {
@@ -2796,7 +2834,7 @@ function prepareStructures$1(structures, packr) {
2796
2834
  packr._mergeStructures(existing);
2797
2835
  return compatible;
2798
2836
  };
2799
- packr.lastTypedStructuresLength = packr.typedStructs?.length;
2837
+ packr.lastTypedStructuresLength = packr.typedStructs && packr.typedStructs.length;
2800
2838
  return structures;
2801
2839
  }
2802
2840