msgpackr 1.7.0-alpha7 → 1.7.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/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?.restoreStructures)
199
200
  restoreStructures();
200
201
  currentStructures = null;
201
202
  src = null;
@@ -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 {
@@ -932,7 +941,16 @@ function readKey() {
932
941
 
933
942
  // the registration of the record definition extension (as "r")
934
943
  const recordDefinition = (id, highByte) => {
935
- var structure = read();
944
+ let structure;
945
+ if (currentUnpackr.freezeData) {
946
+ currentUnpackr.freezeData = false;
947
+ try {
948
+ structure = read();
949
+ } finally {
950
+ currentUnpackr.freezeData = true;
951
+ }
952
+ } else
953
+ structure = read();
936
954
  let firstByte = id;
937
955
  if (highByte !== undefined) {
938
956
  id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
@@ -2078,6 +2096,14 @@ const DATE = 16;
2078
2096
  const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
2079
2097
  TYPE_NAMES[DATE] = 'date';
2080
2098
  const float32Headers = [false, true, true, false, false, true, true, false];
2099
+ let evalSupported;
2100
+ try {
2101
+ new Function('');
2102
+ evalSupported = true;
2103
+ } catch(error) {
2104
+ // if eval variants are not supported, do not create inline object readers ever
2105
+ }
2106
+
2081
2107
  let updatedPosition;
2082
2108
  const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
2083
2109
  let textEncoder$1, currentSource;
@@ -2502,9 +2528,8 @@ function onLoadedStructures$1(sharedData) {
2502
2528
  this.lastTypedStructuresLength = typed.length;
2503
2529
  return named;
2504
2530
  }
2505
- var sourceSymbol = Symbol('source');
2531
+ var sourceSymbol = Symbol.for('source');
2506
2532
  function readStruct$1(src, position, srcEnd, unpackr) {
2507
- // var stringLength = (src[position++] << 8) | src[position++];
2508
2533
  let recordId = src[position++] - 0x20;
2509
2534
  if (recordId >= 24) {
2510
2535
  switch(recordId) {
@@ -2535,23 +2560,13 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2535
2560
  };
2536
2561
  var prototype = construct.prototype;
2537
2562
  let properties = [];
2538
- Object.defineProperty(prototype, 'toJSON', {
2539
- value() {
2540
- // return an enumerable object with own properties to JSON stringify
2541
- let resolved = {};
2542
- for (let i = 0, l = properties.length; i < l; i++) {
2543
- let key = properties[i].key;
2544
- resolved[key] = this[key];
2545
- }
2546
- return resolved;
2547
- },
2548
- // not enumerable or anything
2549
- });
2550
2563
  let currentOffset = 0;
2551
2564
  let lastRefProperty;
2552
2565
  for (let i = 0, l = structure.length; i < l; i++) {
2553
2566
  let definition = structure[i];
2554
2567
  let [ type, size, key, enumerationOffset ] = definition;
2568
+ if (key === '__proto__')
2569
+ key = '__proto_';
2555
2570
  let property = {
2556
2571
  key,
2557
2572
  offset: currentOffset,
@@ -2565,13 +2580,13 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2565
2580
  case 0: getRef = () => 0; break;
2566
2581
  case 1:
2567
2582
  getRef = (source, position) => {
2568
- let ref = source.src[position + property.offset];
2583
+ let ref = source.bytes[position + property.offset];
2569
2584
  return ref >= 0xf6 ? toConstant(ref) : ref;
2570
2585
  };
2571
2586
  break;
2572
2587
  case 2:
2573
2588
  getRef = (source, position) => {
2574
- let src = source.src;
2589
+ let src = source.bytes;
2575
2590
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2576
2591
  let ref = dataView.getUint16(position + property.offset, true);
2577
2592
  return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
@@ -2579,7 +2594,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2579
2594
  break;
2580
2595
  case 4:
2581
2596
  getRef = (source, position) => {
2582
- let src = source.src;
2597
+ let src = source.bytes;
2583
2598
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2584
2599
  let ref = dataView.getUint32(position + property.offset, true);
2585
2600
  return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
@@ -2595,9 +2610,8 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2595
2610
  lastRefProperty.next = property;
2596
2611
  lastRefProperty = property;
2597
2612
  property.multiGetCount = 0;
2598
- get = function() {
2599
- let source = this[sourceSymbol];
2600
- let src = source.src;
2613
+ get = function(source) {
2614
+ let src = source.bytes;
2601
2615
  let position = source.position;
2602
2616
  let refStart = currentOffset + position;
2603
2617
  let ref = getRef(source, position);
@@ -2613,7 +2627,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2613
2627
  next = next.next;
2614
2628
  }
2615
2629
  if (end == null)
2616
- end = source.srcEnd - refStart;
2630
+ end = source.bytesEnd - refStart;
2617
2631
  if (source.srcString) {
2618
2632
  return source.srcString.slice(ref, end);
2619
2633
  }
@@ -2629,7 +2643,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2629
2643
  asciiEnd = null;
2630
2644
  } while((next = next.next));
2631
2645
  if (asciiEnd == null)
2632
- asciiEnd = source.srcEnd - refStart
2646
+ asciiEnd = source.bytesEnd - refStart
2633
2647
  source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
2634
2648
  return source.srcString.slice(ref, end);
2635
2649
  }
@@ -2647,13 +2661,12 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2647
2661
  if (lastRefProperty && !lastRefProperty.next)
2648
2662
  lastRefProperty.next = property;
2649
2663
  lastRefProperty = property;
2650
- get = function() {
2651
- let source = this[sourceSymbol];
2664
+ get = function(source) {
2652
2665
  let position = source.position;
2653
2666
  let refStart = currentOffset + position;
2654
2667
  let ref = getRef(source, position);
2655
2668
  if (typeof ref !== 'number') return ref;
2656
- let src = source.src;
2669
+ let src = source.bytes;
2657
2670
  let end, next = property.next;
2658
2671
  while(next) {
2659
2672
  end = next.getRef(source, position);
@@ -2664,7 +2677,7 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2664
2677
  next = next.next;
2665
2678
  }
2666
2679
  if (end == null)
2667
- end = source.srcEnd - refStart;
2680
+ end = source.bytesEnd - refStart;
2668
2681
  if (type === UTF8) {
2669
2682
  return src.toString('utf8', ref + refStart, end + refStart);
2670
2683
  } else {
@@ -2680,9 +2693,8 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2680
2693
  case NUMBER:
2681
2694
  switch(size) {
2682
2695
  case 4:
2683
- get = function () {
2684
- let source = this[sourceSymbol];
2685
- let src = source.src;
2696
+ get = function (source) {
2697
+ let src = source.bytes;
2686
2698
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2687
2699
  let position = source.position + property.offset;
2688
2700
  let value = dataView.getInt32(position, true);
@@ -2699,9 +2711,8 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2699
2711
  };
2700
2712
  break;
2701
2713
  case 8:
2702
- get = function () {
2703
- let source = this[sourceSymbol];
2704
- let src = source.src;
2714
+ get = function (source) {
2715
+ let src = source.bytes;
2705
2716
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2706
2717
  let value = dataView.getFloat64(source.position + property.offset, true);
2707
2718
  if (isNaN(value)) {
@@ -2713,9 +2724,8 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2713
2724
  };
2714
2725
  break;
2715
2726
  case 1:
2716
- get = function () {
2717
- let source = this[sourceSymbol];
2718
- let src = source.src;
2727
+ get = function (source) {
2728
+ let src = source.bytes;
2719
2729
  let value = src[source.position + property.offset];
2720
2730
  return value < 0xf6 ? value : toConstant(value);
2721
2731
  };
@@ -2723,9 +2733,8 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2723
2733
  }
2724
2734
  break;
2725
2735
  case DATE:
2726
- get = function () {
2727
- let source = this[sourceSymbol];
2728
- let src = source.src;
2736
+ get = function (source) {
2737
+ let src = source.bytes;
2729
2738
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2730
2739
  return new Date(dataView.getFloat64(source.position + property.offset, true));
2731
2740
  };
@@ -2734,15 +2743,45 @@ function readStruct$1(src, position, srcEnd, unpackr) {
2734
2743
  }
2735
2744
  property.get = get;
2736
2745
  }
2737
- for (let property of properties) // assign in enumeration order
2738
- Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
2746
+ // TODO: load the srcString for faster string decoding on toJSON
2747
+ if (evalSupported) {
2748
+ let objectLiteralProperties = [];
2749
+ let args = [];
2750
+ let i = 0;
2751
+ for (let property of properties) { // assign in enumeration order
2752
+ Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
2753
+ let valueFunction = 'v' + i++;
2754
+ args.push(valueFunction);
2755
+ objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
2756
+ }
2757
+ let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
2758
+ Object.defineProperty(prototype, 'toJSON', {
2759
+ value() {
2760
+ return toObject(this[sourceSymbol]);
2761
+ }
2762
+ });
2763
+ } else {
2764
+ Object.defineProperty(prototype, 'toJSON', {
2765
+ value() {
2766
+ // return an enumerable object with own properties to JSON stringify
2767
+ let resolved = {};
2768
+ for (let i = 0, l = properties.length; i < l; i++) {
2769
+ let key = properties[i].key;
2770
+
2771
+ resolved[key] = this[key];
2772
+ }
2773
+ return resolved;
2774
+ },
2775
+ // not enumerable or anything
2776
+ });
2777
+ }
2739
2778
  }
2740
2779
  var instance = new construct();
2741
2780
  instance[sourceSymbol] = {
2742
- src,
2781
+ bytes: src,
2743
2782
  position,
2744
2783
  srcString: '',
2745
- srcEnd
2784
+ bytesEnd: srcEnd
2746
2785
  };
2747
2786
  return instance;
2748
2787
  }
@@ -2755,12 +2794,17 @@ function toConstant(code) {
2755
2794
  }
2756
2795
  throw new Error('Unknown constant');
2757
2796
  }
2797
+ function withSource(get) {
2798
+ return function() {
2799
+ return get(this[sourceSymbol]);
2800
+ }
2801
+ }
2758
2802
 
2759
2803
  function saveState$1() {
2760
2804
  if (currentSource) {
2761
- currentSource.src = Uint8Array.prototype.slice.call(currentSource.src, currentSource.position, currentSource.srcEnd);
2805
+ currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
2762
2806
  currentSource.position = 0;
2763
- currentSource.srcEnd = currentSource.src.length;
2807
+ currentSource.bytesEnd = currentSource.bytes.length;
2764
2808
  }
2765
2809
  }
2766
2810
  function prepareStructures$1(structures, packr) {