msgpackr 1.5.2 → 1.5.5
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 +4 -2
- package/dist/index.js +241 -138
- package/dist/index.min.js +67 -100
- package/dist/node.cjs +243 -138
- package/dist/test.js +22 -2
- package/pack.js +189 -122
- package/package.json +1 -1
- package/unpack.d.ts +2 -0
- package/unpack.js +49 -10
- package/dist/str.cjs +0 -100
package/dist/node.cjs
CHANGED
|
@@ -32,6 +32,13 @@ class C1Type {}
|
|
|
32
32
|
const C1 = new C1Type();
|
|
33
33
|
C1.name = 'MessagePack 0xC1';
|
|
34
34
|
var sequentialMode = false;
|
|
35
|
+
var inlineObjectReadThreshold = 2;
|
|
36
|
+
try {
|
|
37
|
+
new Function('');
|
|
38
|
+
} catch(error) {
|
|
39
|
+
// if eval variants are not supported, do not create inline object readers ever
|
|
40
|
+
inlineObjectReadThreshold = Infinity;
|
|
41
|
+
}
|
|
35
42
|
|
|
36
43
|
class Unpackr {
|
|
37
44
|
constructor(options) {
|
|
@@ -158,6 +165,9 @@ function checkedRead() {
|
|
|
158
165
|
currentStructures.length = sharedLength;
|
|
159
166
|
}
|
|
160
167
|
let result = read();
|
|
168
|
+
if (bundledStrings) // bundled strings to skip past
|
|
169
|
+
position = bundledStrings.postBundlePosition;
|
|
170
|
+
|
|
161
171
|
if (position == srcEnd) {
|
|
162
172
|
// finished reading this source, cleanup references
|
|
163
173
|
if (currentStructures.restoreStructures)
|
|
@@ -439,7 +449,7 @@ const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
|
|
|
439
449
|
function createStructureReader(structure, firstId) {
|
|
440
450
|
function readObject() {
|
|
441
451
|
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
|
442
|
-
if (readObject.count++ >
|
|
452
|
+
if (readObject.count++ > inlineObjectReadThreshold) {
|
|
443
453
|
let readObject = structure.read = (new Function('r', 'return function(){return {' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}}'))(read);
|
|
444
454
|
if (structure.highByte === 0)
|
|
445
455
|
structure.read = createSecondByteReader(firstId, structure.read);
|
|
@@ -500,6 +510,8 @@ function setExtractor(extractStrings) {
|
|
|
500
510
|
return function readString(length) {
|
|
501
511
|
let string = strings[stringPosition++];
|
|
502
512
|
if (string == null) {
|
|
513
|
+
if (bundledStrings)
|
|
514
|
+
return readStringJS(length)
|
|
503
515
|
let extraction = extractStrings(position - headerLength, srcEnd, src);
|
|
504
516
|
if (typeof extraction == 'string') {
|
|
505
517
|
string = extraction;
|
|
@@ -758,6 +770,36 @@ function shortStringInJS(length) {
|
|
|
758
770
|
}
|
|
759
771
|
}
|
|
760
772
|
|
|
773
|
+
function readOnlyJSString() {
|
|
774
|
+
let token = src[position++];
|
|
775
|
+
let length;
|
|
776
|
+
if (token < 0xc0) {
|
|
777
|
+
// fixstr
|
|
778
|
+
length = token - 0xa0;
|
|
779
|
+
} else {
|
|
780
|
+
switch(token) {
|
|
781
|
+
case 0xd9:
|
|
782
|
+
// str 8
|
|
783
|
+
length = src[position++];
|
|
784
|
+
break
|
|
785
|
+
case 0xda:
|
|
786
|
+
// str 16
|
|
787
|
+
length = dataView.getUint16(position);
|
|
788
|
+
position += 2;
|
|
789
|
+
break
|
|
790
|
+
case 0xdb:
|
|
791
|
+
// str 32
|
|
792
|
+
length = dataView.getUint32(position);
|
|
793
|
+
position += 4;
|
|
794
|
+
break
|
|
795
|
+
default:
|
|
796
|
+
throw new Error('Expected string')
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return readStringJS(length)
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
|
|
761
803
|
function readBin(length) {
|
|
762
804
|
return currentUnpackr.copyBuffers ?
|
|
763
805
|
// specifically use the copying slice (not the node one)
|
|
@@ -909,21 +951,18 @@ currentExtensions[0x78] = () => {
|
|
|
909
951
|
let data = read();
|
|
910
952
|
return new RegExp(data[0], data[1])
|
|
911
953
|
};
|
|
912
|
-
|
|
954
|
+
const TEMP_BUNDLE = [];
|
|
913
955
|
currentExtensions[0x62] = (data) => {
|
|
914
956
|
let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
|
|
915
957
|
let dataPosition = position;
|
|
916
|
-
position += dataSize -
|
|
917
|
-
bundledStrings =
|
|
958
|
+
position += dataSize - data.length;
|
|
959
|
+
bundledStrings = TEMP_BUNDLE;
|
|
960
|
+
bundledStrings = [readOnlyJSString(), readOnlyJSString()];
|
|
918
961
|
bundledStrings.position0 = 0;
|
|
919
962
|
bundledStrings.position1 = 0;
|
|
920
|
-
|
|
963
|
+
bundledStrings.postBundlePosition = position;
|
|
921
964
|
position = dataPosition;
|
|
922
|
-
|
|
923
|
-
return read()
|
|
924
|
-
} finally {
|
|
925
|
-
position = postBundlePosition;
|
|
926
|
-
}
|
|
965
|
+
return read()
|
|
927
966
|
};
|
|
928
967
|
|
|
929
968
|
currentExtensions[0xff] = (data) => {
|
|
@@ -1024,11 +1063,12 @@ const hasNodeBuffer = typeof Buffer !== 'undefined';
|
|
|
1024
1063
|
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array;
|
|
1025
1064
|
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
1026
1065
|
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
1027
|
-
let target;
|
|
1066
|
+
let target, keysTarget;
|
|
1028
1067
|
let targetView;
|
|
1029
1068
|
let position$1 = 0;
|
|
1030
1069
|
let safeEnd;
|
|
1031
1070
|
let bundledStrings$1 = null;
|
|
1071
|
+
const MAX_BUNDLE_SIZE = 0xf000;
|
|
1032
1072
|
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
1033
1073
|
const RECORD_SYMBOL = Symbol('record-id');
|
|
1034
1074
|
class Packr extends Unpackr {
|
|
@@ -1036,7 +1076,6 @@ class Packr extends Unpackr {
|
|
|
1036
1076
|
super(options);
|
|
1037
1077
|
this.offset = 0;
|
|
1038
1078
|
let start;
|
|
1039
|
-
let sharedStructures;
|
|
1040
1079
|
let hasSharedUpdate;
|
|
1041
1080
|
let structures;
|
|
1042
1081
|
let referenceMap;
|
|
@@ -1058,10 +1097,13 @@ class Packr extends Unpackr {
|
|
|
1058
1097
|
maxSharedStructures = hasSharedStructures ? 32 : 0;
|
|
1059
1098
|
if (maxSharedStructures > 8160)
|
|
1060
1099
|
throw new Error('Maximum maxSharedStructure is 8160')
|
|
1100
|
+
if (options.structuredClone && options.moreTypes == undefined) {
|
|
1101
|
+
options.moreTypes = true;
|
|
1102
|
+
}
|
|
1061
1103
|
let maxOwnStructures = options.maxOwnStructures;
|
|
1062
1104
|
if (maxOwnStructures == null)
|
|
1063
1105
|
maxOwnStructures = hasSharedStructures ? 32 : 64;
|
|
1064
|
-
if (
|
|
1106
|
+
if (!this.structures && options.useRecords != false)
|
|
1065
1107
|
this.structures = [];
|
|
1066
1108
|
// two byte record ids for shared structures
|
|
1067
1109
|
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
|
|
@@ -1091,31 +1133,28 @@ class Packr extends Unpackr {
|
|
|
1091
1133
|
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1092
1134
|
start = position$1;
|
|
1093
1135
|
referenceMap = packr.structuredClone ? new Map() : null;
|
|
1094
|
-
if (packr.bundleStrings) {
|
|
1095
|
-
bundledStrings$1 = [
|
|
1096
|
-
|
|
1097
|
-
target[position$1++] = 0x62; // 'b'
|
|
1098
|
-
bundledStrings$1.position = position$1 - start;
|
|
1099
|
-
position$1 += 4;
|
|
1136
|
+
if (packr.bundleStrings && typeof value !== 'string') {
|
|
1137
|
+
bundledStrings$1 = [];
|
|
1138
|
+
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1100
1139
|
} else
|
|
1101
1140
|
bundledStrings$1 = null;
|
|
1102
|
-
|
|
1103
|
-
if (
|
|
1104
|
-
if (
|
|
1105
|
-
|
|
1106
|
-
let sharedLength =
|
|
1141
|
+
structures = packr.structures;
|
|
1142
|
+
if (structures) {
|
|
1143
|
+
if (structures.uninitialized)
|
|
1144
|
+
structures = packr._mergeStructures(packr.getStructures());
|
|
1145
|
+
let sharedLength = structures.sharedLength || 0;
|
|
1107
1146
|
if (sharedLength > maxSharedStructures) {
|
|
1108
|
-
//if (maxSharedStructures <= 32 &&
|
|
1109
|
-
throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' +
|
|
1147
|
+
//if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
|
|
1148
|
+
throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
|
|
1110
1149
|
}
|
|
1111
|
-
if (!
|
|
1150
|
+
if (!structures.transitions) {
|
|
1112
1151
|
// rebuild our structure transitions
|
|
1113
|
-
|
|
1152
|
+
structures.transitions = Object.create(null);
|
|
1114
1153
|
for (let i = 0; i < sharedLength; i++) {
|
|
1115
|
-
let keys =
|
|
1154
|
+
let keys = structures[i];
|
|
1116
1155
|
if (!keys)
|
|
1117
1156
|
continue
|
|
1118
|
-
let nextTransition, transition =
|
|
1157
|
+
let nextTransition, transition = structures.transitions;
|
|
1119
1158
|
for (let j = 0, l = keys.length; j < l; j++) {
|
|
1120
1159
|
let key = keys[j];
|
|
1121
1160
|
nextTransition = transition[key];
|
|
@@ -1129,20 +1168,15 @@ class Packr extends Unpackr {
|
|
|
1129
1168
|
lastSharedStructuresLength = sharedLength;
|
|
1130
1169
|
}
|
|
1131
1170
|
if (!isSequential) {
|
|
1132
|
-
|
|
1171
|
+
structures.nextId = sharedLength + 0x40;
|
|
1133
1172
|
}
|
|
1134
1173
|
}
|
|
1135
1174
|
if (hasSharedUpdate)
|
|
1136
1175
|
hasSharedUpdate = false;
|
|
1137
|
-
structures = sharedStructures || [];
|
|
1138
1176
|
try {
|
|
1139
1177
|
pack(value);
|
|
1140
1178
|
if (bundledStrings$1) {
|
|
1141
|
-
|
|
1142
|
-
let writeStrings = bundledStrings$1;
|
|
1143
|
-
bundledStrings$1 = null;
|
|
1144
|
-
pack(writeStrings[0]);
|
|
1145
|
-
pack(writeStrings[1]);
|
|
1179
|
+
writeBundles(start, pack);
|
|
1146
1180
|
}
|
|
1147
1181
|
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1148
1182
|
if (referenceMap && referenceMap.idsToInsert) {
|
|
@@ -1161,12 +1195,15 @@ class Packr extends Unpackr {
|
|
|
1161
1195
|
}
|
|
1162
1196
|
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1163
1197
|
} finally {
|
|
1164
|
-
if (
|
|
1198
|
+
if (structures) {
|
|
1165
1199
|
if (serializationsSinceTransitionRebuild < 10)
|
|
1166
1200
|
serializationsSinceTransitionRebuild++;
|
|
1201
|
+
let sharedLength = structures.sharedLength || maxSharedStructures;
|
|
1202
|
+
if (structures.length > sharedLength)
|
|
1203
|
+
structures.length = sharedLength;
|
|
1167
1204
|
if (transitionsCount > 10000) {
|
|
1168
1205
|
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1169
|
-
|
|
1206
|
+
structures.transitions = null;
|
|
1170
1207
|
serializationsSinceTransitionRebuild = 0;
|
|
1171
1208
|
transitionsCount = 0;
|
|
1172
1209
|
if (recordIdsToRemove.length > 0)
|
|
@@ -1178,13 +1215,9 @@ class Packr extends Unpackr {
|
|
|
1178
1215
|
recordIdsToRemove = [];
|
|
1179
1216
|
}
|
|
1180
1217
|
if (hasSharedUpdate && packr.saveStructures) {
|
|
1181
|
-
let sharedLength = sharedStructures.sharedLength || maxSharedStructures;
|
|
1182
|
-
if (sharedStructures.length > sharedLength) {
|
|
1183
|
-
sharedStructures = sharedStructures.slice(0, sharedLength);
|
|
1184
|
-
}
|
|
1185
1218
|
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1186
1219
|
let returnBuffer = target.subarray(start, position$1);
|
|
1187
|
-
if (packr.saveStructures(
|
|
1220
|
+
if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
|
|
1188
1221
|
// get updated structures and try again if the update failed
|
|
1189
1222
|
packr._mergeStructures(packr.getStructures());
|
|
1190
1223
|
return packr.pack(value)
|
|
@@ -1205,7 +1238,30 @@ class Packr extends Unpackr {
|
|
|
1205
1238
|
var length;
|
|
1206
1239
|
if (type === 'string') {
|
|
1207
1240
|
let strLength = value.length;
|
|
1208
|
-
if (bundledStrings$1 && strLength >=
|
|
1241
|
+
if (bundledStrings$1 && strLength >= 4 && strLength < 0x1000) {
|
|
1242
|
+
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1243
|
+
let extStart;
|
|
1244
|
+
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1245
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1246
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1247
|
+
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
|
|
1248
|
+
target[position$1] = 0xc8; // ext 16
|
|
1249
|
+
position$1 += 3; // reserve for the writing bundle size
|
|
1250
|
+
target[position$1++] = 0x62; // 'b'
|
|
1251
|
+
extStart = position$1 - start;
|
|
1252
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1253
|
+
writeBundles(start, pack); // write the last bundles
|
|
1254
|
+
targetView.setUint16(extStart + start - 3, position$1 - start - extStart);
|
|
1255
|
+
} 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)
|
|
1256
|
+
target[position$1++] = 0xd6; // fixext 4
|
|
1257
|
+
target[position$1++] = 0x62; // 'b'
|
|
1258
|
+
extStart = position$1 - start;
|
|
1259
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1260
|
+
}
|
|
1261
|
+
bundledStrings$1 = ['', '']; // create new ones
|
|
1262
|
+
bundledStrings$1.size = 0;
|
|
1263
|
+
bundledStrings$1.position = extStart;
|
|
1264
|
+
}
|
|
1209
1265
|
let twoByte = hasNonLatin.test(value);
|
|
1210
1266
|
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1211
1267
|
target[position$1++] = 0xc1;
|
|
@@ -1510,53 +1566,55 @@ class Packr extends Unpackr {
|
|
|
1510
1566
|
target[objectOffset++ + start] = size >> 8;
|
|
1511
1567
|
target[objectOffset + start] = size & 0xff;
|
|
1512
1568
|
} :
|
|
1513
|
-
|
|
1514
|
-
/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
|
|
1569
|
+
(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)
|
|
1515
1570
|
(object, safePrototype) => {
|
|
1516
|
-
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
1517
|
-
let objectOffset = position++ - start
|
|
1518
|
-
let wroteKeys
|
|
1571
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1572
|
+
let objectOffset = position$1++ - start;
|
|
1573
|
+
let wroteKeys;
|
|
1519
1574
|
for (let key in object) {
|
|
1520
1575
|
if (safePrototype || object.hasOwnProperty(key)) {
|
|
1521
|
-
nextTransition = transition[key]
|
|
1522
|
-
if (
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
let
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
nextTransition
|
|
1576
|
+
nextTransition = transition[key];
|
|
1577
|
+
if (nextTransition)
|
|
1578
|
+
transition = nextTransition;
|
|
1579
|
+
else {
|
|
1580
|
+
// record doesn't exist, create full new record and insert it
|
|
1581
|
+
let keys = Object.keys(object);
|
|
1582
|
+
let lastTransition = transition;
|
|
1583
|
+
transition = structures.transitions;
|
|
1584
|
+
let newTransitions = 0;
|
|
1585
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1586
|
+
let key = keys[i];
|
|
1587
|
+
nextTransition = transition[key];
|
|
1588
|
+
if (!nextTransition) {
|
|
1589
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1590
|
+
newTransitions++;
|
|
1535
1591
|
}
|
|
1592
|
+
transition = nextTransition;
|
|
1536
1593
|
}
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1594
|
+
if (objectOffset + start + 1 == position$1) {
|
|
1595
|
+
// first key, so we don't need to insert, we can just write record directly
|
|
1596
|
+
position$1--;
|
|
1597
|
+
newRecord(transition, keys, newTransitions);
|
|
1598
|
+
} else // otherwise we need to insert the record, moving existing data after the record
|
|
1599
|
+
insertNewRecord(transition, keys, objectOffset, newTransitions);
|
|
1600
|
+
wroteKeys = true;
|
|
1601
|
+
transition = lastTransition[key];
|
|
1541
1602
|
}
|
|
1542
|
-
|
|
1543
|
-
pack(object[key])
|
|
1603
|
+
pack(object[key]);
|
|
1544
1604
|
}
|
|
1545
1605
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1606
|
+
if (!wroteKeys) {
|
|
1607
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1608
|
+
if (recordId)
|
|
1609
|
+
target[objectOffset + start] = recordId;
|
|
1610
|
+
else
|
|
1611
|
+
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1551
1612
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
(object) => {
|
|
1555
|
-
let keys = Object.keys(object);
|
|
1613
|
+
} :
|
|
1614
|
+
(object, safePrototype) => {
|
|
1556
1615
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1557
1616
|
let newTransitions = 0;
|
|
1558
|
-
for (let
|
|
1559
|
-
let key = keys[i];
|
|
1617
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1560
1618
|
nextTransition = transition[key];
|
|
1561
1619
|
if (!nextTransition) {
|
|
1562
1620
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1572,57 +1630,12 @@ class Packr extends Unpackr {
|
|
|
1572
1630
|
} else
|
|
1573
1631
|
target[position$1++] = recordId;
|
|
1574
1632
|
} else {
|
|
1575
|
-
|
|
1576
|
-
if (!recordId)
|
|
1577
|
-
recordId = 0x40;
|
|
1578
|
-
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1579
|
-
recordId = structures.nextOwnId;
|
|
1580
|
-
if (!(recordId < maxStructureId))
|
|
1581
|
-
recordId = sharedLimitId;
|
|
1582
|
-
structures.nextOwnId = recordId + 1;
|
|
1583
|
-
} else {
|
|
1584
|
-
if (recordId >= maxStructureId)// cycle back around
|
|
1585
|
-
recordId = sharedLimitId;
|
|
1586
|
-
structures.nextId = recordId + 1;
|
|
1587
|
-
}
|
|
1588
|
-
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1589
|
-
transition[RECORD_SYMBOL] = recordId;
|
|
1590
|
-
structures[recordId - 0x40] = keys;
|
|
1591
|
-
|
|
1592
|
-
if (recordId < sharedLimitId) {
|
|
1593
|
-
keys.isShared = true;
|
|
1594
|
-
structures.sharedLength = recordId - 0x3f;
|
|
1595
|
-
hasSharedUpdate = true;
|
|
1596
|
-
if (highByte >= 0) {
|
|
1597
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1598
|
-
target[position$1++] = highByte;
|
|
1599
|
-
} else {
|
|
1600
|
-
target[position$1++] = recordId;
|
|
1601
|
-
}
|
|
1602
|
-
} else {
|
|
1603
|
-
if (highByte >= 0) {
|
|
1604
|
-
target[position$1++] = 0xd5; // fixext 2
|
|
1605
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1606
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1607
|
-
target[position$1++] = highByte;
|
|
1608
|
-
} else {
|
|
1609
|
-
target[position$1++] = 0xd4; // fixext 1
|
|
1610
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1611
|
-
target[position$1++] = recordId;
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
if (newTransitions)
|
|
1615
|
-
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1616
|
-
// record the removal of the id, we can maintain our shared structure
|
|
1617
|
-
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1618
|
-
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1619
|
-
recordIdsToRemove.push(transition);
|
|
1620
|
-
pack(keys);
|
|
1621
|
-
}
|
|
1633
|
+
newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions);
|
|
1622
1634
|
}
|
|
1623
1635
|
// now write the values
|
|
1624
|
-
for (let
|
|
1625
|
-
|
|
1636
|
+
for (let key in object)
|
|
1637
|
+
if (safePrototype || object.hasOwnProperty(key))
|
|
1638
|
+
pack(object[key]);
|
|
1626
1639
|
};
|
|
1627
1640
|
const makeRoom = (end) => {
|
|
1628
1641
|
let newSize;
|
|
@@ -1645,6 +1658,86 @@ class Packr extends Unpackr {
|
|
|
1645
1658
|
safeEnd = newBuffer.length - 10;
|
|
1646
1659
|
return target = newBuffer
|
|
1647
1660
|
};
|
|
1661
|
+
const newRecord = (transition, keys, newTransitions) => {
|
|
1662
|
+
let recordId = structures.nextId;
|
|
1663
|
+
if (!recordId)
|
|
1664
|
+
recordId = 0x40;
|
|
1665
|
+
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1666
|
+
recordId = structures.nextOwnId;
|
|
1667
|
+
if (!(recordId < maxStructureId))
|
|
1668
|
+
recordId = sharedLimitId;
|
|
1669
|
+
structures.nextOwnId = recordId + 1;
|
|
1670
|
+
} else {
|
|
1671
|
+
if (recordId >= maxStructureId)// cycle back around
|
|
1672
|
+
recordId = sharedLimitId;
|
|
1673
|
+
structures.nextId = recordId + 1;
|
|
1674
|
+
}
|
|
1675
|
+
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1676
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1677
|
+
transition.__keys__ = keys;
|
|
1678
|
+
structures[recordId - 0x40] = keys;
|
|
1679
|
+
|
|
1680
|
+
if (recordId < sharedLimitId) {
|
|
1681
|
+
keys.isShared = true;
|
|
1682
|
+
structures.sharedLength = recordId - 0x3f;
|
|
1683
|
+
hasSharedUpdate = true;
|
|
1684
|
+
if (highByte >= 0) {
|
|
1685
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1686
|
+
target[position$1++] = highByte;
|
|
1687
|
+
} else {
|
|
1688
|
+
target[position$1++] = recordId;
|
|
1689
|
+
}
|
|
1690
|
+
} else {
|
|
1691
|
+
if (highByte >= 0) {
|
|
1692
|
+
target[position$1++] = 0xd5; // fixext 2
|
|
1693
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1694
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1695
|
+
target[position$1++] = highByte;
|
|
1696
|
+
} else {
|
|
1697
|
+
target[position$1++] = 0xd4; // fixext 1
|
|
1698
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1699
|
+
target[position$1++] = recordId;
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
if (newTransitions)
|
|
1703
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1704
|
+
// record the removal of the id, we can maintain our shared structure
|
|
1705
|
+
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1706
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1707
|
+
recordIdsToRemove.push(transition);
|
|
1708
|
+
pack(keys);
|
|
1709
|
+
}
|
|
1710
|
+
};
|
|
1711
|
+
const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
|
|
1712
|
+
let mainTarget = target;
|
|
1713
|
+
let mainPosition = position$1;
|
|
1714
|
+
let mainSafeEnd = safeEnd;
|
|
1715
|
+
let mainStart = start;
|
|
1716
|
+
target = keysTarget;
|
|
1717
|
+
position$1 = 0;
|
|
1718
|
+
start = 0;
|
|
1719
|
+
if (!target)
|
|
1720
|
+
keysTarget = target = new ByteArrayAllocate(8192);
|
|
1721
|
+
safeEnd = target.length - 10;
|
|
1722
|
+
newRecord(transition, keys, newTransitions);
|
|
1723
|
+
keysTarget = target;
|
|
1724
|
+
let keysPosition = position$1;
|
|
1725
|
+
target = mainTarget;
|
|
1726
|
+
position$1 = mainPosition;
|
|
1727
|
+
safeEnd = mainSafeEnd;
|
|
1728
|
+
start = mainStart;
|
|
1729
|
+
if (keysPosition > 1) {
|
|
1730
|
+
let newEnd = position$1 + keysPosition - 1;
|
|
1731
|
+
if (newEnd > safeEnd)
|
|
1732
|
+
makeRoom(newEnd);
|
|
1733
|
+
let insertionPosition = insertionOffset + start;
|
|
1734
|
+
target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position$1);
|
|
1735
|
+
target.set(keysTarget.slice(0, keysPosition), insertionPosition);
|
|
1736
|
+
position$1 = newEnd;
|
|
1737
|
+
} else {
|
|
1738
|
+
target[insertionOffset + start] = keysTarget[0];
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1648
1741
|
}
|
|
1649
1742
|
useBuffer(buffer) {
|
|
1650
1743
|
// this means we are finished using our own buffer and we can write over it safely
|
|
@@ -1652,6 +1745,10 @@ class Packr extends Unpackr {
|
|
|
1652
1745
|
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1653
1746
|
position$1 = 0;
|
|
1654
1747
|
}
|
|
1748
|
+
clearSharedData() {
|
|
1749
|
+
if (this.structures)
|
|
1750
|
+
this.structures = [];
|
|
1751
|
+
}
|
|
1655
1752
|
}
|
|
1656
1753
|
|
|
1657
1754
|
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
|
|
@@ -1694,8 +1791,8 @@ extensions = [{
|
|
|
1694
1791
|
}, {
|
|
1695
1792
|
pack(set, allocateForWrite, pack) {
|
|
1696
1793
|
let array = Array.from(set);
|
|
1697
|
-
let { target, position} = allocateForWrite(this.
|
|
1698
|
-
if (this.
|
|
1794
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1795
|
+
if (this.moreTypes) {
|
|
1699
1796
|
target[position++] = 0xd4;
|
|
1700
1797
|
target[position++] = 0x73; // 's' for Set
|
|
1701
1798
|
target[position++] = 0;
|
|
@@ -1704,8 +1801,8 @@ extensions = [{
|
|
|
1704
1801
|
}
|
|
1705
1802
|
}, {
|
|
1706
1803
|
pack(error, allocateForWrite, pack) {
|
|
1707
|
-
let { target, position} = allocateForWrite(this.
|
|
1708
|
-
if (this.
|
|
1804
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1805
|
+
if (this.moreTypes) {
|
|
1709
1806
|
target[position++] = 0xd4;
|
|
1710
1807
|
target[position++] = 0x65; // 'e' for error
|
|
1711
1808
|
target[position++] = 0;
|
|
@@ -1714,8 +1811,8 @@ extensions = [{
|
|
|
1714
1811
|
}
|
|
1715
1812
|
}, {
|
|
1716
1813
|
pack(regex, allocateForWrite, pack) {
|
|
1717
|
-
let { target, position} = allocateForWrite(this.
|
|
1718
|
-
if (this.
|
|
1814
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1815
|
+
if (this.moreTypes) {
|
|
1719
1816
|
target[position++] = 0xd4;
|
|
1720
1817
|
target[position++] = 0x78; // 'x' for regeXp
|
|
1721
1818
|
target[position++] = 0;
|
|
@@ -1724,7 +1821,7 @@ extensions = [{
|
|
|
1724
1821
|
}
|
|
1725
1822
|
}, {
|
|
1726
1823
|
pack(arrayBuffer, allocateForWrite) {
|
|
1727
|
-
if (this.
|
|
1824
|
+
if (this.moreTypes)
|
|
1728
1825
|
writeExtBuffer(arrayBuffer, 0x10, allocateForWrite);
|
|
1729
1826
|
else
|
|
1730
1827
|
writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
|
|
@@ -1732,7 +1829,7 @@ extensions = [{
|
|
|
1732
1829
|
}, {
|
|
1733
1830
|
pack(typedArray, allocateForWrite) {
|
|
1734
1831
|
let constructor = typedArray.constructor;
|
|
1735
|
-
if (constructor !== ByteArray && this.
|
|
1832
|
+
if (constructor !== ByteArray && this.moreTypes)
|
|
1736
1833
|
writeExtBuffer(typedArray, typedArrays.indexOf(constructor.name), allocateForWrite);
|
|
1737
1834
|
else
|
|
1738
1835
|
writeBuffer(typedArray, allocateForWrite);
|
|
@@ -1849,6 +1946,14 @@ function insertIds(serialized, idsToInsert) {
|
|
|
1849
1946
|
return serialized
|
|
1850
1947
|
}
|
|
1851
1948
|
|
|
1949
|
+
function writeBundles(start, pack) {
|
|
1950
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
|
|
1951
|
+
let writeStrings = bundledStrings$1;
|
|
1952
|
+
bundledStrings$1 = null;
|
|
1953
|
+
pack(writeStrings[0]);
|
|
1954
|
+
pack(writeStrings[1]);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1852
1957
|
function addExtension$1(extension) {
|
|
1853
1958
|
if (extension.Class) {
|
|
1854
1959
|
if (!extension.pack && !extension.write)
|
package/dist/test.js
CHANGED
|
@@ -634,10 +634,29 @@
|
|
|
634
634
|
let structures = [];
|
|
635
635
|
let packr = new Packr({ structures });
|
|
636
636
|
var serialized = packr.pack(data);
|
|
637
|
+
serialized = packr.pack(data);
|
|
638
|
+
serialized = packr.pack(data);
|
|
637
639
|
var deserialized = packr.unpack(serialized);
|
|
638
640
|
assert.deepEqual(deserialized, data);
|
|
639
641
|
});
|
|
640
642
|
|
|
643
|
+
test('mixed structures', function(){
|
|
644
|
+
let data1 = { a: 1, b: 2, c: 3 };
|
|
645
|
+
let data2 = { a: 1, b: 2, d: 4 };
|
|
646
|
+
let data3 = { a: 1, b: 2, e: 5 };
|
|
647
|
+
let structures = [];
|
|
648
|
+
let packr = new Packr({ structures });
|
|
649
|
+
var serialized = packr.pack(data1);
|
|
650
|
+
var deserialized = packr.unpack(serialized);
|
|
651
|
+
assert.deepEqual(deserialized, data1);
|
|
652
|
+
var serialized = packr.pack(data2);
|
|
653
|
+
var deserialized = packr.unpack(serialized);
|
|
654
|
+
assert.deepEqual(deserialized, data2);
|
|
655
|
+
var serialized = packr.pack(data3);
|
|
656
|
+
var deserialized = packr.unpack(serialized);
|
|
657
|
+
assert.deepEqual(deserialized, data3);
|
|
658
|
+
});
|
|
659
|
+
|
|
641
660
|
test('mixed array', function(){
|
|
642
661
|
var data = [
|
|
643
662
|
'one',
|
|
@@ -686,8 +705,7 @@
|
|
|
686
705
|
});
|
|
687
706
|
test('pack/unpack sample data with bundled strings', function(){
|
|
688
707
|
var data = sampleData;
|
|
689
|
-
let
|
|
690
|
-
let packr = new Packr({ structures, bundleStrings: true });
|
|
708
|
+
let packr = new Packr({ /*structures,*/ useRecords: false, bundleStrings: true });
|
|
691
709
|
var serialized = packr.pack(data);
|
|
692
710
|
var deserialized = packr.unpack(serialized);
|
|
693
711
|
assert.deepEqual(deserialized, data);
|
|
@@ -841,6 +859,7 @@
|
|
|
841
859
|
object.children[2] = object.children[0];
|
|
842
860
|
object.childrenAgain = object.children;
|
|
843
861
|
let packr = new Packr({
|
|
862
|
+
moreTypes: true,
|
|
844
863
|
structuredClone: true,
|
|
845
864
|
});
|
|
846
865
|
var serialized = packr.pack(object);
|
|
@@ -865,6 +884,7 @@
|
|
|
865
884
|
uint16Array: new Uint16Array([3,4])
|
|
866
885
|
};
|
|
867
886
|
let packr = new Packr({
|
|
887
|
+
moreTypes: true,
|
|
868
888
|
structuredClone: true,
|
|
869
889
|
});
|
|
870
890
|
var serialized = packr.pack(object);
|