cbor-x 1.5.8 → 1.5.9

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
@@ -501,7 +501,8 @@
501
501
  function safeKey(key) {
502
502
  // protect against prototype pollution
503
503
  if (typeof key === 'string') return key === '__proto__' ? '__proto_' : key
504
- if (typeof key !== 'object') return key.toString()
504
+ if (typeof key === 'number' || typeof key === 'boolean' || typeof key === 'bigint') return key.toString();
505
+ if (key == null) return key + '';
505
506
  // protect against expensive (DoS) string conversions
506
507
  throw new Error('Invalid property name type ' + typeof key);
507
508
  }
@@ -918,6 +919,7 @@
918
919
  referenceMap.id = 0;
919
920
  }
920
921
  let id = referenceMap.id++;
922
+ let startingPosition = position$1;
921
923
  let token = src[position$1];
922
924
  let target;
923
925
  // TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
@@ -930,8 +932,20 @@
930
932
  let refEntry = { target }; // a placeholder object
931
933
  referenceMap.set(id, refEntry);
932
934
  let targetProperties = read(); // read the next value as the target object to id
933
- if (refEntry.used) // there is a cycle, so we have to assign properties to original target
935
+ if (refEntry.used) {// there is a cycle, so we have to assign properties to original target
936
+ if (Object.getPrototypeOf(target) !== Object.getPrototypeOf(targetProperties)) {
937
+ // this means that the returned target does not match the targetProperties, so we need rerun the read to
938
+ // have the correctly create instance be assigned as a reference, then we do the copy the properties back to the
939
+ // target
940
+ // reset the position so that the read can be repeated
941
+ position$1 = startingPosition;
942
+ // the returned instance is our new target for references
943
+ target = targetProperties;
944
+ referenceMap.set(id, { target });
945
+ targetProperties = read();
946
+ }
934
947
  return Object.assign(target, targetProperties)
948
+ }
935
949
  refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
936
950
  return targetProperties // no cycle, can just use the returned read object
937
951
  };
@@ -1013,7 +1027,7 @@
1013
1027
  for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
1014
1028
  if (!littleEndian && bytesPerElement == 1)
1015
1029
  continue
1016
- let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : 3;
1030
+ let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : bytesPerElement == 8 ? 3 : 0;
1017
1031
  currentExtensions[littleEndian ? tag : (tag - 4)] = (bytesPerElement == 1 || littleEndian == isLittleEndianMachine$1) ? (buffer) => {
1018
1032
  if (!TypedArray)
1019
1033
  throw new Error('Could not find typed array for code ' + tag)
@@ -1023,7 +1037,7 @@
1023
1037
  bytesPerElement === 2 && !(buffer.byteOffset & 1) ||
1024
1038
  bytesPerElement === 4 && !(buffer.byteOffset & 3) ||
1025
1039
  bytesPerElement === 8 && !(buffer.byteOffset & 7))
1026
- return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1040
+ return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength >> sizeShift);
1027
1041
  }
1028
1042
  // we have to slice/copy here to get a new ArrayBuffer, if we are not word/byte aligned
1029
1043
  return new TypedArray(Uint8Array.prototype.slice.call(buffer, 0).buffer)
@@ -1622,7 +1636,7 @@
1622
1636
  }
1623
1637
  let constructor = value.constructor;
1624
1638
  if (constructor === Object) {
1625
- writeObject(value, true);
1639
+ writeObject(value);
1626
1640
  } else if (constructor === Array) {
1627
1641
  length = value.length;
1628
1642
  if (length < 0x18) {
@@ -1717,8 +1731,8 @@
1717
1731
  return encode(json)
1718
1732
  }
1719
1733
 
1720
- // no extension found, write as object
1721
- writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
1734
+ // no extension found, write as a plain object
1735
+ writeObject(value);
1722
1736
  }
1723
1737
  }
1724
1738
  } else if (type === 'boolean') {
@@ -1780,19 +1794,19 @@
1780
1794
  }
1781
1795
  }
1782
1796
  } :
