msgpackr 1.4.7 → 1.5.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 +16 -2
- package/dist/index.js +278 -100
- package/dist/index.min.js +68 -99
- package/dist/node.cjs +281 -103
- package/dist/str.cjs +100 -0
- package/dist/test.js +44 -3
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/node-index.js +2 -4
- package/pack.js +191 -85
- package/package.json +7 -1
- package/unpack.d.ts +3 -0
- package/unpack.js +84 -11
- package/.vscode/launch.json +0 -23
- package/tests/benchmark-stream.cjs +0 -282
- package/tests/benchmark.cjs +0 -199
- package/tests/example.json +0 -52
- package/tests/example2.json +0 -26
- package/tests/example3.json +0 -22
- package/tests/example4.json +0 -1
- package/tests/example5.json +0 -12
- package/tests/floats.json +0 -1
- package/tests/index.html +0 -28
- package/tests/sample-large.json +0 -231
- package/tests/strings2.json +0 -1
- package/tests/test-compatibility.cjs +0 -64
- package/tests/test-incomplete.js +0 -41
- package/tests/test-node-iterators.js +0 -72
- package/tests/test-node-stream.js +0 -76
- package/tests/test.js +0 -640
package/dist/node.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var currentStructures;
|
|
|
20
20
|
var srcString;
|
|
21
21
|
var srcStringStart = 0;
|
|
22
22
|
var srcStringEnd = 0;
|
|
23
|
+
var bundledStrings;
|
|
23
24
|
var referenceMap;
|
|
24
25
|
var currentExtensions = [];
|
|
25
26
|
var dataView;
|
|
@@ -60,12 +61,21 @@ class Unpackr {
|
|
|
60
61
|
srcStringEnd = 0;
|
|
61
62
|
srcString = null;
|
|
62
63
|
strings = EMPTY_ARRAY;
|
|
64
|
+
bundledStrings = null;
|
|
63
65
|
src = source;
|
|
64
66
|
// this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
|
|
65
67
|
// technique for getting data from a database where it can be copied into an existing buffer instead of creating
|
|
66
68
|
// new ones
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
try {
|
|
70
|
+
dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
|
|
71
|
+
} catch(error) {
|
|
72
|
+
// if it doesn't have a buffer, maybe it is the wrong type of object
|
|
73
|
+
src = null;
|
|
74
|
+
if (source instanceof Uint8Array)
|
|
75
|
+
throw error
|
|
76
|
+
throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
|
|
77
|
+
}
|
|
78
|
+
if (this instanceof Unpackr) {
|
|
69
79
|
currentUnpackr = this;
|
|
70
80
|
if (this.structures) {
|
|
71
81
|
currentStructures = this.structures;
|
|
@@ -148,6 +158,9 @@ function checkedRead() {
|
|
|
148
158
|
currentStructures.length = sharedLength;
|
|
149
159
|
}
|
|
150
160
|
let result = read();
|
|
161
|
+
if (bundledStrings) // bundled strings to skip past
|
|
162
|
+
position = bundledStrings.postBundlePosition;
|
|
163
|
+
|
|
151
164
|
if (position == srcEnd) {
|
|
152
165
|
// finished reading this source, cleanup references
|
|
153
166
|
if (currentStructures.restoreStructures)
|
|
@@ -242,7 +255,15 @@ function read() {
|
|
|
242
255
|
let value;
|
|
243
256
|
switch (token) {
|
|
244
257
|
case 0xc0: return null
|
|
245
|
-
case 0xc1:
|
|
258
|
+
case 0xc1:
|
|
259
|
+
if (bundledStrings) {
|
|
260
|
+
value = read(); // followed by the length of the string in characters (not bytes!)
|
|
261
|
+
if (value > 0)
|
|
262
|
+
return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
|
|
263
|
+
else
|
|
264
|
+
return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value)
|
|
265
|
+
}
|
|
266
|
+
return C1; // "never-used", return special object to denote that
|
|
246
267
|
case 0xc2: return false
|
|
247
268
|
case 0xc3: return true
|
|
248
269
|
case 0xc4:
|
|
@@ -297,10 +318,11 @@ function read() {
|
|
|
297
318
|
position += 4;
|
|
298
319
|
return value
|
|
299
320
|
case 0xcf:
|
|
300
|
-
if (currentUnpackr.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
321
|
+
if (currentUnpackr.int64AsNumber) {
|
|
322
|
+
value = dataView.getUint32(position) * 0x100000000;
|
|
323
|
+
value += dataView.getUint32(position + 4);
|
|
324
|
+
} else
|
|
325
|
+
value = dataView.getBigUint64(position);
|
|
304
326
|
position += 8;
|
|
305
327
|
return value
|
|
306
328
|
|
|
@@ -316,7 +338,11 @@ function read() {
|
|
|
316
338
|
position += 4;
|
|
317
339
|
return value
|
|
318
340
|
case 0xd3:
|
|
319
|
-
|
|
341
|
+
if (currentUnpackr.int64AsNumber) {
|
|
342
|
+
value = dataView.getInt32(position) * 0x100000000;
|
|
343
|
+
value += dataView.getUint32(position + 4);
|
|
344
|
+
} else
|
|
345
|
+
value = dataView.getBigInt64(position);
|
|
320
346
|
position += 8;
|
|
321
347
|
return value
|
|
322
348
|
|
|
@@ -465,8 +491,10 @@ var readFixedString = readStringJS;
|
|
|
465
491
|
var readString8 = readStringJS;
|
|
466
492
|
var readString16 = readStringJS;
|
|
467
493
|
var readString32 = readStringJS;
|
|
494
|
+
exports.isNativeAccelerationEnabled = false;
|
|
468
495
|
|
|
469
496
|
function setExtractor(extractStrings) {
|
|
497
|
+
exports.isNativeAccelerationEnabled = true;
|
|
470
498
|
readFixedString = readString(1);
|
|
471
499
|
readString8 = readString(2);
|
|
472
500
|
readString16 = readString(3);
|
|
@@ -475,6 +503,8 @@ function setExtractor(extractStrings) {
|
|
|
475
503
|
return function readString(length) {
|
|
476
504
|
let string = strings[stringPosition++];
|
|
477
505
|
if (string == null) {
|
|
506
|
+
if (bundledStrings)
|
|
507
|
+
return readStringJS(length)
|
|
478
508
|
let extraction = extractStrings(position - headerLength, srcEnd, src);
|
|
479
509
|
if (typeof extraction == 'string') {
|
|
480
510
|
string = extraction;
|
|
@@ -733,6 +763,36 @@ function shortStringInJS(length) {
|
|
|
733
763
|
}
|
|
734
764
|
}
|
|
735
765
|
|
|
766
|
+
function readOnlyJSString() {
|
|
767
|
+
let token = src[position++];
|
|
768
|
+
let length;
|
|
769
|
+
if (token < 0xc0) {
|
|
770
|
+
// fixstr
|
|
771
|
+
length = token - 0xa0;
|
|
772
|
+
} else {
|
|
773
|
+
switch(token) {
|
|
774
|
+
case 0xd9:
|
|
775
|
+
// str 8
|
|
776
|
+
length = src[position++];
|
|
777
|
+
break
|
|
778
|
+
case 0xda:
|
|
779
|
+
// str 16
|
|
780
|
+
length = dataView.getUint16(position);
|
|
781
|
+
position += 2;
|
|
782
|
+
break
|
|
783
|
+
case 0xdb:
|
|
784
|
+
// str 32
|
|
785
|
+
length = dataView.getUint32(position);
|
|
786
|
+
position += 4;
|
|
787
|
+
break
|
|
788
|
+
default:
|
|
789
|
+
throw new Error('Expected string')
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return readStringJS(length)
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
|
|
736
796
|
function readBin(length) {
|
|
737
797
|
return currentUnpackr.copyBuffers ?
|
|
738
798
|
// specifically use the copying slice (not the node one)
|
|
@@ -884,6 +944,19 @@ currentExtensions[0x78] = () => {
|
|
|
884
944
|
let data = read();
|
|
885
945
|
return new RegExp(data[0], data[1])
|
|
886
946
|
};
|
|
947
|
+
const TEMP_BUNDLE = [];
|
|
948
|
+
currentExtensions[0x62] = (data) => {
|
|
949
|
+
let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
|
|
950
|
+
let dataPosition = position;
|
|
951
|
+
position += dataSize - data.length;
|
|
952
|
+
bundledStrings = TEMP_BUNDLE;
|
|
953
|
+
bundledStrings = [readOnlyJSString(), readOnlyJSString()];
|
|
954
|
+
bundledStrings.position0 = 0;
|
|
955
|
+
bundledStrings.position1 = 0;
|
|
956
|
+
bundledStrings.postBundlePosition = position;
|
|
957
|
+
position = dataPosition;
|
|
958
|
+
return read()
|
|
959
|
+
};
|
|
887
960
|
|
|
888
961
|
currentExtensions[0xff] = (data) => {
|
|
889
962
|
// 32-bit date extension
|
|
@@ -898,7 +971,7 @@ currentExtensions[0xff] = (data) => {
|
|
|
898
971
|
((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
|
|
899
972
|
(((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
|
|
900
973
|
else
|
|
901
|
-
|
|
974
|
+
return new Date('invalid')
|
|
902
975
|
}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
903
976
|
// registration of bulk record definition?
|
|
904
977
|
// currentExtensions[0x52] = () =>
|
|
@@ -912,6 +985,7 @@ function saveState(callback) {
|
|
|
912
985
|
let savedSrcString = srcString;
|
|
913
986
|
let savedStrings = strings;
|
|
914
987
|
let savedReferenceMap = referenceMap;
|
|
988
|
+
let savedBundledStrings = bundledStrings;
|
|
915
989
|
|
|
916
990
|
// TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
|
|
917
991
|
let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed
|
|
@@ -928,6 +1002,7 @@ function saveState(callback) {
|
|
|
928
1002
|
srcString = savedSrcString;
|
|
929
1003
|
strings = savedStrings;
|
|
930
1004
|
referenceMap = savedReferenceMap;
|
|
1005
|
+
bundledStrings = savedBundledStrings;
|
|
931
1006
|
src = savedSrc;
|
|
932
1007
|
sequentialMode = savedSequentialMode;
|
|
933
1008
|
currentStructures = savedStructures;
|
|
@@ -981,10 +1056,13 @@ const hasNodeBuffer = typeof Buffer !== 'undefined';
|
|
|
981
1056
|
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array;
|
|
982
1057
|
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
983
1058
|
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
984
|
-
let target;
|
|
1059
|
+
let target, keysTarget;
|
|
985
1060
|
let targetView;
|
|
986
1061
|
let position$1 = 0;
|
|
987
1062
|
let safeEnd;
|
|
1063
|
+
let bundledStrings$1 = null;
|
|
1064
|
+
const MAX_BUNDLE_SIZE = 0xf000;
|
|
1065
|
+
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
988
1066
|
const RECORD_SYMBOL = Symbol('record-id');
|
|
989
1067
|
class Packr extends Unpackr {
|
|
990
1068
|
constructor(options) {
|
|
@@ -1046,6 +1124,11 @@ class Packr extends Unpackr {
|
|
|
1046
1124
|
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1047
1125
|
start = position$1;
|
|
1048
1126
|
referenceMap = packr.structuredClone ? new Map() : null;
|
|
1127
|
+
if (packr.bundleStrings && typeof value !== 'string') {
|
|
1128
|
+
bundledStrings$1 = [];
|
|
1129
|
+
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1130
|
+
} else
|
|
1131
|
+
bundledStrings$1 = null;
|
|
1049
1132
|
sharedStructures = packr.structures;
|
|
1050
1133
|
if (sharedStructures) {
|
|
1051
1134
|
if (sharedStructures.uninitialized)
|
|
@@ -1081,9 +1164,12 @@ class Packr extends Unpackr {
|
|
|
1081
1164
|
}
|
|
1082
1165
|
if (hasSharedUpdate)
|
|
1083
1166
|
hasSharedUpdate = false;
|
|
1084
|
-
structures = sharedStructures || [];
|
|
1167
|
+
structures = sharedStructures || (packr.structures = []);
|
|
1085
1168
|
try {
|
|
1086
1169
|
pack(value);
|
|
1170
|
+
if (bundledStrings$1) {
|
|
1171
|
+
writeBundles(start, pack);
|
|
1172
|
+
}
|
|
1087
1173
|
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1088
1174
|
if (referenceMap && referenceMap.idsToInsert) {
|
|
1089
1175
|
position$1 += referenceMap.idsToInsert.length * 6;
|
|
@@ -1094,7 +1180,7 @@ class Packr extends Unpackr {
|
|
|
1094
1180
|
referenceMap = null;
|
|
1095
1181
|
return serialized
|
|
1096
1182
|
}
|
|
1097
|
-
if (encodeOptions
|
|
1183
|
+
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
1098
1184
|
target.start = start;
|
|
1099
1185
|
target.end = position$1;
|
|
1100
1186
|
return target
|
|
@@ -1104,6 +1190,8 @@ class Packr extends Unpackr {
|
|
|
1104
1190
|
if (sharedStructures) {
|
|
1105
1191
|
if (serializationsSinceTransitionRebuild < 10)
|
|
1106
1192
|
serializationsSinceTransitionRebuild++;
|
|
1193
|
+
if (sharedStructures.length > maxSharedStructures)
|
|
1194
|
+
sharedStructures.length = maxSharedStructures;
|
|
1107
1195
|
if (transitionsCount > 10000) {
|
|
1108
1196
|
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1109
1197
|
sharedStructures.transitions = null;
|
|
@@ -1133,6 +1221,8 @@ class Packr extends Unpackr {
|
|
|
1133
1221
|
return returnBuffer
|
|
1134
1222
|
}
|
|
1135
1223
|
}
|
|
1224
|
+
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1225
|
+
position$1 = start;
|
|
1136
1226
|
}
|
|
1137
1227
|
};
|
|
1138
1228
|
const pack = (value) => {
|
|
@@ -1143,6 +1233,36 @@ class Packr extends Unpackr {
|
|
|
1143
1233
|
var length;
|
|
1144
1234
|
if (type === 'string') {
|
|
1145
1235
|
let strLength = value.length;
|
|
1236
|
+
if (bundledStrings$1 && strLength >= 4 && strLength < 0x1000) {
|
|
1237
|
+
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1238
|
+
let extStart;
|
|
1239
|
+
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1240
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1241
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1242
|
+
if (bundledStrings$1.position) { // here we use the 0x62 extension to write the last bundle and reserve sapce for the reference pointer to the next/current bundle
|
|
1243
|
+
target[position$1] = 0xc8; // ext 16
|
|
1244
|
+
position$1 += 3; // reserve for the writing bundle size
|
|
1245
|
+
target[position$1++] = 0x62; // 'b'
|
|
1246
|
+
extStart = position$1 - start;
|
|
1247
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1248
|
+
writeBundles(start, pack); // write the last bundles
|
|
1249
|
+
targetView.setUint16(extStart + start - 3, position$1 - start - extStart);
|
|
1250
|
+
} else { // here we use the 0x62 extension just to reserve the space for the reference pointer to the bundle (will be updated once the bundle is written)
|
|
1251
|
+
target[position$1++] = 0xd6; // fixext 4
|
|
1252
|
+
target[position$1++] = 0x62; // 'b'
|
|
1253
|
+
extStart = position$1 - start;
|
|
1254
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1255
|
+
}
|
|
1256
|
+
bundledStrings$1 = ['', '']; // create new ones
|
|
1257
|
+
bundledStrings$1.size = 0;
|
|
1258
|
+
bundledStrings$1.position = extStart;
|
|
1259
|
+
}
|
|
1260
|
+
let twoByte = hasNonLatin.test(value);
|
|
1261
|
+
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1262
|
+
target[position$1++] = 0xc1;
|
|
1263
|
+
pack(twoByte ? -strLength : strLength);
|
|
1264
|
+
return
|
|
1265
|
+
}
|
|
1146
1266
|
let headerSize;
|
|
1147
1267
|
// first we estimate the header size, so we can write to the correct location
|
|
1148
1268
|
if (strLength < 0x20) {
|
|
@@ -1441,53 +1561,55 @@ class Packr extends Unpackr {
|
|
|
1441
1561
|
target[objectOffset++ + start] = size >> 8;
|
|
1442
1562
|
target[objectOffset + start] = size & 0xff;
|
|
1443
1563
|
} :
|
|
1444
|
-
|
|
1445
|
-
/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
|
|
1564
|
+
(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)
|
|
1446
1565
|
(object, safePrototype) => {
|
|
1447
|
-
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
1448
|
-
let objectOffset = position++ - start
|
|
1449
|
-
let wroteKeys
|
|
1566
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1567
|
+
let objectOffset = position$1++ - start;
|
|
1568
|
+
let wroteKeys;
|
|
1450
1569
|
for (let key in object) {
|
|
1451
1570
|
if (safePrototype || object.hasOwnProperty(key)) {
|
|
1452
|
-
nextTransition = transition[key]
|
|
1453
|
-
if (
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
let
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
nextTransition
|
|
1571
|
+
nextTransition = transition[key];
|
|
1572
|
+
if (nextTransition)
|
|
1573
|
+
transition = nextTransition;
|
|
1574
|
+
else {
|
|
1575
|
+
// record doesn't exist, create full new record and insert it
|
|
1576
|
+
let keys = Object.keys(object);
|
|
1577
|
+
let lastTransition = transition;
|
|
1578
|
+
transition = structures.transitions;
|
|
1579
|
+
let newTransitions = 0;
|
|
1580
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1581
|
+
let key = keys[i];
|
|
1582
|
+
nextTransition = transition[key];
|
|
1583
|
+
if (!nextTransition) {
|
|
1584
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1585
|
+
newTransitions++;
|
|
1466
1586
|
}
|
|
1587
|
+
transition = nextTransition;
|
|
1467
1588
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1589
|
+
if (objectOffset + start + 1 == position$1) {
|
|
1590
|
+
// first key, so we don't need to insert, we can just write record directly
|
|
1591
|
+
position$1--;
|
|
1592
|
+
newRecord(transition, keys, newTransitions);
|
|
1593
|
+
} else // otherwise we need to insert the record, moving existing data after the record
|
|
1594
|
+
insertNewRecord(transition, keys, objectOffset, newTransitions);
|
|
1595
|
+
wroteKeys = true;
|
|
1596
|
+
transition = lastTransition[key];
|
|
1472
1597
|
}
|
|
1473
|
-
|
|
1474
|
-
pack(object[key])
|
|
1598
|
+
pack(object[key]);
|
|
1475
1599
|
}
|
|
1476
1600
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1601
|
+
if (!wroteKeys) {
|
|
1602
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1603
|
+
if (recordId)
|
|
1604
|
+
target[objectOffset + start] = recordId;
|
|
1605
|
+
else
|
|
1606
|
+
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1482
1607
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
(object) => {
|
|
1486
|
-
let keys = Object.keys(object);
|
|
1608
|
+
} :
|
|
1609
|
+
(object, safePrototype) => {
|
|
1487
1610
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1488
1611
|
let newTransitions = 0;
|
|
1489
|
-
for (let
|
|
1490
|
-
let key = keys[i];
|
|
1612
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1491
1613
|
nextTransition = transition[key];
|
|
1492
1614
|
if (!nextTransition) {
|
|
1493
1615
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1503,57 +1625,12 @@ class Packr extends Unpackr {
|
|
|
1503
1625
|
} else
|
|
1504
1626
|
target[position$1++] = recordId;
|
|
1505
1627
|
} else {
|
|
1506
|
-
|
|
1507
|
-
if (!recordId)
|
|
1508
|
-
recordId = 0x40;
|
|
1509
|
-
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1510
|
-
recordId = structures.nextOwnId;
|
|
1511
|
-
if (!(recordId < maxStructureId))
|
|
1512
|
-
recordId = sharedLimitId;
|
|
1513
|
-
structures.nextOwnId = recordId + 1;
|
|
1514
|
-
} else {
|
|
1515
|
-
if (recordId >= maxStructureId)// cycle back around
|
|
1516
|
-
recordId = sharedLimitId;
|
|
1517
|
-
structures.nextId = recordId + 1;
|
|
1518
|
-
}
|
|
1519
|
-
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1520
|
-
transition[RECORD_SYMBOL] = recordId;
|
|
1521
|
-
structures[recordId - 0x40] = keys;
|
|
1522
|
-
|
|
1523
|
-
if (recordId < sharedLimitId) {
|
|
1524
|
-
keys.isShared = true;
|
|
1525
|
-
structures.sharedLength = recordId - 0x3f;
|
|
1526
|
-
hasSharedUpdate = true;
|
|
1527
|
-
if (highByte >= 0) {
|
|
1528
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1529
|
-
target[position$1++] = highByte;
|
|
1530
|
-
} else {
|
|
1531
|
-
target[position$1++] = recordId;
|
|
1532
|
-
}
|
|
1533
|
-
} else {
|
|
1534
|
-
if (highByte >= 0) {
|
|
1535
|
-
target[position$1++] = 0xd5; // fixext 2
|
|
1536
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1537
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1538
|
-
target[position$1++] = highByte;
|
|
1539
|
-
} else {
|
|
1540
|
-
target[position$1++] = 0xd4; // fixext 1
|
|
1541
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1542
|
-
target[position$1++] = recordId;
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
if (newTransitions)
|
|
1546
|
-
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1547
|
-
// record the removal of the id, we can maintain our shared structure
|
|
1548
|
-
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1549
|
-
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1550
|
-
recordIdsToRemove.push(transition);
|
|
1551
|
-
pack(keys);
|
|
1552
|
-
}
|
|
1628
|
+
newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions);
|
|
1553
1629
|
}
|
|
1554
1630
|
// now write the values
|
|
1555
|
-
for (let
|
|
1556
|
-
|
|
1631
|
+
for (let key in object)
|
|
1632
|
+
if (safePrototype || object.hasOwnProperty(key))
|
|
1633
|
+
pack(object[key]);
|
|
1557
1634
|
};
|
|
1558
1635
|
const makeRoom = (end) => {
|
|
1559
1636
|
let newSize;
|
|
@@ -1562,7 +1639,7 @@ class Packr extends Unpackr {
|
|
|
1562
1639
|
if ((end - start) > MAX_BUFFER_SIZE)
|
|
1563
1640
|
throw new Error('Packed buffer would be larger than maximum buffer size')
|
|
1564
1641
|
newSize = Math.min(MAX_BUFFER_SIZE,
|
|
1565
|
-
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2),
|
|
1642
|
+
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
|
|
1566
1643
|
} else // faster handling for smaller buffers
|
|
1567
1644
|
newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
|
|
1568
1645
|
let newBuffer = new ByteArrayAllocate(newSize);
|
|
@@ -1576,6 +1653,86 @@ class Packr extends Unpackr {
|
|
|
1576
1653
|
safeEnd = newBuffer.length - 10;
|
|
1577
1654
|
return target = newBuffer
|
|
1578
1655
|
};
|
|
1656
|
+
const newRecord = (transition, keys, newTransitions) => {
|
|
1657
|
+
let recordId = structures.nextId;
|
|
1658
|
+
if (!recordId)
|
|
1659
|
+
recordId = 0x40;
|
|
1660
|
+
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1661
|
+
recordId = structures.nextOwnId;
|
|
1662
|
+
if (!(recordId < maxStructureId))
|
|
1663
|
+
recordId = sharedLimitId;
|
|
1664
|
+
structures.nextOwnId = recordId + 1;
|
|
1665
|
+
} else {
|
|
1666
|
+
if (recordId >= maxStructureId)// cycle back around
|
|
1667
|
+
recordId = sharedLimitId;
|
|
1668
|
+
structures.nextId = recordId + 1;
|
|
1669
|
+
}
|
|
1670
|
+
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1671
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1672
|
+
transition.__keys__ = keys;
|
|
1673
|
+
structures[recordId - 0x40] = keys;
|
|
1674
|
+
|
|
1675
|
+
if (recordId < sharedLimitId) {
|
|
1676
|
+
keys.isShared = true;
|
|
1677
|
+
structures.sharedLength = recordId - 0x3f;
|
|
1678
|
+
hasSharedUpdate = true;
|
|
1679
|
+
if (highByte >= 0) {
|
|
1680
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1681
|
+
target[position$1++] = highByte;
|
|
1682
|
+
} else {
|
|
1683
|
+
target[position$1++] = recordId;
|
|
1684
|
+
}
|
|
1685
|
+
} else {
|
|
1686
|
+
if (highByte >= 0) {
|
|
1687
|
+
target[position$1++] = 0xd5; // fixext 2
|
|
1688
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1689
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1690
|
+
target[position$1++] = highByte;
|
|
1691
|
+
} else {
|
|
1692
|
+
target[position$1++] = 0xd4; // fixext 1
|
|
1693
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1694
|
+
target[position$1++] = recordId;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
if (newTransitions)
|
|
1698
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1699
|
+
// record the removal of the id, we can maintain our shared structure
|
|
1700
|
+
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1701
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1702
|
+
recordIdsToRemove.push(transition);
|
|
1703
|
+
pack(keys);
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
|
|
1707
|
+
let mainTarget = target;
|
|
1708
|
+
let mainPosition = position$1;
|
|
1709
|
+
let mainSafeEnd = safeEnd;
|
|
1710
|
+
let mainStart = start;
|
|
1711
|
+
target = keysTarget;
|
|
1712
|
+
position$1 = 0;
|
|
1713
|
+
start = 0;
|
|
1714
|
+
if (!target)
|
|
1715
|
+
keysTarget = target = new ByteArrayAllocate(8192);
|
|
1716
|
+
safeEnd = target.length - 10;
|
|
1717
|
+
newRecord(transition, keys, newTransitions);
|
|
1718
|
+
keysTarget = target;
|
|
1719
|
+
let keysPosition = position$1;
|
|
1720
|
+
target = mainTarget;
|
|
1721
|
+
position$1 = mainPosition;
|
|
1722
|
+
safeEnd = mainSafeEnd;
|
|
1723
|
+
start = mainStart;
|
|
1724
|
+
if (keysPosition > 1) {
|
|
1725
|
+
let newEnd = position$1 + keysPosition - 1;
|
|
1726
|
+
if (newEnd > safeEnd)
|
|
1727
|
+
makeRoom(newEnd);
|
|
1728
|
+
let insertionPosition = insertionOffset + start;
|
|
1729
|
+
target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position$1);
|
|
1730
|
+
target.set(keysTarget.slice(0, keysPosition), insertionPosition);
|
|
1731
|
+
position$1 = newEnd;
|
|
1732
|
+
} else {
|
|
1733
|
+
target[insertionOffset + start] = keysTarget[0];
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1579
1736
|
}
|
|
1580
1737
|
useBuffer(buffer) {
|
|
1581
1738
|
// this means we are finished using our own buffer and we can write over it safely
|
|
@@ -1583,11 +1740,15 @@ class Packr extends Unpackr {
|
|
|
1583
1740
|
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1584
1741
|
position$1 = 0;
|
|
1585
1742
|
}
|
|
1743
|
+
clearSharedData() {
|
|
1744
|
+
if (this.structures)
|
|
1745
|
+
this.structures = [];
|
|
1746
|
+
}
|
|
1586
1747
|
}
|
|
1587
1748
|
|
|
1588
1749
|
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
|
|
1589
1750
|
extensions = [{
|
|
1590
|
-
pack(date, allocateForWrite) {
|
|
1751
|
+
pack(date, allocateForWrite, pack) {
|
|
1591
1752
|
let seconds = date.getTime() / 1000;
|
|
1592
1753
|
if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
|
|
1593
1754
|
// Timestamp 32
|
|
@@ -1602,6 +1763,16 @@ extensions = [{
|
|
|
1602
1763
|
target[position++] = 0xff;
|
|
1603
1764
|
targetView.setUint32(position, date.getMilliseconds() * 4000000 + ((seconds / 1000 / 0x100000000) >> 0));
|
|
1604
1765
|
targetView.setUint32(position + 4, seconds);
|
|
1766
|
+
} else if (isNaN(seconds)) {
|
|
1767
|
+
if (this.onInvalidDate) {
|
|
1768
|
+
allocateForWrite(0);
|
|
1769
|
+
return pack(this.onInvalidDate())
|
|
1770
|
+
}
|
|
1771
|
+
// Intentionally invalid timestamp
|
|
1772
|
+
let { target, targetView, position} = allocateForWrite(3);
|
|
1773
|
+
target[position++] = 0xd4;
|
|
1774
|
+
target[position++] = 0xff;
|
|
1775
|
+
target[position++] = 0xff;
|
|
1605
1776
|
} else {
|
|
1606
1777
|
// Timestamp 96
|
|
1607
1778
|
let { target, targetView, position} = allocateForWrite(15);
|
|
@@ -1770,6 +1941,14 @@ function insertIds(serialized, idsToInsert) {
|
|
|
1770
1941
|
return serialized
|
|
1771
1942
|
}
|
|
1772
1943
|
|
|
1944
|
+
function writeBundles(start, pack) {
|
|
1945
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
|
|
1946
|
+
let writeStrings = bundledStrings$1;
|
|
1947
|
+
bundledStrings$1 = null;
|
|
1948
|
+
pack(writeStrings[0]);
|
|
1949
|
+
pack(writeStrings[1]);
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1773
1952
|
function addExtension$1(extension) {
|
|
1774
1953
|
if (extension.Class) {
|
|
1775
1954
|
if (!extension.pack && !extension.write)
|
|
@@ -1787,7 +1966,8 @@ const pack = defaultPackr.pack;
|
|
|
1787
1966
|
const encode = defaultPackr.pack;
|
|
1788
1967
|
const Encoder = Packr;
|
|
1789
1968
|
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1790
|
-
const REUSE_BUFFER_MODE =
|
|
1969
|
+
const REUSE_BUFFER_MODE = 512;
|
|
1970
|
+
const RESET_BUFFER_MODE = 1024;
|
|
1791
1971
|
|
|
1792
1972
|
class PackrStream extends stream.Transform {
|
|
1793
1973
|
constructor(options) {
|
|
@@ -1939,9 +2119,7 @@ function tryRequire(moduleId) {
|
|
|
1939
2119
|
let require$1 = module$1.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('node.cjs', document.baseURI).href)));
|
|
1940
2120
|
return require$1(moduleId)
|
|
1941
2121
|
} catch (error) {
|
|
1942
|
-
if (typeof window
|
|
1943
|
-
console.warn('Native extraction module not loaded, msgpackr will still run, but with decreased performance. ' + error.message.split('\n')[0]);
|
|
1944
|
-
else
|
|
2122
|
+
if (typeof window != 'undefined')
|
|
1945
2123
|
console.warn('For browser usage, directly use msgpackr/unpack or msgpackr/pack modules. ' + error.message.split('\n')[0]);
|
|
1946
2124
|
}
|
|
1947
2125
|
}
|