cbor-x 1.5.8 → 1.6.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/README.md +12 -0
- package/decode.d.ts +1 -1
- package/decode.js +67 -9
- package/dist/decode-no-eval.cjs +65 -9
- package/dist/decode-no-eval.cjs.map +1 -1
- package/dist/index-no-eval.cjs +92 -25
- 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 +92 -25
- 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 +93 -25
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +149 -42
- package/dist/test.js.map +1 -1
- package/encode.js +28 -16
- package/index.d.ts +6 -1
- package/index.js +1 -1
- package/node-index.js +1 -1
- package/package.json +9 -3
package/dist/node.cjs
CHANGED
|
@@ -17,6 +17,10 @@ const RECORD_INLINE_ID = 0xdfff; // temporary first-come first-serve tag // prop
|
|
|
17
17
|
const BUNDLED_STRINGS_ID = 0xdff9;
|
|
18
18
|
const PACKED_REFERENCE_TAG_ID = 6;
|
|
19
19
|
const STOP_CODE = {};
|
|
20
|
+
let maxArraySize = 112810000; // This is the maximum array size in V8. We would potentially detect and set it higher
|
|
21
|
+
// for JSC, but this is pretty large and should be sufficient for most use cases
|
|
22
|
+
let maxMapSize = 16810000; // JavaScript has a fixed maximum map size of about 16710000, but JS itself enforces this,
|
|
23
|
+
// many keys in an object, so also probably a reasonable choice there.
|
|
20
24
|
let strings = EMPTY_ARRAY;
|
|
21
25
|
let stringPosition = 0;
|
|
22
26
|
let currentDecoder = {};
|
|
@@ -293,6 +297,7 @@ function read() {
|
|
|
293
297
|
let array = [];
|
|
294
298
|
let value, i = 0;
|
|
295
299
|
while ((value = read()) != STOP_CODE) {
|
|
300
|
+
if (i >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
296
301
|
array[i++] = value;
|
|
297
302
|
}
|
|
298
303
|
return majorType == 4 ? array : majorType == 3 ? array.join('') : Buffer.concat(array)
|
|
@@ -300,8 +305,19 @@ function read() {
|
|
|
300
305
|
let key;
|
|
301
306
|
if (currentDecoder.mapsAsObjects) {
|
|
302
307
|
let object = {};
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
let i = 0;
|
|
309
|
+
if (currentDecoder.keyMap) {
|
|
310
|
+
while((key = read()) != STOP_CODE) {
|
|
311
|
+
if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
|
|
312
|
+
object[safeKey(currentDecoder.decodeKey(key))] = read();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
while ((key = read()) != STOP_CODE) {
|
|
317
|
+
if (i++ >= maxMapSize) throw new Error(`Property count exceeds ${maxMapSize}`)
|
|
318
|
+
object[safeKey(key)] = read();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
305
321
|
return object
|
|
306
322
|
} else {
|
|
307
323
|
if (restoreMapsAsObject) {
|
|
@@ -309,8 +325,24 @@ function read() {
|
|
|
309
325
|
restoreMapsAsObject = false;
|
|
310
326
|
}
|
|
311
327
|
let map = new Map();
|
|
312
|
-
if (currentDecoder.keyMap)
|
|
313
|
-
|
|
328
|
+
if (currentDecoder.keyMap) {
|
|
329
|
+
let i = 0;
|
|
330
|
+
while((key = read()) != STOP_CODE) {
|
|
331
|
+
if (i++ >= maxMapSize) {
|
|
332
|
+
throw new Error(`Map size exceeds ${maxMapSize}`);
|
|
333
|
+
}
|
|
334
|
+
map.set(currentDecoder.decodeKey(key), read());
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
let i = 0;
|
|
339
|
+
while ((key = read()) != STOP_CODE) {
|
|
340
|
+
if (i++ >= maxMapSize) {
|
|
341
|
+
throw new Error(`Map size exceeds ${maxMapSize}`);
|
|
342
|
+
}
|
|
343
|
+
map.set(key, read());
|
|
344
|
+
}
|
|
345
|
+
}
|
|
314
346
|
return map
|
|
315
347
|
}
|
|
316
348
|
case 7:
|
|
@@ -341,12 +373,14 @@ function read() {
|
|
|
341
373
|
}
|
|
342
374
|
return readFixedString(token)
|
|
343
375
|
case 4: // array
|
|
376
|
+
if (token >= maxArraySize) throw new Error(`Array length exceeds ${maxArraySize}`)
|
|
344
377
|
let array = new Array(token);
|
|
345
378
|
//if (currentDecoder.keyMap) for (let i = 0; i < token; i++) array[i] = currentDecoder.decodeKey(read())
|
|
346
379
|
//else
|
|
347
380
|
for (let i = 0; i < token; i++) array[i] = read();
|
|
348
381
|
return array
|
|
349
382
|
case 5: // map
|
|
383
|
+
if (token >= maxMapSize) throw new Error(`Map size exceeds ${maxArraySize}`)
|
|
350
384
|
if (currentDecoder.mapsAsObjects) {
|
|
351
385
|
let object = {};
|
|
352
386
|
if (currentDecoder.keyMap) for (let i = 0; i < token; i++) object[safeKey(currentDecoder.decodeKey(read()))] = read();
|
|
@@ -448,6 +482,7 @@ function read() {
|
|
|
448
482
|
}
|
|
449
483
|
const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
|
|
450
484
|
function createStructureReader(structure) {
|
|
485
|
+
if (!structure) throw new Error('Structure is required in record definition');
|
|
451
486
|
function readObject() {
|
|
452
487
|
// get the array size from the header
|
|
453
488
|
let length = src[position$1++];
|
|
@@ -503,7 +538,8 @@ function createStructureReader(structure) {
|
|
|
503
538
|
function safeKey(key) {
|
|
504
539
|
// protect against prototype pollution
|
|
505
540
|
if (typeof key === 'string') return key === '__proto__' ? '__proto_' : key
|
|
506
|
-
if (typeof key
|
|
541
|
+
if (typeof key === 'number' || typeof key === 'boolean' || typeof key === 'bigint') return key.toString();
|
|
542
|
+
if (key == null) return key + '';
|
|
507
543
|
// protect against expensive (DoS) string conversions
|
|
508
544
|
throw new Error('Invalid property name type ' + typeof key);
|
|
509
545
|
}
|
|
@@ -808,7 +844,7 @@ currentExtensions[2] = (buffer) => {
|
|
|
808
844
|
// bigint extension
|
|
809
845
|
let value = BigInt(0);
|
|
810
846
|
for (let i = 0, l = buffer.byteLength; i < l; i++) {
|
|
811
|
-
value = BigInt(buffer[i]) + value << BigInt(8);
|
|
847
|
+
value = BigInt(buffer[i]) + (value << BigInt(8));
|
|
812
848
|
}
|
|
813
849
|
return value
|
|
814
850
|
};
|
|
@@ -923,6 +959,7 @@ currentExtensions[28] = (read) => {
|
|
|
923
959
|
referenceMap.id = 0;
|
|
924
960
|
}
|
|
925
961
|
let id = referenceMap.id++;
|
|
962
|
+
let startingPosition = position$1;
|
|
926
963
|
let token = src[position$1];
|
|
927
964
|
let target;
|
|
928
965
|
// TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
|
|
@@ -935,8 +972,20 @@ currentExtensions[28] = (read) => {
|
|
|
935
972
|
let refEntry = { target }; // a placeholder object
|
|
936
973
|
referenceMap.set(id, refEntry);
|
|
937
974
|
let targetProperties = read(); // read the next value as the target object to id
|
|
938
|
-
if (refEntry.used) // there is a cycle, so we have to assign properties to original target
|
|
975
|
+
if (refEntry.used) {// there is a cycle, so we have to assign properties to original target
|
|
976
|
+
if (Object.getPrototypeOf(target) !== Object.getPrototypeOf(targetProperties)) {
|
|
977
|
+
// this means that the returned target does not match the targetProperties, so we need rerun the read to
|
|
978
|
+
// have the correctly create instance be assigned as a reference, then we do the copy the properties back to the
|
|
979
|
+
// target
|
|
980
|
+
// reset the position so that the read can be repeated
|
|
981
|
+
position$1 = startingPosition;
|
|
982
|
+
// the returned instance is our new target for references
|
|
983
|
+
target = targetProperties;
|
|
984
|
+
referenceMap.set(id, { target });
|
|
985
|
+
targetProperties = read();
|
|
986
|
+
}
|
|
939
987
|
return Object.assign(target, targetProperties)
|
|
988
|
+
}
|
|
940
989
|
refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
|
|
941
990
|
return targetProperties // no cycle, can just use the returned read object
|
|
942
991
|
};
|
|
@@ -1018,7 +1067,7 @@ function registerTypedArray(TypedArray, tag) {
|
|
|
1018
1067
|
for (let littleEndian = 0; littleEndian < 2; littleEndian++) {
|
|
1019
1068
|
if (!littleEndian && bytesPerElement == 1)
|
|
1020
1069
|
continue
|
|
1021
|
-
let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : 3;
|
|
1070
|
+
let sizeShift = bytesPerElement == 2 ? 1 : bytesPerElement == 4 ? 2 : bytesPerElement == 8 ? 3 : 0;
|
|
1022
1071
|
currentExtensions[littleEndian ? tag : (tag - 4)] = (bytesPerElement == 1 || littleEndian == isLittleEndianMachine$1) ? (buffer) => {
|
|
1023
1072
|
if (!TypedArray)
|
|
1024
1073
|
throw new Error('Could not find typed array for code ' + tag)
|
|
@@ -1028,7 +1077,7 @@ function registerTypedArray(TypedArray, tag) {
|
|
|
1028
1077
|
bytesPerElement === 2 && !(buffer.byteOffset & 1) ||
|
|
1029
1078
|
bytesPerElement === 4 && !(buffer.byteOffset & 3) ||
|
|
1030
1079
|
bytesPerElement === 8 && !(buffer.byteOffset & 7))
|
|
1031
|
-
return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
1080
|
+
return new TypedArray(buffer.buffer, buffer.byteOffset, buffer.byteLength >> sizeShift);
|
|
1032
1081
|
}
|
|
1033
1082
|
// we have to slice/copy here to get a new ArrayBuffer, if we are not word/byte aligned
|
|
1034
1083
|
return new TypedArray(Uint8Array.prototype.slice.call(buffer, 0).buffer)
|
|
@@ -1145,6 +1194,12 @@ function addExtension$1(extension) {
|
|
|
1145
1194
|
currentExtensions[extension.tag] = extension.decode;
|
|
1146
1195
|
}
|
|
1147
1196
|
|
|
1197
|
+
function setSizeLimits(limits) {
|
|
1198
|
+
if (limits.maxMapSize) maxMapSize = limits.maxMapSize;
|
|
1199
|
+
if (limits.maxArraySize) maxArraySize = limits.maxArraySize;
|
|
1200
|
+
if (limits.maxObjectSize) limits.maxObjectSize;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1148
1203
|
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
1149
1204
|
for (let i = 0; i < 256; i++) {
|
|
1150
1205
|
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
|
@@ -1632,7 +1687,7 @@ class Encoder extends Decoder {
|
|
|
1632
1687
|
}
|
|
1633
1688
|
let constructor = value.constructor;
|
|
1634
1689
|
if (constructor === Object) {
|
|
1635
|
-
writeObject(value
|
|
1690
|
+
writeObject(value);
|
|
1636
1691
|
} else if (constructor === Array) {
|
|
1637
1692
|
length = value.length;
|
|
1638
1693
|
if (length < 0x18) {
|
|
@@ -1727,8 +1782,8 @@ class Encoder extends Decoder {
|
|
|
1727
1782
|
return encode(json)
|
|
1728
1783
|
}
|
|
1729
1784
|
|
|
1730
|
-
// no extension found, write as object
|
|
1731
|
-
writeObject(value
|
|
1785
|
+
// no extension found, write as a plain object
|
|
1786
|
+
writeObject(value);
|
|
1732
1787
|
}
|
|
1733
1788
|
}
|
|
1734
1789
|
} else if (type === 'boolean') {
|
|
@@ -1748,7 +1803,19 @@ class Encoder extends Decoder {
|
|
|
1748
1803
|
target[position++] = 0xfb;
|
|
1749
1804
|
targetView.setFloat64(position, Number(value));
|
|
1750
1805
|
} else {
|
|
1751
|
-
|
|
1806
|
+
if (value >= BigInt(0))
|
|
1807
|
+
target[position++] = 0xc2; // tag 2
|
|
1808
|
+
else {
|
|
1809
|
+
target[position++] = 0xc3; // tag 2
|
|
1810
|
+
value = BigInt(-1) - value;
|
|
1811
|
+
}
|
|
1812
|
+
let bytes = [];
|
|
1813
|
+
while (value) {
|
|
1814
|
+
bytes.push(Number(value & BigInt(0xff)));
|
|
1815
|
+
value >>= BigInt(8);
|
|
1816
|
+
}
|
|
1817
|
+
writeBuffer(new Uint8Array(bytes.reverse()), makeRoom);
|
|
1818
|
+
return;
|
|
1752
1819
|
}
|
|
1753
1820
|
}
|
|
1754
1821
|
position += 8;
|
|
@@ -1790,19 +1857,19 @@ class Encoder extends Decoder {
|
|
|
1790
1857
|
}
|
|
1791
1858
|
}
|
|
1792
1859
|
} :
|
|
1793
|
-
(object
|
|
1860
|
+
(object) => {
|
|
1794
1861
|
target[position++] = 0xb9; // always use map 16, so we can preallocate and set the length afterwards
|
|
1795
1862
|
let objectOffset = position - start;
|
|
1796
1863
|
position += 2;
|
|
1797
1864
|
let size = 0;
|
|
1798
|
-
if (encoder.keyMap) {
|
|
1799
|
-
for (let key in object) if (
|
|
1865
|
+
if (encoder.keyMap) {
|
|
1866
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1800
1867
|
encode(encoder.encodeKey(key));
|
|
1801
1868
|
encode(object[key]);
|
|
1802
1869
|
size++;
|
|
1803
1870
|
}
|
|
1804
1871
|
} else {
|
|
1805
|
-
for (let key in object) if (
|
|
1872
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1806
1873
|
encode(key);
|
|
1807
1874
|
encode(object[key]);
|
|
1808
1875
|
size++;
|
|
@@ -1811,7 +1878,7 @@ class Encoder extends Decoder {
|
|
|
1811
1878
|
target[objectOffset++ + start] = size >> 8;
|
|
1812
1879
|
target[objectOffset + start] = size & 0xff;
|
|
1813
1880
|
} :
|
|
1814
|
-
(object,
|
|
1881
|
+
(object, skipValues) => {
|
|
1815
1882
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1816
1883
|
let newTransitions = 0;
|
|
1817
1884
|
let length = 0;
|
|
@@ -1830,7 +1897,7 @@ class Encoder extends Decoder {
|
|
|
1830
1897
|
transition = nextTransition;
|
|
1831
1898
|
}
|
|
1832
1899
|
} else {
|
|
1833
|
-
for (let key in object) if (
|
|
1900
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
1834
1901
|
nextTransition = transition[key];
|
|
1835
1902
|
if (!nextTransition) {
|
|
1836
1903
|
if (transition[RECORD_SYMBOL] & 0x100000) {// this indicates it is a brancheable/extendable terminal node, so we will use this record id and extend it
|
|
@@ -1890,9 +1957,9 @@ class Encoder extends Decoder {
|
|
|
1890
1957
|
writeArrayHeader(length + 2);
|
|
1891
1958
|
encode(0xe000 + recordId);
|
|
1892
1959
|
encode(keys);
|
|
1893
|
-
if (
|
|
1960
|
+
if (skipValues) return; // special exit for iterator
|
|
1894
1961
|
for (let key in object)
|
|
1895
|
-
if (
|
|
1962
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
1896
1963
|
encode(object[key]);
|
|
1897
1964
|
return
|
|
1898
1965
|
}
|
|
@@ -1902,9 +1969,9 @@ class Encoder extends Decoder {
|
|
|
1902
1969
|
} else {
|
|
1903
1970
|
writeArrayHeader(length);
|
|
1904
1971
|
}
|
|
1905
|
-
if (
|
|
1972
|
+
if (skipValues) return; // special exit for iterator
|
|
1906
1973
|
for (let key in object)
|
|
1907
|
-
if (
|
|
1974
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key))
|
|
1908
1975
|
encode(object[key]);
|
|
1909
1976
|
};
|
|
1910
1977
|
const makeRoom = (end) => {
|
|
@@ -1942,7 +2009,7 @@ class Encoder extends Decoder {
|
|
|
1942
2009
|
if (constructor === Object) {
|
|
1943
2010
|
let useRecords = encoder.useRecords !== false;
|
|
1944
2011
|
if (useRecords)
|
|
1945
|
-
writeObject(object,
|
|
2012
|
+
writeObject(object, true); // write the record identifier
|
|
1946
2013
|
else
|
|
1947
2014
|
writeEntityLength(Object.keys(object).length, 0xa0);
|
|
1948
2015
|
for (let key in object) {
|
|
@@ -1967,7 +2034,7 @@ class Encoder extends Decoder {
|
|
|
1967
2034
|
yield* tryEncode(value, iterateProperties, 'element');
|
|
1968
2035
|
} else encode(value);
|
|
1969
2036
|
}
|
|
1970
|
-
} else if (object[Symbol.iterator]) {
|
|
2037
|
+
} else if (object[Symbol.iterator] && !object.buffer) { // iterator, but exclude typed arrays
|
|
1971
2038
|
target[position++] = 0x9f; // start indefinite array
|
|
1972
2039
|
for (let value of object) {
|
|
1973
2040
|
if (value && (typeof value === 'object' || position - start > chunkThreshold)) {
|
|
@@ -2557,5 +2624,6 @@ exports.encodeAsIterable = encodeAsIterable;
|
|
|
2557
2624
|
exports.encodeIter = encodeIter;
|
|
2558
2625
|
exports.mapsAsObjects = mapsAsObjects;
|
|
2559
2626
|
exports.roundFloat32 = roundFloat32;
|
|
2627
|
+
exports.setSizeLimits = setSizeLimits;
|
|
2560
2628
|
exports.useRecords = useRecords;
|
|
2561
2629
|
//# sourceMappingURL=node.cjs.map
|