msgpackr 1.7.0-beta1 → 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/test.js CHANGED
@@ -179,6 +179,7 @@
179
179
  let result;
180
180
  if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
181
181
  result = readStruct(src, position, srcEnd, currentUnpackr);
182
+ src = null; // dispose of this so that recursive unpack calls don't save state
182
183
  if (!(options && options.lazy) && result)
183
184
  result = result.toJSON();
184
185
  position = srcEnd;
@@ -189,7 +190,7 @@
189
190
 
190
191
  if (position == srcEnd) {
191
192
  // finished reading this source, cleanup references
192
- if (currentStructures.restoreStructures)
193
+ if (currentStructures?.restoreStructures)
193
194
  restoreStructures();
194
195
  currentStructures = null;
195
196
  src = null;
@@ -244,7 +245,10 @@
244
245
  if (currentUnpackr.mapsAsObjects) {
245
246
  let object = {};
246
247
  for (let i = 0; i < token; i++) {
247
- object[readKey()] = read();
248
+ let key = readKey();
249
+ if (key === '__proto__')
250
+ key = '__proto_';
251
+ object[key] = read();
248
252
  }
249
253
  return object
250
254
  } else {
@@ -473,7 +477,7 @@
473
477
  // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
474
478
  if (readObject.count++ > inlineObjectReadThreshold) {
475
479
  let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
476
- '({' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
480
+ '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
477
481
  if (structure.highByte === 0)
478
482
  structure.read = createSecondByteReader(firstId, structure.read);
479
483
  return readObject() // second byte is already read, if there is one so immediately read object
@@ -481,6 +485,8 @@
481
485
  let object = {};
482
486
  for (let i = 0, l = structure.length; i < l; i++) {
483
487
  let key = structure[i];
488
+ if (key === '__proto__')
489
+ key = '__proto_';
484
490
  object[key] = read();
485
491
  }
486
492
  if (currentUnpackr.freezeData)
@@ -601,7 +607,10 @@
601
607
  if (currentUnpackr.mapsAsObjects) {
602
608
  let object = {};
603
609
  for (let i = 0; i < length; i++) {
604
- object[readKey()] = read();
610
+ let key = readKey();
611
+ if (key === '__proto__')
612
+ key = '__proto_';
613
+ object[key] = read();
605
614
  }
606
615
  return object
607
616
  } else {
@@ -1997,6 +2006,14 @@
1997
2006
  const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
1998
2007
  TYPE_NAMES[DATE] = 'date';
1999
2008
  const float32Headers = [false, true, true, false, false, true, true, false];
2009
+ let evalSupported;
2010
+ try {
2011
+ new Function('');
2012
+ evalSupported = true;
2013
+ } catch(error) {
2014
+ // if eval variants are not supported, do not create inline object readers ever
2015
+ }
2016
+
2000
2017
  let updatedPosition;
2001
2018
  const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
2002
2019
  let textEncoder$1, currentSource;
@@ -2453,23 +2470,13 @@
2453
2470
  };
2454
2471
  var prototype = construct.prototype;
2455
2472
  let properties = [];
2456
- Object.defineProperty(prototype, 'toJSON', {
2457
- value() {
2458
- // return an enumerable object with own properties to JSON stringify
2459
- let resolved = {};
2460
- for (let i = 0, l = properties.length; i < l; i++) {
2461
- let key = properties[i].key;
2462
- resolved[key] = this[key];
2463
- }
2464
- return resolved;
2465
- },
2466
- // not enumerable or anything
2467
- });
2468
2473
  let currentOffset = 0;
2469
2474
  let lastRefProperty;
2470
2475
  for (let i = 0, l = structure.length; i < l; i++) {
2471
2476
  let definition = structure[i];
2472
2477
  let [ type, size, key, enumerationOffset ] = definition;
2478
+ if (key === '__proto__')
2479
+ key = '__proto_';
2473
2480
  let property = {
2474
2481
  key,
2475
2482
  offset: currentOffset,
@@ -2513,8 +2520,7 @@
2513
2520
  lastRefProperty.next = property;
2514
2521
  lastRefProperty = property;
2515
2522
  property.multiGetCount = 0;
2516
- get = function() {
2517
- let source = this[sourceSymbol];
2523
+ get = function(source) {
2518
2524
  let src = source.bytes;
2519
2525
  let position = source.position;
2520
2526
  let refStart = currentOffset + position;
@@ -2565,8 +2571,7 @@
2565
2571
  if (lastRefProperty && !lastRefProperty.next)
2566
2572
  lastRefProperty.next = property;
2567
2573
  lastRefProperty = property;
2568
- get = function() {
2569
- let source = this[sourceSymbol];
2574
+ get = function(source) {
2570
2575
  let position = source.position;
2571
2576
  let refStart = currentOffset + position;
2572
2577
  let ref = getRef(source, position);
@@ -2598,8 +2603,7 @@
2598
2603
  case NUMBER:
2599
2604
  switch(size) {
2600
2605
  case 4:
2601
- get = function () {
2602
- let source = this[sourceSymbol];
2606
+ get = function (source) {
2603
2607
  let src = source.bytes;
2604
2608
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2605
2609
  let position = source.position + property.offset;
@@ -2617,8 +2621,7 @@
2617
2621
  };
2618
2622
  break;
2619
2623
  case 8:
2620
- get = function () {
2621
- let source = this[sourceSymbol];
2624
+ get = function (source) {
2622
2625
  let src = source.bytes;
2623
2626
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2624
2627
  let value = dataView.getFloat64(source.position + property.offset, true);
@@ -2631,8 +2634,7 @@
2631
2634
  };
2632
2635
  break;
2633
2636
  case 1:
2634
- get = function () {
2635
- let source = this[sourceSymbol];
2637
+ get = function (source) {
2636
2638
  let src = source.bytes;
2637
2639
  let value = src[source.position + property.offset];
2638
2640
  return value < 0xf6 ? value : toConstant(value);
@@ -2641,8 +2643,7 @@
2641
2643
  }
2642
2644
  break;
2643
2645
  case DATE:
2644
- get = function () {
2645
- let source = this[sourceSymbol];
2646
+ get = function (source) {
2646
2647
  let src = source.bytes;
2647
2648
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2648
2649
  return new Date(dataView.getFloat64(source.position + property.offset, true));
@@ -2652,8 +2653,38 @@
2652
2653
  }
2653
2654
  property.get = get;
2654
2655
  }
2655
- for (let property of properties) // assign in enumeration order
2656
- Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
2656
+ // TODO: load the srcString for faster string decoding on toJSON
2657
+ if (evalSupported) {
2658
+ let objectLiteralProperties = [];
2659
+ let args = [];
2660
+ let i = 0;
2661
+ for (let property of properties) { // assign in enumeration order
2662
+ Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
2663
+ let valueFunction = 'v' + i++;
2664
+ args.push(valueFunction);
2665
+ objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
2666
+ }
2667
+ let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
2668
+ Object.defineProperty(prototype, 'toJSON', {
2669
+ value() {
2670
+ return toObject(this[sourceSymbol]);
2671
+ }
2672
+ });
2673
+ } else {
2674
+ Object.defineProperty(prototype, 'toJSON', {
2675
+ value() {
2676
+ // return an enumerable object with own properties to JSON stringify
2677
+ let resolved = {};
2678
+ for (let i = 0, l = properties.length; i < l; i++) {
2679
+ let key = properties[i].key;
2680
+
2681
+ resolved[key] = this[key];
2682
+ }
2683
+ return resolved;
2684
+ },
2685
+ // not enumerable or anything
2686
+ });
2687
+ }
2657
2688
  }
2658
2689
  var instance = new construct();
2659
2690
  instance[sourceSymbol] = {
@@ -2673,6 +2704,11 @@
2673
2704
  }
2674
2705
  throw new Error('Unknown constant');
2675
2706
  }
2707
+ function withSource(get) {
2708
+ return function() {
2709
+ return get(this[sourceSymbol]);
2710
+ }
2711
+ }
2676
2712
 
2677
2713
  function saveState$1() {
2678
2714
  if (currentSource) {
@@ -3045,6 +3081,17 @@
3045
3081
  assert.deepEqual(data, deserialized);
3046
3082
  assert.equal(deserialized.extendedInstance.getDouble(), 8);
3047
3083
  });
3084
+ test('proto handling', function() {
3085
+ var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');
3086
+ var decoded = unpack(pack(objectWithProto));
3087
+ assert(!decoded.foo);
3088
+ var objectsWithProto = [objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto, objectWithProto];
3089
+ let packr = new Packr$1();
3090
+ var decoded = packr.unpack(packr.pack(objectsWithProto));
3091
+ for (let object of decoded) {
3092
+ assert(!decoded.foo);
3093
+ }
3094
+ });
3048
3095
 
3049
3096
  test.skip('text decoder', function() {
3050
3097
  let td = new TextDecoder('ISO-8859-15');