1783
- (object, safePrototype) => {
1797
+ (object) => {
1784
1798
  target[position++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
1785
1799
  let objectOffset = position - start;
1786
1800
  position += 2;
1787
1801
  let size = 0;
1788
1802
  if (encoder.keyMap) {
1789
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1803
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1790
1804
  encode(encoder.encodeKey(key));
1791
1805
  encode(object[key]);
1792
1806
  size++;
1793
1807
  }
1794
1808
  } else {
1795
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1809
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1796
1810
  encode(key);
1797
1811
  encode(object[key]);
1798
1812
  size++;
@@ -1801,7 +1815,7 @@
1801
1815
  target[objectOffset++ + start] = size >> 8;
1802
1816
  target[objectOffset + start] = size & 0xff;
1803
1817
  } :
1804
- (object, safePrototype) => {
1818
+ (object, skipValues) => {
1805
1819
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
1806
1820
  let newTransitions = 0;
1807
1821
  let length = 0;
@@ -1820,7 +1834,7 @@
1820
1834
  transition = nextTransition;
1821
1835
  }
1822
1836
  } else {
1823
- for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
1837
+ for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
1824
1838
  nextTransition = transition[key];
1825
1839
  if (!nextTransition) {
1826
1840
  if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
@@ -1880,9 +1894,9 @@
1880
1894
  writeArrayHeader(length + 2);
1881
1895
  encode(0xe000 + recordId);
1882
1896
  encode(keys);
1883
- if (safePrototype === null) return; // special exit for iterator
1897
+ if (skipValues) return; // special exit for iterator
1884
1898
  for (let key in object)
1885
- if (safePrototype || object.hasOwnProperty(key))
1899
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
1886
1900
  encode(object[key]);
1887
1901
  return
1888
1902
  }
@@ -1892,9 +1906,9 @@
1892
1906
  } else {
1893
1907
  writeArrayHeader(length);
1894
1908
  }
1895
- if (safePrototype === null) return; // special exit for iterator
1909
+ if (skipValues) return; // special exit for iterator
1896
1910
  for (let key in object)
1897
- if (safePrototype || object.hasOwnProperty(key))
1911
+ if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
1898
1912
  encode(object[key]);
1899
1913
  };
1900
1914
  const makeRoom = (end) => {
@@ -1932,7 +1946,7 @@
1932
1946
  if (constructor === Object) {
1933
1947
  let useRecords = encoder.useRecords !== false;
1934
1948
  if (useRecords)
1935
- writeObject(object, null); // write the record identifier
1949
+ writeObject(object, true); // write the record identifier
1936
1950
  else
1937
1951
  writeEntityLength(Object.keys(object).length, 0xa0);
1938
1952
  for (let key in object) {
@@ -2649,22 +2663,17 @@
2649
2663
  assert.deepEqual(deserialized1, data1);
2650
2664
  assert.deepEqual(deserialized2, data2);
2651
2665
  });
2652
- test('extended class encode/decode', function(){
2666
+ test('extended class encode/decode', function() {
2653
2667
  function Extended() {
2654
2668
 
2655
2669
  }
2670
+
2656
2671
  Extended.prototype.getDouble = function() {
2657
2672
  return this.value * 2
2658
2673
  };
2659
2674
  var instance = new Extended();
2660
2675
  instance.value = 4;
2661
2676
  instance.string = 'decode this: ᾜ';
2662
- var data = {
2663
- prop1: 'has multi-byte: ᾜ',
2664
- extendedInstance: instance,
2665
- prop2: 'more string',
2666
- num: 3,
2667
- };
2668
2677
  let encoder = new Encoder();
2669
2678
  addExtension({
2670
2679
  Class: Extended,
@@ -2679,10 +2688,37 @@
2679
2688
  return encoder.encode([instance.value, instance.string])
2680
2689
  }
2681
2690
  });
2682
- var serialized = encode(data);
2683
- var deserialized = decode(serialized);
2684
- assert.deepEqual(data, deserialized);
2685
- assert.equal(deserialized.extendedInstance.getDouble(), 8);
2691
+ });
2692
+ test('extended class encode/decode with self reference in structered clone', function(){
2693
+ function Extended() {
2694
+
2695
+ }
2696
+ addExtension({
2697
+ Class: Extended,
2698
+ tag: 301,
2699
+ decode: function(data) {
2700
+ let e = new Extended();
2701
+ e.value = data[0];
2702
+ e.string = data[1];
2703
+ return e
2704
+ },
2705
+ encode: function(instance, encode) {
2706
+ return encode([instance.value, instance.string])
2707
+ }
2708
+ });
2709
+ var instance = new Extended();
2710
+ instance.value = instance;
2711
+ instance.string = 'hi';
2712
+ let data = {
2713
+ extended: instance
2714
+ };
2715
+ let encoder = new Encoder({
2716
+ structuredClone: true,
2717
+ });
2718
+ let serialized = encoder.encode(data);
2719
+ encoder.decode(serialized);
2720
+ assert(data.extended.value.value === data.extended);
2721
+ assert(data.extended instanceof Extended);
2686
2722
  });
2687
2723
 
2688
2724
  test('addExtension with map', function(){
@@ -2824,6 +2860,12 @@
2824
2860
  var deserialized = decode(serialized);
2825
2861
  assert.deepEqual(deserialized, data);
2826
2862
  });
2863
+ test('object with __proto__', function(){
2864
+ const data = { foo: 'bar', __proto__: { isAdmin: true } };
2865
+ var serialized = encode(data);
2866
+ var deserialized = decode(serialized);
2867
+ assert.deepEqual(deserialized, { foo: 'bar' });
2868
+ });
2827
2869
 
2828
2870
  test('big buffer', function() {
2829
2871
  var size = 100000000;
@@ -3092,6 +3134,11 @@
3092
3134
  let badInput = Buffer.from('7b2273657269616c6e6f223a2265343a30222c226970223a223139322e3136382e312e3335222c226b6579223a226770735f736563726574227d', 'hex');
3093
3135
  assert.throws(function(){ decode(badInput); }); // should throw, not crash
3094
3136
  });
3137
+ test('buffer key', function() {
3138
+ let encoder = new Encoder({ mapsAsObjects: false });
3139
+ let test = encoder.decode(Buffer.from('D87982A1446E616D654361626301', 'hex'));
3140
+ console.log(test);
3141
+ });
3095
3142
  test('encode as iterator', function() {
3096
3143
  let hasIterables = {
3097
3144
  a: 1,
@@ -3184,6 +3231,15 @@
3184
3231
  decode(Buffer.concat(result));
3185
3232
  console.log(performance.now() - start, result.length);
3186
3233
  });
3234
+
3235
+ test('little-endian typed array with aligned data', function() {
3236
+ // array[1] { uint32-little-endian-typed-array { bytes <00 00 00 00> } }
3237
+ let data = new Uint8Array([ 129, 216, 70, 68, 0, 0, 0, 0 ]);
3238
+ assert.deepEqual(decode(data), [new Uint32Array([0])]);
3239
+
3240
+ let value = {x: new Float32Array([1, 2, 3])};
3241
+ assert.deepEqual(decode(encode(value)), value);
3242
+ });
3187
3243
  });
3188
3244
  suite('CBOR performance tests', function(){
3189
3245
  test('performance JSON.parse', function() {