msgpackr 1.10.1 → 1.11.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 +3 -1
- package/dist/index-no-eval.cjs +61 -29
- 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 +61 -29
- 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 +61 -29
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +143 -30
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +12 -3
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +19 -9
- package/index.d.ts +19 -9
- package/index.js +1 -1
- package/pack.js +47 -32
- package/package.json +1 -1
- package/struct.js +2 -0
- package/unpack.js +12 -3
package/pack.js
CHANGED
|
@@ -53,7 +53,7 @@ export class Packr extends Unpackr {
|
|
|
53
53
|
if (!this.structures && options.useRecords != false)
|
|
54
54
|
this.structures = []
|
|
55
55
|
// two byte record ids for shared structures
|
|
56
|
-
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64)
|
|
56
|
+
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64)
|
|
57
57
|
let sharedLimitId = maxSharedStructures + 0x40
|
|
58
58
|
let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40
|
|
59
59
|
if (maxStructureId > 8256) {
|
|
@@ -71,7 +71,7 @@ export class Packr extends Unpackr {
|
|
|
71
71
|
}
|
|
72
72
|
safeEnd = target.length - 10
|
|
73
73
|
if (safeEnd - position < 0x800) {
|
|
74
|
-
// don't start too close to the end,
|
|
74
|
+
// don't start too close to the end,
|
|
75
75
|
target = new ByteArrayAllocate(target.length)
|
|
76
76
|
targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))
|
|
77
77
|
safeEnd = target.length - 10
|
|
@@ -189,10 +189,14 @@ export class Packr extends Unpackr {
|
|
|
189
189
|
return packr.pack(value, encodeOptions)
|
|
190
190
|
}
|
|
191
191
|
packr.lastNamedStructuresLength = sharedLength
|
|
192
|
+
// don't keep large buffers around
|
|
193
|
+
if (target.length > 0x40000000) target = null
|
|
192
194
|
return returnBuffer
|
|
193
195
|
}
|
|
194
196
|
}
|
|
195
197
|
}
|
|
198
|
+
// don't keep large buffers around, they take too much memory and cause problems (limit at 1GB)
|
|
199
|
+
if (target.length > 0x40000000) target = null
|
|
196
200
|
if (encodeOptions & RESET_BUFFER_MODE)
|
|
197
201
|
position = start
|
|
198
202
|
}
|
|
@@ -410,12 +414,12 @@ export class Packr extends Unpackr {
|
|
|
410
414
|
targetView.setUint32(position, referee.id)
|
|
411
415
|
position += 4
|
|
412
416
|
return
|
|
413
|
-
} else
|
|
417
|
+
} else
|
|
414
418
|
referenceMap.set(value, { offset: position - start })
|
|
415
419
|
}
|
|
416
420
|
let constructor = value.constructor
|
|
417
421
|
if (constructor === Object) {
|
|
418
|
-
writeObject(value
|
|
422
|
+
writeObject(value)
|
|
419
423
|
} else if (constructor === Array) {
|
|
420
424
|
packArray(value)
|
|
421
425
|
} else if (constructor === Map) {
|
|
@@ -438,7 +442,7 @@ export class Packr extends Unpackr {
|
|
|
438
442
|
pack(entryValue)
|
|
439
443
|
}
|
|
440
444
|
}
|
|
441
|
-
} else {
|
|
445
|
+
} else {
|
|
442
446
|
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
443
447
|
let extensionClass = extensionClasses[i]
|
|
444
448
|
if (value instanceof extensionClass) {
|
|
@@ -506,13 +510,13 @@ export class Packr extends Unpackr {
|
|
|
506
510
|
if (json !== value)
|
|
507
511
|
return pack(json)
|
|
508
512
|
}
|
|
509
|
-
|
|
513
|
+
|
|
510
514
|
// if there is a writeFunction, use it, otherwise just encode as undefined
|
|
511
515
|
if (type === 'function')
|
|
512
516
|
return pack(this.writeFunction && this.writeFunction(value));
|
|
513
|
-
|
|
514
|
-
// no extension found, write as object
|
|
515
|
-
writeObject(value
|
|
517
|
+
|
|
518
|
+
// no extension found, write as plain object
|
|
519
|
+
writeObject(value)
|
|
516
520
|
}
|
|
517
521
|
}
|
|
518
522
|
}
|
|
@@ -568,9 +572,19 @@ export class Packr extends Unpackr {
|
|
|
568
572
|
}
|
|
569
573
|
}
|
|
570
574
|
|
|
571
|
-
const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber) ? (object) => {
|
|
575
|
+
const writePlainObject = (this.variableMapSize || this.coercibleKeyAsNumber || this.skipValues) ? (object) => {
|
|
572
576
|
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
573
|
-
let keys
|
|
577
|
+
let keys;
|
|
578
|
+
if (this.skipValues) {
|
|
579
|
+
keys = [];
|
|
580
|
+
for (let key in object) {
|
|
581
|
+
if ((typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) &&
|
|
582
|
+
!this.skipValues.includes(object[key]))
|
|
583
|
+
keys.push(key);
|
|
584
|
+
}
|
|
585
|
+
} else {
|
|
586
|
+
keys = Object.keys(object)
|
|
587
|
+
}
|
|
574
588
|
let length = keys.length
|
|
575
589
|
if (length < 0x10) {
|
|
576
590
|
target[position++] = 0x80 | length
|
|
@@ -599,13 +613,13 @@ export class Packr extends Unpackr {
|
|
|
599
613
|
}
|
|
600
614
|
}
|
|
601
615
|
} :
|
|
602
|
-
(object
|
|
616
|
+
(object) => {
|
|
603
617
|
target[position++] = 0xde // always using map 16, so we can preallocate and set the length afterwards
|
|
604
618
|
let objectOffset = position - start
|
|
605
619
|
position += 2
|
|
606
620
|
let size = 0
|
|
607
621
|
for (let key in object) {
|
|
608
|
-
if (
|
|
622
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
609
623
|
pack(key)
|
|
610
624
|
pack(object[key])
|
|
611
625
|
size++
|
|
@@ -617,12 +631,12 @@ export class Packr extends Unpackr {
|
|
|
617
631
|
|
|
618
632
|
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
619
633
|
(options.progressiveRecords && !useTwoByteRecords) ? // this is about 2% faster for highly stable structures, since it only requires one for-in loop (but much more expensive when new structure needs to be written)
|
|
620
|
-
(object
|
|
634
|
+
(object) => {
|
|
621
635
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
622
636
|
let objectOffset = position++ - start
|
|
623
637
|
let wroteKeys
|
|
624
638
|
for (let key in object) {
|
|
625
|
-
if (
|
|
639
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
626
640
|
nextTransition = transition[key]
|
|
627
641
|
if (nextTransition)
|
|
628
642
|
transition = nextTransition
|
|
@@ -661,10 +675,10 @@ export class Packr extends Unpackr {
|
|
|
661
675
|
insertNewRecord(transition, Object.keys(object), objectOffset, 0)
|
|
662
676
|
}
|
|
663
677
|
} :
|
|
664
|
-
(object
|
|
678
|
+
(object) => {
|
|
665
679
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
666
680
|
let newTransitions = 0
|
|
667
|
-
for (let key in object) if (
|
|
681
|
+
for (let key in object) if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
668
682
|
nextTransition = transition[key]
|
|
669
683
|
if (!nextTransition) {
|
|
670
684
|
nextTransition = transition[key] = Object.create(null)
|
|
@@ -684,16 +698,16 @@ export class Packr extends Unpackr {
|
|
|
684
698
|
}
|
|
685
699
|
// now write the values
|
|
686
700
|
for (let key in object)
|
|
687
|
-
if (
|
|
701
|
+
if (typeof object.hasOwnProperty !== 'function' || object.hasOwnProperty(key)) {
|
|
688
702
|
pack(object[key])
|
|
689
703
|
}
|
|
690
704
|
}
|
|
691
705
|
|
|
692
|
-
//
|
|
706
|
+
// create reference to useRecords if useRecords is a function
|
|
693
707
|
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
694
|
-
|
|
695
|
-
const writeObject = checkUseRecords ? (object
|
|
696
|
-
checkUseRecords(object) ? writeRecord(object
|
|
708
|
+
|
|
709
|
+
const writeObject = checkUseRecords ? (object) => {
|
|
710
|
+
checkUseRecords(object) ? writeRecord(object) : writePlainObject(object)
|
|
697
711
|
} : writeRecord
|
|
698
712
|
|
|
699
713
|
const makeRoom = (end) => {
|
|
@@ -798,7 +812,7 @@ export class Packr extends Unpackr {
|
|
|
798
812
|
target[insertionOffset + start] = keysTarget[0]
|
|
799
813
|
}
|
|
800
814
|
}
|
|
801
|
-
const writeStruct = (object
|
|
815
|
+
const writeStruct = (object) => {
|
|
802
816
|
let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
|
|
803
817
|
if (notifySharedUpdate)
|
|
804
818
|
return hasSharedUpdate = true;
|
|
@@ -812,16 +826,22 @@ export class Packr extends Unpackr {
|
|
|
812
826
|
return position;
|
|
813
827
|
}, this);
|
|
814
828
|
if (newPosition === 0) // bail and go to a msgpack object
|
|
815
|
-
return writeObject(object
|
|
829
|
+
return writeObject(object);
|
|
816
830
|
position = newPosition;
|
|
817
831
|
}
|
|
818
832
|
}
|
|
819
833
|
useBuffer(buffer) {
|
|
820
834
|
// this means we are finished using our own buffer and we can write over it safely
|
|
821
835
|
target = buffer
|
|
822
|
-
|
|
836
|
+
target.dataView || (target.dataView = new DataView(target.buffer, target.byteOffset, target.byteLength))
|
|
823
837
|
position = 0
|
|
824
838
|
}
|
|
839
|
+
set position (value) {
|
|
840
|
+
position = value;
|
|
841
|
+
}
|
|
842
|
+
get position() {
|
|
843
|
+
return position;
|
|
844
|
+
}
|
|
825
845
|
clearSharedData() {
|
|
826
846
|
if (this.structures)
|
|
827
847
|
this.structures = []
|
|
@@ -830,12 +850,6 @@ export class Packr extends Unpackr {
|
|
|
830
850
|
}
|
|
831
851
|
}
|
|
832
852
|
|
|
833
|
-
function copyBinary(source, target, targetOffset, offset, endOffset) {
|
|
834
|
-
while (offset < endOffset) {
|
|
835
|
-
target[targetOffset++] = source[offset++]
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
|
|
839
853
|
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ]
|
|
840
854
|
extensions = [{
|
|
841
855
|
pack(date, allocateForWrite, pack) {
|
|
@@ -896,7 +910,7 @@ extensions = [{
|
|
|
896
910
|
target[position++] = 0x65 // 'e' for error
|
|
897
911
|
target[position++] = 0
|
|
898
912
|
}
|
|
899
|
-
pack([ error.name, error.message ])
|
|
913
|
+
pack([ error.name, error.message, error.cause ])
|
|
900
914
|
}
|
|
901
915
|
}, {
|
|
902
916
|
pack(regex, allocateForWrite, pack) {
|
|
@@ -949,6 +963,7 @@ function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
|
|
|
949
963
|
}
|
|
950
964
|
target[position++] = 0x74 // "t" for typed array
|
|
951
965
|
target[position++] = type
|
|
966
|
+
if (!typedArray.buffer) typedArray = new Uint8Array(typedArray)
|
|
952
967
|
target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position)
|
|
953
968
|
}
|
|
954
969
|
function writeBuffer(buffer, allocateForWrite) {
|
package/package.json
CHANGED
package/struct.js
CHANGED
|
@@ -504,6 +504,8 @@ function readStruct(src, position, srcEnd, unpackr) {
|
|
|
504
504
|
src = Uint8Array.prototype.slice.call(src, position, srcEnd);
|
|
505
505
|
srcEnd -= position;
|
|
506
506
|
position = 0;
|
|
507
|
+
if (!unpackr.getStructures)
|
|
508
|
+
throw new Error(`Reference to shared structure ${recordId} without getStructures method`);
|
|
507
509
|
unpackr._mergeStructures(unpackr.getStructures());
|
|
508
510
|
if (!unpackr.typedStructs)
|
|
509
511
|
throw new Error('Could not find any shared typed structures');
|
package/unpack.js
CHANGED
|
@@ -967,8 +967,10 @@ function readKey() {
|
|
|
967
967
|
}
|
|
968
968
|
|
|
969
969
|
function asSafeString(property) {
|
|
970
|
+
// protect against expensive (DoS) string conversions
|
|
970
971
|
if (typeof property === 'string') return property;
|
|
971
|
-
if (typeof property === 'number') return property.toString();
|
|
972
|
+
if (typeof property === 'number' || typeof property === 'boolean' || typeof property === 'bigint') return property.toString();
|
|
973
|
+
if (property == null) return property + '';
|
|
972
974
|
throw new Error('Invalid property type for record', typeof property);
|
|
973
975
|
}
|
|
974
976
|
// the registration of the record definition extension (as "r")
|
|
@@ -1008,7 +1010,7 @@ currentExtensions[0x42] = (data) => {
|
|
|
1008
1010
|
let errors = { Error, TypeError, ReferenceError };
|
|
1009
1011
|
currentExtensions[0x65] = () => {
|
|
1010
1012
|
let data = read()
|
|
1011
|
-
return (errors[data[0]] || Error)(data[1])
|
|
1013
|
+
return (errors[data[0]] || Error)(data[1], { cause: data[2] })
|
|
1012
1014
|
}
|
|
1013
1015
|
|
|
1014
1016
|
currentExtensions[0x69] = (data) => {
|
|
@@ -1052,8 +1054,15 @@ let glbl = typeof globalThis === 'object' ? globalThis : window;
|
|
|
1052
1054
|
currentExtensions[0x74] = (data) => {
|
|
1053
1055
|
let typeCode = data[0]
|
|
1054
1056
|
let typedArrayName = typedArrays[typeCode]
|
|
1055
|
-
if (!typedArrayName)
|
|
1057
|
+
if (!typedArrayName) {
|
|
1058
|
+
if (typeCode === 16) {
|
|
1059
|
+
let ab = new ArrayBuffer(data.length - 1)
|
|
1060
|
+
let u8 = new Uint8Array(ab)
|
|
1061
|
+
u8.set(data.subarray(1))
|
|
1062
|
+
return ab;
|
|
1063
|
+
}
|
|
1056
1064
|
throw new Error('Could not find typed array for code ' + typeCode)
|
|
1065
|
+
}
|
|
1057
1066
|
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
1058
1067
|
return new glbl[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
1059
1068
|
}
|