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/README.md
CHANGED
|
@@ -157,10 +157,22 @@ unpackMultiple(data, (value) => {
|
|
|
157
157
|
})
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
If you need to know the start and end offsets of the unpacked values, these are
|
|
161
|
+
provided as optional parameters in the callback:
|
|
162
|
+
```js
|
|
163
|
+
let data = new Uint8Array([1, 2, 3]) // encodings of values 1, 2, and 3
|
|
164
|
+
unpackMultiple(data, (value,start,end) => {
|
|
165
|
+
// called for each value
|
|
166
|
+
// `start` is the data buffer offset where the value was read from
|
|
167
|
+
// `end` is `start` plus the byte length of the encoded value
|
|
168
|
+
// return false if you wish to end the parsing
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
160
172
|
## Options
|
|
161
173
|
The following options properties can be provided to the Packr or Unpackr constructor:
|
|
162
174
|
|
|
163
|
-
* `useRecords` - Setting this to `false` disables the record extension and stores JavaScript objects as MessagePack maps, and unpacks maps as JavaScript `Object`s, which ensures compatibilty with other decoders.
|
|
175
|
+
* `useRecords` - Setting this to `false` disables the record extension and stores JavaScript objects as MessagePack maps, and unpacks maps as JavaScript `Object`s, which ensures compatibilty with other decoders. Setting this to a function will use records for objects where `useRecords(object)` returns `true`.
|
|
164
176
|
* `structures` - Provides the array of structures that is to be used for record extension, if you want the structures saved and used again. This array will be modified in place with new record structures that are serialized (if less than 32 structures are in the array).
|
|
165
177
|
* `moreTypes` - Enable serialization of additional built-in types/classes including typed arrays, `Set`s, `Map`s, and `Error`s.
|
|
166
178
|
* `structuredClone` - This enables the structured cloning extensions that will encode object/cyclic references. `moreTypes` is enabled by default when this is enabled.
|
package/dist/index-no-eval.cjs
CHANGED
|
@@ -119,10 +119,10 @@
|
|
|
119
119
|
let size = source.length;
|
|
120
120
|
let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size);
|
|
121
121
|
if (forEach) {
|
|
122
|
-
if (forEach(value) === false) return;
|
|
122
|
+
if (forEach(value, lastPosition, position$1) === false) return;
|
|
123
123
|
while(position$1 < size) {
|
|
124
124
|
lastPosition = position$1;
|
|
125
|
-
if (forEach(checkedRead()) === false) {
|
|
125
|
+
if (forEach(checkedRead(), lastPosition, position$1) === false) {
|
|
126
126
|
return
|
|
127
127
|
}
|
|
128
128
|
}
|
|
@@ -194,6 +194,10 @@
|
|
|
194
194
|
position$1 = bundledStrings$1.postBundlePosition;
|
|
195
195
|
bundledStrings$1 = null;
|
|
196
196
|
}
|
|
197
|
+
if (sequentialMode)
|
|
198
|
+
// we only need to restore the structures if there was an error, but if we completed a read,
|
|
199
|
+
// we can clear this out and keep the structures we read
|
|
200
|
+
currentStructures.restoreStructures = null;
|
|
197
201
|
|
|
198
202
|
if (position$1 == srcEnd) {
|
|
199
203
|
// finished reading this source, cleanup references
|
|
@@ -916,7 +920,10 @@
|
|
|
916
920
|
structure.highByte = highByte;
|
|
917
921
|
}
|
|
918
922
|
let existingStructure = currentStructures[id];
|
|
919
|
-
|
|
923
|
+
// If it is a shared structure, we need to restore any changes after reading.
|
|
924
|
+
// Also in sequential mode, we may get incomplete reads and thus errors, and we need to restore
|
|
925
|
+
// to the state prior to an incomplete read in order to properly resume.
|
|
926
|
+
if (existingStructure && (existingStructure.isShared || sequentialMode)) {
|
|
920
927
|
(currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
|
|
921
928
|
}
|
|
922
929
|
currentStructures[id] = structure;
|
|
@@ -926,10 +933,10 @@
|
|
|
926
933
|
currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
927
934
|
currentExtensions[0].noBuffer = true;
|
|
928
935
|
|
|
929
|
-
let
|
|
936
|
+
let errors = { Error, TypeError, ReferenceError };
|
|
930
937
|
currentExtensions[0x65] = () => {
|
|
931
938
|
let data = read();
|
|
932
|
-
return (
|
|
939
|
+
return (errors[data[0]] || Error)(data[1])
|
|
933
940
|
};
|
|
934
941
|
|
|
935
942
|
currentExtensions[0x69] = (data) => {
|
|
@@ -967,6 +974,7 @@
|
|
|
967
974
|
|
|
968
975
|
const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array');
|
|
969
976
|
|
|
977
|
+
let glbl = typeof globalThis === 'object' ? globalThis : window;
|
|
970
978
|
currentExtensions[0x74] = (data) => {
|
|
971
979
|
let typeCode = data[0];
|
|
972
980
|
let typedArrayName = typedArrays[typeCode];
|
|
@@ -1253,7 +1261,7 @@
|
|
|
1253
1261
|
if (serializationsSinceTransitionRebuild < 10)
|
|
1254
1262
|
serializationsSinceTransitionRebuild++;
|
|
1255
1263
|
let sharedLength = structures.sharedLength || 0;
|
|
1256
|
-
if (structures.length > sharedLength)
|
|
1264
|
+
if (structures.length > sharedLength && !isSequential)
|
|
1257
1265
|
structures.length = sharedLength;
|
|
1258
1266
|
if (transitionsCount > 10000) {
|
|
1259
1267
|
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
@@ -1461,7 +1469,7 @@
|
|
|
1461
1469
|
targetView.setFloat64(position, value);
|
|
1462
1470
|
position += 8;
|
|
1463
1471
|
}
|
|
1464
|
-
} else if (type === 'object') {
|
|
1472
|
+
} else if (type === 'object' || type === 'function') {
|
|
1465
1473
|
if (!value)
|
|
1466
1474
|
target[position++] = 0xc0;
|
|
1467
1475
|
else {
|
|
@@ -1568,6 +1576,11 @@
|
|
|
1568
1576
|
} else {
|
|
1569
1577
|
if (value.toJSON) // use this as an alternate mechanism for expressing how to serialize
|
|
1570
1578
|
return pack(value.toJSON());
|
|
1579
|
+
|
|
1580
|
+
// if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1581
|
+
if (type === 'function')
|
|
1582
|
+
return pack(this.writeFunction && this.writeFunction(value));
|
|
1583
|
+
|
|
1571
1584
|
// no extension found, write as object
|
|
1572
1585
|
writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
|
|
1573
1586
|
}
|
|
@@ -1602,14 +1615,12 @@
|
|
|
1602
1615
|
target[position++] = 0;
|
|
1603
1616
|
target[position++] = 0;
|
|
1604
1617
|
}
|
|
1605
|
-
} else if (type === 'function') {
|
|
1606
|
-
pack(this.writeFunction && this.writeFunction()); // if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1607
1618
|
} else {
|
|
1608
1619
|
throw new Error('Unknown type: ' + type)
|
|
1609
1620
|
}
|
|
1610
1621
|
};
|
|
1611
1622
|
|
|
1612
|
-
const
|
|
1623
|
+
const writePlainObject = this.variableMapSize ? (object) => {
|
|
1613
1624
|
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1614
1625
|
let keys = Object.keys(object);
|
|
1615
1626
|
let length = keys.length;
|
|
@@ -1644,7 +1655,9 @@
|
|
|
1644
1655
|
}
|
|
1645
1656
|
target[objectOffset++ + start] = size >> 8;
|
|
1646
1657
|
target[objectOffset + start] = size & 0xff;
|
|
1647
|
-
}
|
|
1658
|
+
};
|
|
1659
|
+
|
|
1660
|
+
const writeRecord = this.useRecords === false ? writePlainObject :
|
|
1648
1661
|
(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)
|
|
1649
1662
|
(object, safePrototype) => {
|
|
1650
1663
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
@@ -1716,6 +1729,14 @@
|
|
|
1716
1729
|
if (safePrototype || object.hasOwnProperty(key))
|
|
1717
1730
|
pack(object[key]);
|
|
1718
1731
|
};
|
|
1732
|
+
|
|
1733
|
+
// craete reference to useRecords if useRecords is a function
|
|
1734
|
+
const checkUseRecords = typeof this.useRecords == 'function' && this.useRecords;
|
|
1735
|
+
|
|
1736
|
+
const writeObject = checkUseRecords ? (object, safePrototype) => {
|
|
1737
|
+
checkUseRecords(object) ? writeRecord(object,safePrototype) : writePlainObject(object,safePrototype);
|
|
1738
|
+
} : writeRecord;
|
|
1739
|
+
|
|
1719
1740
|
const makeRoom = (end) => {
|
|
1720
1741
|
let newSize;
|
|
1721
1742
|
if (end > 0x1000000) {
|
|
@@ -1888,7 +1909,10 @@
|
|
|
1888
1909
|
}
|
|
1889
1910
|
}, {
|
|
1890
1911
|
pack(set, allocateForWrite, pack) {
|
|
1891
|
-
if (this.setAsEmptyObject)
|
|
1912
|
+
if (this.setAsEmptyObject) {
|
|
1913
|
+
allocateForWrite(0);
|
|
1914
|
+
return pack({})
|
|
1915
|
+
}
|
|
1892
1916
|
let array = Array.from(set);
|
|
1893
1917
|
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1894
1918
|
if (this.moreTypes) {
|