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/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 {
@@ -886,7 +895,16 @@
886
895
 
887
896
  // the registration of the record definition extension (as "r")
888
897
  const recordDefinition = (id, highByte) => {
889
- var structure = read();
898
+ let structure;
899
+ if (currentUnpackr.freezeData) {
900
+ currentUnpackr.freezeData = false;
901
+ try {
902
+ structure = read();
903
+ } finally {
904
+ currentUnpackr.freezeData = true;
905
+ }
906
+ } else
907
+ structure = read();
890
908
  let firstByte = id;
891
909
  if (highByte !== undefined) {
892
910
  id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
@@ -1988,6 +2006,14 @@
1988
2006
  const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
1989
2007
  TYPE_NAMES[DATE] = 'date';
1990
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
+
1991
2017
  let updatedPosition;
1992
2018
  const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
1993
2019
  let textEncoder$1, currentSource;
@@ -2412,9 +2438,8 @@
2412
2438
  this.lastTypedStructuresLength = typed.length;
2413
2439
  return named;
2414
2440
  }
2415
- var sourceSymbol = Symbol('source');
2441
+ var sourceSymbol = Symbol.for('source');
2416
2442
  function readStruct$1(src, position, srcEnd, unpackr) {
2417
- // var stringLength = (src[position++] << 8) | src[position++];
2418
2443
  let recordId = src[position++] - 0x20;
2419
2444
  if (recordId >= 24) {
2420
2445
  switch(recordId) {
@@ -2445,23 +2470,13 @@
2445
2470
  };
2446
2471
  var prototype = construct.prototype;
2447
2472
  let properties = [];
2448
- Object.defineProperty(prototype, 'toJSON', {
2449
- value() {
2450
- // return an enumerable object with own properties to JSON stringify
2451
- let resolved = {};
2452
- for (let i = 0, l = properties.length; i < l; i++) {
2453
- let key = properties[i].key;
2454
- resolved[key] = this[key];
2455
- }
2456
- return resolved;
2457
- },
2458
- // not enumerable or anything
2459
- });
2460
2473
  let currentOffset = 0;
2461
2474
  let lastRefProperty;
2462
2475
  for (let i = 0, l = structure.length; i < l; i++) {
2463
2476
  let definition = structure[i];
2464
2477
  let [ type, size, key, enumerationOffset ] = definition;
2478
+ if (key === '__proto__')
2479
+ key = '__proto_';
2465
2480
  let property = {
2466
2481
  key,
2467
2482
  offset: currentOffset,
@@ -2475,13 +2490,13 @@
2475
2490
  case 0: getRef = () => 0; break;
2476
2491
  case 1:
2477
2492
  getRef = (source, position) => {
2478
- let ref = source.src[position + property.offset];
2493
+ let ref = source.bytes[position + property.offset];
2479
2494
  return ref >= 0xf6 ? toConstant(ref) : ref;
2480
2495
  };
2481
2496
  break;
2482
2497
  case 2:
2483
2498
  getRef = (source, position) => {
2484
- let src = source.src;
2499
+ let src = source.bytes;
2485
2500
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2486
2501
  let ref = dataView.getUint16(position + property.offset, true);
2487
2502
  return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
@@ -2489,7 +2504,7 @@
2489
2504
  break;
2490
2505
  case 4:
2491
2506
  getRef = (source, position) => {
2492
- let src = source.src;
2507
+ let src = source.bytes;
2493
2508
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2494
2509
  let ref = dataView.getUint32(position + property.offset, true);
2495
2510
  return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
@@ -2505,9 +2520,8 @@
2505
2520
  lastRefProperty.next = property;
2506
2521
  lastRefProperty = property;
2507
2522
  property.multiGetCount = 0;
2508
- get = function() {
2509
- let source = this[sourceSymbol];
2510
- let src = source.src;
2523
+ get = function(source) {
2524
+ let src = source.bytes;
2511
2525
  let position = source.position;
2512
2526
  let refStart = currentOffset + position;
2513
2527
  let ref = getRef(source, position);
@@ -2523,7 +2537,7 @@
2523
2537
  next = next.next;
2524
2538
  }
2525
2539
  if (end == null)
2526
- end = source.srcEnd - refStart;
2540
+ end = source.bytesEnd - refStart;
2527
2541
  if (source.srcString) {
2528
2542
  return source.srcString.slice(ref, end);
2529
2543
  }
@@ -2539,7 +2553,7 @@
2539
2553
  asciiEnd = null;
2540
2554
  } while((next = next.next));
2541
2555
  if (asciiEnd == null)
2542
- asciiEnd = source.srcEnd - refStart
2556
+ asciiEnd = source.bytesEnd - refStart
2543
2557
  source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
2544
2558
  return source.srcString.slice(ref, end);
2545
2559
  }
@@ -2557,13 +2571,12 @@
2557
2571
  if (lastRefProperty && !lastRefProperty.next)
2558
2572
  lastRefProperty.next = property;
2559
2573
  lastRefProperty = property;
2560
- get = function() {
2561
- let source = this[sourceSymbol];
2574
+ get = function(source) {
2562
2575
  let position = source.position;
2563
2576
  let refStart = currentOffset + position;
2564
2577
  let ref = getRef(source, position);
2565
2578
  if (typeof ref !== 'number') return ref;
2566
- let src = source.src;
2579
+ let src = source.bytes;
2567
2580
  let end, next = property.next;
2568
2581
  while(next) {
2569
2582
  end = next.getRef(source, position);
@@ -2574,7 +2587,7 @@
2574
2587
  next = next.next;
2575
2588
  }
2576
2589
  if (end == null)
2577
- end = source.srcEnd - refStart;
2590
+ end = source.bytesEnd - refStart;
2578
2591
  if (type === UTF8) {
2579
2592
  return src.toString('utf8', ref + refStart, end + refStart);
2580
2593
  } else {
@@ -2590,9 +2603,8 @@
2590
2603
  case NUMBER:
2591
2604
  switch(size) {
2592
2605
  case 4:
2593
- get = function () {
2594
- let source = this[sourceSymbol];
2595
- let src = source.src;
2606
+ get = function (source) {
2607
+ let src = source.bytes;
2596
2608
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2597
2609
  let position = source.position + property.offset;
2598
2610
  let value = dataView.getInt32(position, true);
@@ -2609,9 +2621,8 @@
2609
2621
  };
2610
2622
  break;
2611
2623
  case 8:
2612
- get = function () {
2613
- let source = this[sourceSymbol];
2614
- let src = source.src;
2624
+ get = function (source) {
2625
+ let src = source.bytes;
2615
2626
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2616
2627
  let value = dataView.getFloat64(source.position + property.offset, true);
2617
2628
  if (isNaN(value)) {
@@ -2623,9 +2634,8 @@
2623
2634
  };
2624
2635
  break;
2625
2636
  case 1:
2626
- get = function () {
2627
- let source = this[sourceSymbol];
2628
- let src = source.src;
2637
+ get = function (source) {
2638
+ let src = source.bytes;
2629
2639
  let value = src[source.position + property.offset];
2630
2640
  return value < 0xf6 ? value : toConstant(value);
2631
2641
  };
@@ -2633,9 +2643,8 @@
2633
2643
  }
2634
2644
  break;
2635
2645
  case DATE:
2636
- get = function () {
2637
- let source = this[sourceSymbol];
2638
- let src = source.src;
2646
+ get = function (source) {
2647
+ let src = source.bytes;
2639
2648
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2640
2649
  return new Date(dataView.getFloat64(source.position + property.offset, true));
2641
2650
  };
@@ -2644,15 +2653,45 @@
2644
2653
  }
2645
2654
  property.get = get;
2646
2655
  }
2647
- for (let property of properties) // assign in enumeration order
2648
- 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
+ }
2649
2688
  }
2650
2689
  var instance = new construct();
2651
2690
  instance[sourceSymbol] = {
2652
- src,
2691
+ bytes: src,
2653
2692
  position,
2654
2693
  srcString: '',
2655
- srcEnd
2694
+ bytesEnd: srcEnd
2656
2695
  };
2657
2696
  return instance;
2658
2697
  }
@@ -2665,12 +2704,17 @@
2665
2704
  }
2666
2705
  throw new Error('Unknown constant');
2667
2706
  }
2707
+ function withSource(get) {
2708
+ return function() {
2709
+ return get(this[sourceSymbol]);
2710
+ }
2711
+ }
2668
2712
 
2669
2713
  function saveState$1() {
2670
2714
  if (currentSource) {
2671
- currentSource.src = Uint8Array.prototype.slice.call(currentSource.src, currentSource.position, currentSource.srcEnd);
2715
+ currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
2672
2716
  currentSource.position = 0;
2673
- currentSource.srcEnd = currentSource.src.length;
2717
+ currentSource.bytesEnd = currentSource.bytes.length;
2674
2718
  }
2675
2719
  }
2676
2720
  function prepareStructures$1(structures, packr) {
@@ -3037,6 +3081,17 @@
3037
3081
  assert.deepEqual(data, deserialized);
3038
3082
  assert.equal(deserialized.extendedInstance.getDouble(), 8);
3039
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
+ });
3040
3095
 
3041
3096
  test.skip('text decoder', function() {
3042
3097
  let td = new TextDecoder('ISO-8859-15');