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/decode.js +18 -4
- package/dist/decode-no-eval.cjs +18 -4
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +31 -17
- package/dist/index-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.min.js +1 -1
- package/dist/index-no-eval.min.js.map +1 -1
- package/dist/index.js +31 -17
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/node.cjs +31 -17
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +84 -28
- package/dist/test.js.map +1 -1
- package/encode.js +13 -13
- package/package.json +9 -3
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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 (
|
|
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,
|
|
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 (
|
|
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 (
|
|
1897
|
+
if (skipValues) return; // special exit for iterator
|
|
1884
1898
|
for (let key in object)
|
|
1885
|
-
if (
|
|
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 (
|
|
1909
|
+
if (skipValues) return; // special exit for iterator
|
|
1896
1910
|
for (let key in object)
|
|
1897
|
-
if (
|
|
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,
|
|
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
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
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() {
|