msgpackr 1.9.1 → 1.9.3
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 +13 -1
- package/dist/index-no-eval.cjs +36 -12
- 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 +36 -12
- 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 +36 -12
- package/dist/node.cjs.map +1 -1
- package/dist/test.js +134 -14
- package/dist/test.js.map +1 -1
- package/dist/unpack-no-eval.cjs +13 -5
- package/dist/unpack-no-eval.cjs.map +1 -1
- package/index.d.cts +5 -5
- package/index.d.ts +5 -5
- package/pack.d.cts +1 -0
- package/pack.js +23 -7
- package/package.json +14 -6
- package/unpack.d.cts +2 -0
- package/unpack.js +13 -5
package/dist/test.js
CHANGED
|
@@ -120,10 +120,10 @@
|
|
|
120
120
|
let size = source.length;
|
|
121
121
|
let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size);
|
|
122
122
|
if (forEach) {
|
|
123
|
-
if (forEach(value) === false) return;
|
|
123
|
+
if (forEach(value, lastPosition, position$1) === false) return;
|
|
124
124
|
while(position$1 < size) {
|
|
125
125
|
lastPosition = position$1;
|
|
126
|
-
if (forEach(checkedRead()) === false) {
|
|
126
|
+
if (forEach(checkedRead(), lastPosition, position$1) === false) {
|
|
127
127
|
return
|
|
128
128
|
}
|
|
129
129
|
}
|
|
@@ -197,6 +197,10 @@
|
|
|
197
197
|
position$1 = bundledStrings$1.postBundlePosition;
|
|
198
198
|
bundledStrings$1 = null;
|
|
199
199
|
}
|
|
200
|
+
if (sequentialMode)
|
|
201
|
+
// we only need to restore the structures if there was an error, but if we completed a read,
|
|
202
|
+
// we can clear this out and keep the structures we read
|
|
203
|
+
currentStructures.restoreStructures = null;
|
|
200
204
|
|
|
201
205
|
if (position$1 == srcEnd) {
|
|
202
206
|
// finished reading this source, cleanup references
|
|
@@ -967,7 +971,10 @@
|
|
|
967
971
|
structure.highByte = highByte;
|
|
968
972
|
}
|
|
969
973
|
let existingStructure = currentStructures[id];
|
|
970
|
-
|
|
974
|
+
// If it is a shared structure, we need to restore any changes after reading.
|
|
975
|
+
// Also in sequential mode, we may get incomplete reads and thus errors, and we need to restore
|
|
976
|
+
// to the state prior to an incomplete read in order to properly resume.
|
|
977
|
+
if (existingStructure && (existingStructure.isShared || sequentialMode)) {
|
|
971
978
|
(currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
|
|
972
979
|
}
|
|
973
980
|
currentStructures[id] = structure;
|
|
@@ -977,10 +984,10 @@
|
|
|
977
984
|
currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
978
985
|
currentExtensions[0].noBuffer = true;
|
|
979
986
|
|
|
980
|
-
let
|
|
987
|
+
let errors = { Error, TypeError, ReferenceError };
|
|
981
988
|
currentExtensions[0x65] = () => {
|
|
982
989
|
let data = read();
|
|
983
|
-
return (
|
|
990
|
+
return (errors[data[0]] || Error)(data[1])
|
|
984
991
|
};
|
|
985
992
|
|
|
986
993
|
currentExtensions[0x69] = (data) => {
|
|
@@ -1018,6 +1025,7 @@
|
|
|
1018
1025
|
|
|
1019
1026
|
const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array');
|
|
1020
1027
|
|
|
1028
|
+
let glbl = typeof globalThis === 'object' ? globalThis : window;
|
|
1021
1029
|
currentExtensions[0x74] = (data) => {
|
|
1022
1030
|
let typeCode = data[0];
|
|
1023
1031
|
let typedArrayName = typedArrays[typeCode];
|
|
@@ -1314,7 +1322,7 @@
|
|
|
1314
1322
|
if (serializationsSinceTransitionRebuild < 10)
|
|
1315
1323
|
serializationsSinceTransitionRebuild++;
|
|
1316
1324
|
let sharedLength = structures.sharedLength || 0;
|
|
1317
|
-
if (structures.length > sharedLength)
|
|
1325
|
+
if (structures.length > sharedLength && !isSequential)
|
|
1318
1326
|
structures.length = sharedLength;
|
|
1319
1327
|
if (transitionsCount > 10000) {
|
|
1320
1328
|
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
@@ -1522,7 +1530,7 @@
|
|
|
1522
1530
|
targetView.setFloat64(position, value);
|
|
1523
1531
|
position += 8;
|
|
1524
1532
|
}
|
|
1525
|
-
} else if (type === 'object') {
|
|
1533
|
+
} else if (type === 'object' || type === 'function') {
|
|
1526
1534
|
if (!value)
|
|
1527
1535
|
target[position++] = 0xc0;
|
|
1528
1536
|
else {
|
|
@@ -1629,6 +1637,11 @@
|
|
|
1629
1637
|
} else {
|
|
1630
1638
|
if (value.toJSON) // use this as an alternate mechanism for expressing how to serialize
|
|
1631
1639
|
return pack(value.toJSON());
|
|
1640
|
+
|
|
1641
|
+
// if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1642
|
+
if (type === 'function')
|
|
1643
|
+
return pack(this.writeFunction && this.writeFunction(value));
|
|
1644
|
+
|
|
1632
1645
|
// no extension found, write as object
|
|
1633
1646
|
writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
|
|
1634
1647
|
}
|
|
@@ -1663,14 +1676,12 @@
|
|
|
1663
1676
|
target[position++] = 0;
|
|
1664
1677
|
target[position++] = 0;
|
|
1665
1678
|
}
|
|
1666
|
-
} else if (type === 'function') {
|
|
1667
|
-
pack(this.writeFunction && this.writeFunction()); // if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1668
1679
|
} else {
|
|
1669
1680
|
throw new Error('Unknown type: ' + type)
|
|
1670
1681
|
}
|
|
1671
1682
|
};
|
|
1672
1683
|
|
|
1673
|
-
const
|
|
1684
|
+
const writePlainObject = this.variableMapSize ? (object) => {
|
|
1674
1685
|
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1675
1686
|
let keys = Object.keys(object);
|
|
1676
1687
|
let length = keys.length;
|
|
@@ -1705,7 +1716,9 @@
|
|
|
1705
1716
|
}
|
|
1706
1717
|
target[objectOffset++ + start] = size >> 8;
|
|
1707
1718
|
target[objectOffset + start] = size & 0xff;
|
|
1708
|
-
}
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
1709
1722
|
(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)
|
|
1710
1723
|
(object, safePrototype) => {
|
|
1711
1724
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
@@ -1777,6 +1790,14 @@
|
|
|
1777
1790
|
if (safePrototype || object.hasOwnProperty(key))
|
|
1778
1791
|
pack(object[key]);
|
|
1779
1792
|
};
|
|
1793
|
+
|
|
1794
|
+
// craete reference to useRecords if useRecords is a function
|
|
1795
|
+
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
1796
|
+
|
|
1797
|
+
const writeObject = checkUseRecords ? (object, safePrototype) => {
|
|
1798
|
+
checkUseRecords(object) ? writeRecord(object,safePrototype) : writePlainObject(object,safePrototype);
|
|
1799
|
+
} : writeRecord;
|
|
1800
|
+
|
|
1780
1801
|
const makeRoom = (end) => {
|
|
1781
1802
|
let newSize;
|
|
1782
1803
|
if (end > 0x1000000) {
|
|
@@ -1949,7 +1970,10 @@
|
|
|
1949
1970
|
}
|
|
1950
1971
|
}, {
|
|
1951
1972
|
pack(set, allocateForWrite, pack) {
|
|
1952
|
-
if (this.setAsEmptyObject)
|
|
1973
|
+
if (this.setAsEmptyObject) {
|
|
1974
|
+
allocateForWrite(0);
|
|
1975
|
+
return pack({})
|
|
1976
|
+
}
|
|
1953
1977
|
let array = Array.from(set);
|
|
1954
1978
|
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1955
1979
|
if (this.moreTypes) {
|
|
@@ -3053,7 +3077,6 @@
|
|
|
3053
3077
|
var deserialized = packr.unpack(serialized);
|
|
3054
3078
|
assert.deepEqual(deserialized, data);
|
|
3055
3079
|
});
|
|
3056
|
-
|
|
3057
3080
|
test('255 chars', function () {
|
|
3058
3081
|
const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W';
|
|
3059
3082
|
var serialized = pack(data);
|
|
@@ -3152,6 +3175,44 @@
|
|
|
3152
3175
|
});
|
|
3153
3176
|
}
|
|
3154
3177
|
|
|
3178
|
+
test('pack/unpack sample data with useRecords function', function () {
|
|
3179
|
+
var data = [
|
|
3180
|
+
{id: 1, type: 1, labels: {a: 1, b: 2}},
|
|
3181
|
+
{id: 2, type: 1, labels: {b: 1, c: 2}},
|
|
3182
|
+
{id: 3, type: 1, labels: {d: 1, e: 2}}
|
|
3183
|
+
];
|
|
3184
|
+
|
|
3185
|
+
var alternatives = [
|
|
3186
|
+
{useRecords: false}, // 88 bytes
|
|
3187
|
+
{useRecords: true}, // 58 bytes
|
|
3188
|
+
{mapsAsObjects: true, useRecords: (v)=>!!v.id}, // 55 bytes
|
|
3189
|
+
{mapsAsObjects: true, variableMapSize: true, useRecords: (v)=>!!v.id} // 49 bytes
|
|
3190
|
+
];
|
|
3191
|
+
|
|
3192
|
+
for(let o of alternatives) {
|
|
3193
|
+
let packr = new Packr(o);
|
|
3194
|
+
var serialized = packr.pack(data);
|
|
3195
|
+
var deserialized = packr.unpack(serialized);
|
|
3196
|
+
assert.deepEqual(deserialized, data);
|
|
3197
|
+
}
|
|
3198
|
+
});
|
|
3199
|
+
|
|
3200
|
+
test('mapAsEmptyObject combination', function () {
|
|
3201
|
+
const msgpackr = new Packr({ useRecords: false, encodeUndefinedAsNil: true, variableMapSize: true, mapAsEmptyObject: true, setAsEmptyObject: true });
|
|
3202
|
+
|
|
3203
|
+
const map = new Map();
|
|
3204
|
+
map.set('a', 1);
|
|
3205
|
+
map.set('b', 2);
|
|
3206
|
+
const set = new Set();
|
|
3207
|
+
set.add('a');
|
|
3208
|
+
set.add('b');
|
|
3209
|
+
const input = { map, set };
|
|
3210
|
+
|
|
3211
|
+
const packed = msgpackr.pack(input);
|
|
3212
|
+
const unpacked = msgpackr.unpack(packed);
|
|
3213
|
+
assert.deepEqual(unpacked.map, {});
|
|
3214
|
+
assert.deepEqual(unpacked.set, {});
|
|
3215
|
+
});
|
|
3155
3216
|
test('pack/unpack empty data with bundled strings', function () {
|
|
3156
3217
|
var data = {};
|
|
3157
3218
|
let packr = new Packr({bundleStrings: true});
|
|
@@ -3312,7 +3373,6 @@
|
|
|
3312
3373
|
assert.deepEqual(data, deserialized);
|
|
3313
3374
|
});
|
|
3314
3375
|
|
|
3315
|
-
|
|
3316
3376
|
test('unregistered extended Array class read/write', function(){
|
|
3317
3377
|
var instance = new ExtendArray2();
|
|
3318
3378
|
instance.push(0);
|
|
@@ -3465,6 +3525,58 @@
|
|
|
3465
3525
|
assert.equal(deserialized.extendedInstance[0], 0);
|
|
3466
3526
|
});
|
|
3467
3527
|
|
|
3528
|
+
test('extended class pack/unpack proxied', function(){
|
|
3529
|
+
function Extended() {
|
|
3530
|
+
|
|
3531
|
+
}
|
|
3532
|
+
Extended.prototype.__call__ = function(){
|
|
3533
|
+
return this.value * 4
|
|
3534
|
+
};
|
|
3535
|
+
Extended.prototype.getDouble = function() {
|
|
3536
|
+
return this.value * 2
|
|
3537
|
+
};
|
|
3538
|
+
|
|
3539
|
+
var instance = function() { instance.__call__();/* callable stuff */ };
|
|
3540
|
+
Object.setPrototypeOf(instance,Extended.prototype);
|
|
3541
|
+
|
|
3542
|
+
instance.value = 4;
|
|
3543
|
+
var data = instance;
|
|
3544
|
+
|
|
3545
|
+
let packr = new Packr();
|
|
3546
|
+
addExtension({
|
|
3547
|
+
Class: Extended,
|
|
3548
|
+
type: 15,
|
|
3549
|
+
unpack: function(buffer) {
|
|
3550
|
+
var e = function() { e.__call__(); };
|
|
3551
|
+
Object.setPrototypeOf(e,Extended.prototype);
|
|
3552
|
+
e.value = packr.unpack(buffer);
|
|
3553
|
+
return e
|
|
3554
|
+
},
|
|
3555
|
+
pack: function(instance) {
|
|
3556
|
+
return packr.pack(instance.value)
|
|
3557
|
+
}
|
|
3558
|
+
});
|
|
3559
|
+
var serialized = pack(data);
|
|
3560
|
+
var deserialized = unpack(serialized);
|
|
3561
|
+
assert.equal(deserialized.getDouble(), 8);
|
|
3562
|
+
});
|
|
3563
|
+
|
|
3564
|
+
test.skip('convert Date to string', function(){
|
|
3565
|
+
var data = {
|
|
3566
|
+
aDate: new Date(),
|
|
3567
|
+
};
|
|
3568
|
+
new Packr();
|
|
3569
|
+
addExtension({
|
|
3570
|
+
Class: Date,
|
|
3571
|
+
write(date) {
|
|
3572
|
+
return date.toString()
|
|
3573
|
+
}
|
|
3574
|
+
});
|
|
3575
|
+
var serialized = pack(data);
|
|
3576
|
+
var deserialized = unpack(serialized);
|
|
3577
|
+
assert.equal(deserialized.aDate, data.aDate.toString());
|
|
3578
|
+
});
|
|
3579
|
+
|
|
3468
3580
|
test('proto handling', function() {
|
|
3469
3581
|
var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');
|
|
3470
3582
|
var decoded = unpack(pack(objectWithProto));
|
|
@@ -3961,6 +4073,14 @@
|
|
|
3961
4073
|
assert.deepEqual(values, [1, 2, 3, 4]);
|
|
3962
4074
|
});
|
|
3963
4075
|
|
|
4076
|
+
test('unpackMultiple with positions', () => {
|
|
4077
|
+
let values = unpackMultiple(new Uint8Array([1, 2, 3, 4]));
|
|
4078
|
+
assert.deepEqual(values, [1, 2, 3, 4]);
|
|
4079
|
+
values = [];
|
|
4080
|
+
unpackMultiple(new Uint8Array([1, 2, 3, 4]), (value,start,end) => values.push([value,start,end]));
|
|
4081
|
+
assert.deepEqual(values, [[1,0,1], [2,1,2], [3,2,3], [4,3,4]]);
|
|
4082
|
+
});
|
|
4083
|
+
|
|
3964
4084
|
});
|
|
3965
4085
|
suite('msgpackr performance tests', function(){
|
|
3966
4086
|
test('performance JSON.parse', function() {
|