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/README.md
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
[](README.md)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
|
|
10
|
+
<img align="right" src="./assets/performance.png" width="380"/>
|
|
10
11
|
|
|
11
|
-
The msgpackr package is an extremely fast MessagePack NodeJS/JavaScript implementation. Currently, it is significantly faster than any other known implementations, faster than Avro (for JS), and generally faster than native V8 JSON.stringify/parse, on NodeJS. It also includes an optional record extension (the `r` in msgpackr), for defining record structures that makes MessagePack even faster and more compact, often over twice as fast as even native JSON functions, several times faster than other JS implementations, and 15-50% more compact. See the performance section for more details. Structured cloning (with support for cyclical references) is also supported through optional extensions
|
|
12
|
+
The msgpackr package is an extremely fast MessagePack NodeJS/JavaScript implementation. Currently, it is significantly faster than any other known implementations, faster than Avro (for JS), and generally faster than native V8 JSON.stringify/parse, on NodeJS. It also includes an optional record extension (the `r` in msgpackr), for defining record structures that makes MessagePack even faster and more compact, often over twice as fast as even native JSON functions, several times faster than other JS implementations, and 15-50% more compact. See the performance section for more details. Structured cloning (with support for cyclical references) is also supported through optional extensions.
|
|
12
13
|
|
|
13
14
|
## Basic Usage
|
|
14
15
|
|
|
@@ -158,7 +159,8 @@ The following options properties can be provided to the Packr or Unpackr constru
|
|
|
158
159
|
|
|
159
160
|
* `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.
|
|
160
161
|
* `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).
|
|
161
|
-
* `
|
|
162
|
+
* `moreTypes` - Enable serialization of additional built-in types/classes including typed arrays, `Set`s, `Map`s, and `Error`s.
|
|
163
|
+
* `structuredClone` - This enables the structured cloning extensions that will encode object/cyclic references. `moreTypes` is enabled by default when this is enabled.
|
|
162
164
|
* `mapsAsObjects` - If `true`, this will decode MessagePack maps and JS `Object`s with the map entries decoded to object properties. If `false`, maps are decoded as JavaScript `Map`s. This is disabled by default if `useRecords` is enabled (which allows `Map`s to be preserved), and is enabled by default if `useRecords` is disabled.
|
|
163
165
|
* `useFloat32` - This will enable msgpackr to encode non-integer numbers as `float32`. See next section for possible values.
|
|
164
166
|
* `variableMapSize` - This will use varying map size definition (fixmap, map16, map32) based on the number of keys when encoding objects, which yields slightly more compact encodings (for small objects), but is typically 5-10% slower during encoding. This is necessary if you need to use objects with more than 65535 keys. This is only relevant when record extension is disabled.
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,13 @@
|
|
|
28
28
|
const C1 = new C1Type();
|
|
29
29
|
C1.name = 'MessagePack 0xC1';
|
|
30
30
|
var sequentialMode = false;
|
|
31
|
+
var inlineObjectReadThreshold = 2;
|
|
32
|
+
try {
|
|
33
|
+
new Function('');
|
|
34
|
+
} catch(error) {
|
|
35
|
+
// if eval variants are not supported, do not create inline object readers ever
|
|
36
|
+
inlineObjectReadThreshold = Infinity;
|
|
37
|
+
}
|
|
31
38
|
|
|
32
39
|
class Unpackr {
|
|
33
40
|
constructor(options) {
|
|
@@ -152,6 +159,9 @@
|
|
|
152
159
|
currentStructures.length = sharedLength;
|
|
153
160
|
}
|
|
154
161
|
let result = read();
|
|
162
|
+
if (bundledStrings) // bundled strings to skip past
|
|
163
|
+
position = bundledStrings.postBundlePosition;
|
|
164
|
+
|
|
155
165
|
if (position == srcEnd) {
|
|
156
166
|
// finished reading this source, cleanup references
|
|
157
167
|
if (currentStructures.restoreStructures)
|
|
@@ -433,7 +443,7 @@
|
|
|
433
443
|
function createStructureReader(structure, firstId) {
|
|
434
444
|
function readObject() {
|
|
435
445
|
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
|
436
|
-
if (readObject.count++ >
|
|
446
|
+
if (readObject.count++ > inlineObjectReadThreshold) {
|
|
437
447
|
let readObject = structure.read = (new Function('r', 'return function(){return {' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '}}'))(read);
|
|
438
448
|
if (structure.highByte === 0)
|
|
439
449
|
structure.read = createSecondByteReader(firstId, structure.read);
|
|
@@ -715,6 +725,36 @@
|
|
|
715
725
|
}
|
|
716
726
|
}
|
|
717
727
|
|
|
728
|
+
function readOnlyJSString() {
|
|
729
|
+
let token = src[position++];
|
|
730
|
+
let length;
|
|
731
|
+
if (token < 0xc0) {
|
|
732
|
+
// fixstr
|
|
733
|
+
length = token - 0xa0;
|
|
734
|
+
} else {
|
|
735
|
+
switch(token) {
|
|
736
|
+
case 0xd9:
|
|
737
|
+
// str 8
|
|
738
|
+
length = src[position++];
|
|
739
|
+
break
|
|
740
|
+
case 0xda:
|
|
741
|
+
// str 16
|
|
742
|
+
length = dataView.getUint16(position);
|
|
743
|
+
position += 2;
|
|
744
|
+
break
|
|
745
|
+
case 0xdb:
|
|
746
|
+
// str 32
|
|
747
|
+
length = dataView.getUint32(position);
|
|
748
|
+
position += 4;
|
|
749
|
+
break
|
|
750
|
+
default:
|
|
751
|
+
throw new Error('Expected string')
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return readStringJS(length)
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
|
|
718
758
|
function readBin(length) {
|
|
719
759
|
return currentUnpackr.copyBuffers ?
|
|
720
760
|
// specifically use the copying slice (not the node one)
|
|
@@ -866,21 +906,18 @@
|
|
|
866
906
|
let data = read();
|
|
867
907
|
return new RegExp(data[0], data[1])
|
|
868
908
|
};
|
|
869
|
-
|
|
909
|
+
const TEMP_BUNDLE = [];
|
|
870
910
|
currentExtensions[0x62] = (data) => {
|
|
871
911
|
let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
|
|
872
912
|
let dataPosition = position;
|
|
873
|
-
position += dataSize -
|
|
874
|
-
bundledStrings =
|
|
913
|
+
position += dataSize - data.length;
|
|
914
|
+
bundledStrings = TEMP_BUNDLE;
|
|
915
|
+
bundledStrings = [readOnlyJSString(), readOnlyJSString()];
|
|
875
916
|
bundledStrings.position0 = 0;
|
|
876
917
|
bundledStrings.position1 = 0;
|
|
877
|
-
|
|
918
|
+
bundledStrings.postBundlePosition = position;
|
|
878
919
|
position = dataPosition;
|
|
879
|
-
|
|
880
|
-
return read()
|
|
881
|
-
} finally {
|
|
882
|
-
position = postBundlePosition;
|
|
883
|
-
}
|
|
920
|
+
return read()
|
|
884
921
|
};
|
|
885
922
|
|
|
886
923
|
currentExtensions[0xff] = (data) => {
|
|
@@ -977,11 +1014,12 @@
|
|
|
977
1014
|
const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array;
|
|
978
1015
|
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
979
1016
|
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
980
|
-
let target;
|
|
1017
|
+
let target, keysTarget;
|
|
981
1018
|
let targetView;
|
|
982
1019
|
let position$1 = 0;
|
|
983
1020
|
let safeEnd;
|
|
984
1021
|
let bundledStrings$1 = null;
|
|
1022
|
+
const MAX_BUNDLE_SIZE = 0xf000;
|
|
985
1023
|
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
986
1024
|
const RECORD_SYMBOL = Symbol('record-id');
|
|
987
1025
|
class Packr extends Unpackr {
|
|
@@ -989,7 +1027,6 @@
|
|
|
989
1027
|
super(options);
|
|
990
1028
|
this.offset = 0;
|
|
991
1029
|
let start;
|
|
992
|
-
let sharedStructures;
|
|
993
1030
|
let hasSharedUpdate;
|
|
994
1031
|
let structures;
|
|
995
1032
|
let referenceMap;
|
|
@@ -1011,10 +1048,13 @@
|
|
|
1011
1048
|
maxSharedStructures = hasSharedStructures ? 32 : 0;
|
|
1012
1049
|
if (maxSharedStructures > 8160)
|
|
1013
1050
|
throw new Error('Maximum maxSharedStructure is 8160')
|
|
1051
|
+
if (options.structuredClone && options.moreTypes == undefined) {
|
|
1052
|
+
options.moreTypes = true;
|
|
1053
|
+
}
|
|
1014
1054
|
let maxOwnStructures = options.maxOwnStructures;
|
|
1015
1055
|
if (maxOwnStructures == null)
|
|
1016
1056
|
maxOwnStructures = hasSharedStructures ? 32 : 64;
|
|
1017
|
-
if (
|
|
1057
|
+
if (!this.structures && options.useRecords != false)
|
|
1018
1058
|
this.structures = [];
|
|
1019
1059
|
// two byte record ids for shared structures
|
|
1020
1060
|
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
|
|
@@ -1044,31 +1084,28 @@
|
|
|
1044
1084
|
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1045
1085
|
start = position$1;
|
|
1046
1086
|
referenceMap = packr.structuredClone ? new Map() : null;
|
|
1047
|
-
if (packr.bundleStrings) {
|
|
1048
|
-
bundledStrings$1 = [
|
|
1049
|
-
|
|
1050
|
-
target[position$1++] = 0x62; // 'b'
|
|
1051
|
-
bundledStrings$1.position = position$1 - start;
|
|
1052
|
-
position$1 += 4;
|
|
1087
|
+
if (packr.bundleStrings && typeof value !== 'string') {
|
|
1088
|
+
bundledStrings$1 = [];
|
|
1089
|
+
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1053
1090
|
} else
|
|
1054
1091
|
bundledStrings$1 = null;
|
|
1055
|
-
|
|
1056
|
-
if (
|
|
1057
|
-
if (
|
|
1058
|
-
|
|
1059
|
-
let sharedLength =
|
|
1092
|
+
structures = packr.structures;
|
|
1093
|
+
if (structures) {
|
|
1094
|
+
if (structures.uninitialized)
|
|
1095
|
+
structures = packr._mergeStructures(packr.getStructures());
|
|
1096
|
+
let sharedLength = structures.sharedLength || 0;
|
|
1060
1097
|
if (sharedLength > maxSharedStructures) {
|
|
1061
|
-
//if (maxSharedStructures <= 32 &&
|
|
1062
|
-
throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' +
|
|
1098
|
+
//if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
|
|
1099
|
+
throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
|
|
1063
1100
|
}
|
|
1064
|
-
if (!
|
|
1101
|
+
if (!structures.transitions) {
|
|
1065
1102
|
// rebuild our structure transitions
|
|
1066
|
-
|
|
1103
|
+
structures.transitions = Object.create(null);
|
|
1067
1104
|
for (let i = 0; i < sharedLength; i++) {
|
|
1068
|
-
let keys =
|
|
1105
|
+
let keys = structures[i];
|
|
1069
1106
|
if (!keys)
|
|
1070
1107
|
continue
|
|
1071
|
-
let nextTransition, transition =
|
|
1108
|
+
let nextTransition, transition = structures.transitions;
|
|
1072
1109
|
for (let j = 0, l = keys.length; j < l; j++) {
|
|
1073
1110
|
let key = keys[j];
|
|
1074
1111
|
nextTransition = transition[key];
|
|
@@ -1082,20 +1119,15 @@
|
|
|
1082
1119
|
lastSharedStructuresLength = sharedLength;
|
|
1083
1120
|
}
|
|
1084
1121
|
if (!isSequential) {
|
|
1085
|
-
|
|
1122
|
+
structures.nextId = sharedLength + 0x40;
|
|
1086
1123
|
}
|
|
1087
1124
|
}
|
|
1088
1125
|
if (hasSharedUpdate)
|
|
1089
1126
|
hasSharedUpdate = false;
|
|
1090
|
-
structures = sharedStructures || [];
|
|
1091
1127
|
try {
|
|
1092
1128
|
pack(value);
|
|
1093
1129
|
if (bundledStrings$1) {
|
|
1094
|
-
|
|
1095
|
-
let writeStrings = bundledStrings$1;
|
|
1096
|
-
bundledStrings$1 = null;
|
|
1097
|
-
pack(writeStrings[0]);
|
|
1098
|
-
pack(writeStrings[1]);
|
|
1130
|
+
writeBundles(start, pack);
|
|
1099
1131
|
}
|
|
1100
1132
|
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1101
1133
|
if (referenceMap && referenceMap.idsToInsert) {
|
|
@@ -1114,12 +1146,15 @@
|
|
|
1114
1146
|
}
|
|
1115
1147
|
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1116
1148
|
} finally {
|
|
1117
|
-
if (
|
|
1149
|
+
if (structures) {
|
|
1118
1150
|
if (serializationsSinceTransitionRebuild < 10)
|
|
1119
1151
|
serializationsSinceTransitionRebuild++;
|
|
1152
|
+
let sharedLength = structures.sharedLength || maxSharedStructures;
|
|
1153
|
+
if (structures.length > sharedLength)
|
|
1154
|
+
structures.length = sharedLength;
|
|
1120
1155
|
if (transitionsCount > 10000) {
|
|
1121
1156
|
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1122
|
-
|
|
1157
|
+
structures.transitions = null;
|
|
1123
1158
|
serializationsSinceTransitionRebuild = 0;
|
|
1124
1159
|
transitionsCount = 0;
|
|
1125
1160
|
if (recordIdsToRemove.length > 0)
|
|
@@ -1131,13 +1166,9 @@
|
|
|
1131
1166
|
recordIdsToRemove = [];
|
|
1132
1167
|
}
|
|
1133
1168
|
if (hasSharedUpdate && packr.saveStructures) {
|
|
1134
|
-
let sharedLength = sharedStructures.sharedLength || maxSharedStructures;
|
|
1135
|
-
if (sharedStructures.length > sharedLength) {
|
|
1136
|
-
sharedStructures = sharedStructures.slice(0, sharedLength);
|
|
1137
|
-
}
|
|
1138
1169
|
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1139
1170
|
let returnBuffer = target.subarray(start, position$1);
|
|
1140
|
-
if (packr.saveStructures(
|
|
1171
|
+
if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
|
|
1141
1172
|
// get updated structures and try again if the update failed
|
|
1142
1173
|
packr._mergeStructures(packr.getStructures());
|
|
1143
1174
|
return packr.pack(value)
|
|
@@ -1158,7 +1189,30 @@
|
|
|
1158
1189
|
var length;
|
|
1159
1190
|
if (type === 'string') {
|
|
1160
1191
|
let strLength = value.length;
|
|
1161
|
-
if (bundledStrings$1 && strLength >=
|
|
1192
|
+
if (bundledStrings$1 && strLength >= 4 && strLength < 0x1000) {
|
|
1193
|
+
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1194
|
+
let extStart;
|
|
1195
|
+
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1196
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1197
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1198
|
+
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
|
|
1199
|
+
target[position$1] = 0xc8; // ext 16
|
|
1200
|
+
position$1 += 3; // reserve for the writing bundle size
|
|
1201
|
+
target[position$1++] = 0x62; // 'b'
|
|
1202
|
+
extStart = position$1 - start;
|
|
1203
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1204
|
+
writeBundles(start, pack); // write the last bundles
|
|
1205
|
+
targetView.setUint16(extStart + start - 3, position$1 - start - extStart);
|
|
1206
|
+
} 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)
|
|
1207
|
+
target[position$1++] = 0xd6; // fixext 4
|
|
1208
|
+
target[position$1++] = 0x62; // 'b'
|
|
1209
|
+
extStart = position$1 - start;
|
|
1210
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1211
|
+
}
|
|
1212
|
+
bundledStrings$1 = ['', '']; // create new ones
|
|
1213
|
+
bundledStrings$1.size = 0;
|
|
1214
|
+
bundledStrings$1.position = extStart;
|
|
1215
|
+
}
|
|
1162
1216
|
let twoByte = hasNonLatin.test(value);
|
|
1163
1217
|
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1164
1218
|
target[position$1++] = 0xc1;
|
|
@@ -1463,53 +1517,55 @@
|
|
|
1463
1517
|
target[objectOffset++ + start] = size >> 8;
|
|
1464
1518
|
target[objectOffset + start] = size & 0xff;
|
|
1465
1519
|
} :
|
|
1466
|
-
|
|
1467
|
-
/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
|
|
1520
|
+
(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)
|
|
1468
1521
|
(object, safePrototype) => {
|
|
1469
|
-
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
1470
|
-
let objectOffset = position++ - start
|
|
1471
|
-
let wroteKeys
|
|
1522
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1523
|
+
let objectOffset = position$1++ - start;
|
|
1524
|
+
let wroteKeys;
|
|
1472
1525
|
for (let key in object) {
|
|
1473
1526
|
if (safePrototype || object.hasOwnProperty(key)) {
|
|
1474
|
-
nextTransition = transition[key]
|
|
1475
|
-
if (
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
let
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
nextTransition
|
|
1527
|
+
nextTransition = transition[key];
|
|
1528
|
+
if (nextTransition)
|
|
1529
|
+
transition = nextTransition;
|
|
1530
|
+
else {
|
|
1531
|
+
// record doesn't exist, create full new record and insert it
|
|
1532
|
+
let keys = Object.keys(object);
|
|
1533
|
+
let lastTransition = transition;
|
|
1534
|
+
transition = structures.transitions;
|
|
1535
|
+
let newTransitions = 0;
|
|
1536
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1537
|
+
let key = keys[i];
|
|
1538
|
+
nextTransition = transition[key];
|
|
1539
|
+
if (!nextTransition) {
|
|
1540
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1541
|
+
newTransitions++;
|
|
1488
1542
|
}
|
|
1543
|
+
transition = nextTransition;
|
|
1489
1544
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1545
|
+
if (objectOffset + start + 1 == position$1) {
|
|
1546
|
+
// first key, so we don't need to insert, we can just write record directly
|
|
1547
|
+
position$1--;
|
|
1548
|
+
newRecord(transition, keys, newTransitions);
|
|
1549
|
+
} else // otherwise we need to insert the record, moving existing data after the record
|
|
1550
|
+
insertNewRecord(transition, keys, objectOffset, newTransitions);
|
|
1551
|
+
wroteKeys = true;
|
|
1552
|
+
transition = lastTransition[key];
|
|
1494
1553
|
}
|
|
1495
|
-
|
|
1496
|
-
pack(object[key])
|
|
1554
|
+
pack(object[key]);
|
|
1497
1555
|
}
|
|
1498
1556
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1557
|
+
if (!wroteKeys) {
|
|
1558
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1559
|
+
if (recordId)
|
|
1560
|
+
target[objectOffset + start] = recordId;
|
|
1561
|
+
else
|
|
1562
|
+
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1504
1563
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
(object) => {
|
|
1508
|
-
let keys = Object.keys(object);
|
|
1564
|
+
} :
|
|
1565
|
+
(object, safePrototype) => {
|
|
1509
1566
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1510
1567
|
let newTransitions = 0;
|
|
1511
|
-
for (let
|
|
1512
|
-
let key = keys[i];
|
|
1568
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1513
1569
|
nextTransition = transition[key];
|
|
1514
1570
|
if (!nextTransition) {
|
|
1515
1571
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -1525,57 +1581,12 @@
|
|
|
1525
1581
|
} else
|
|
1526
1582
|
target[position$1++] = recordId;
|
|
1527
1583
|
} else {
|
|
1528
|
-
|
|
1529
|
-
if (!recordId)
|
|
1530
|
-
recordId = 0x40;
|
|
1531
|
-
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1532
|
-
recordId = structures.nextOwnId;
|
|
1533
|
-
if (!(recordId < maxStructureId))
|
|
1534
|
-
recordId = sharedLimitId;
|
|
1535
|
-
structures.nextOwnId = recordId + 1;
|
|
1536
|
-
} else {
|
|
1537
|
-
if (recordId >= maxStructureId)// cycle back around
|
|
1538
|
-
recordId = sharedLimitId;
|
|
1539
|
-
structures.nextId = recordId + 1;
|
|
1540
|
-
}
|
|
1541
|
-
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1542
|
-
transition[RECORD_SYMBOL] = recordId;
|
|
1543
|
-
structures[recordId - 0x40] = keys;
|
|
1544
|
-
|
|
1545
|
-
if (recordId < sharedLimitId) {
|
|
1546
|
-
keys.isShared = true;
|
|
1547
|
-
structures.sharedLength = recordId - 0x3f;
|
|
1548
|
-
hasSharedUpdate = true;
|
|
1549
|
-
if (highByte >= 0) {
|
|
1550
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1551
|
-
target[position$1++] = highByte;
|
|
1552
|
-
} else {
|
|
1553
|
-
target[position$1++] = recordId;
|
|
1554
|
-
}
|
|
1555
|
-
} else {
|
|
1556
|
-
if (highByte >= 0) {
|
|
1557
|
-
target[position$1++] = 0xd5; // fixext 2
|
|
1558
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1559
|
-
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1560
|
-
target[position$1++] = highByte;
|
|
1561
|
-
} else {
|
|
1562
|
-
target[position$1++] = 0xd4; // fixext 1
|
|
1563
|
-
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1564
|
-
target[position$1++] = recordId;
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
if (newTransitions)
|
|
1568
|
-
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1569
|
-
// record the removal of the id, we can maintain our shared structure
|
|
1570
|
-
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1571
|
-
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1572
|
-
recordIdsToRemove.push(transition);
|
|
1573
|
-
pack(keys);
|
|
1574
|
-
}
|
|
1584
|
+
newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions);
|
|
1575
1585
|
}
|
|
1576
1586
|
// now write the values
|
|
1577
|
-
for (let
|
|
1578
|
-
|
|
1587
|
+
for (let key in object)
|
|
1588
|
+
if (safePrototype || object.hasOwnProperty(key))
|
|
1589
|
+
pack(object[key]);
|
|
1579
1590
|
};
|
|
1580
1591
|
const makeRoom = (end) => {
|
|
1581
1592
|
let newSize;
|
|
@@ -1598,6 +1609,86 @@
|
|
|
1598
1609
|
safeEnd = newBuffer.length - 10;
|
|
1599
1610
|
return target = newBuffer
|
|
1600
1611
|
};
|
|
1612
|
+
const newRecord = (transition, keys, newTransitions) => {
|
|
1613
|
+
let recordId = structures.nextId;
|
|
1614
|
+
if (!recordId)
|
|
1615
|
+
recordId = 0x40;
|
|
1616
|
+
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1617
|
+
recordId = structures.nextOwnId;
|
|
1618
|
+
if (!(recordId < maxStructureId))
|
|
1619
|
+
recordId = sharedLimitId;
|
|
1620
|
+
structures.nextOwnId = recordId + 1;
|
|
1621
|
+
} else {
|
|
1622
|
+
if (recordId >= maxStructureId)// cycle back around
|
|
1623
|
+
recordId = sharedLimitId;
|
|
1624
|
+
structures.nextId = recordId + 1;
|
|
1625
|
+
}
|
|
1626
|
+
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1627
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1628
|
+
transition.__keys__ = keys;
|
|
1629
|
+
structures[recordId - 0x40] = keys;
|
|
1630
|
+
|
|
1631
|
+
if (recordId < sharedLimitId) {
|
|
1632
|
+
keys.isShared = true;
|
|
1633
|
+
structures.sharedLength = recordId - 0x3f;
|
|
1634
|
+
hasSharedUpdate = true;
|
|
1635
|
+
if (highByte >= 0) {
|
|
1636
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1637
|
+
target[position$1++] = highByte;
|
|
1638
|
+
} else {
|
|
1639
|
+
target[position$1++] = recordId;
|
|
1640
|
+
}
|
|
1641
|
+
} else {
|
|
1642
|
+
if (highByte >= 0) {
|
|
1643
|
+
target[position$1++] = 0xd5; // fixext 2
|
|
1644
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1645
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1646
|
+
target[position$1++] = highByte;
|
|
1647
|
+
} else {
|
|
1648
|
+
target[position$1++] = 0xd4; // fixext 1
|
|
1649
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1650
|
+
target[position$1++] = recordId;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
if (newTransitions)
|
|
1654
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1655
|
+
// record the removal of the id, we can maintain our shared structure
|
|
1656
|
+
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1657
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1658
|
+
recordIdsToRemove.push(transition);
|
|
1659
|
+
pack(keys);
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
|
|
1663
|
+
let mainTarget = target;
|
|
1664
|
+
let mainPosition = position$1;
|
|
1665
|
+
let mainSafeEnd = safeEnd;
|
|
1666
|
+
let mainStart = start;
|
|
1667
|
+
target = keysTarget;
|
|
1668
|
+
position$1 = 0;
|
|
1669
|
+
start = 0;
|
|
1670
|
+
if (!target)
|
|
1671
|
+
keysTarget = target = new ByteArrayAllocate(8192);
|
|
1672
|
+
safeEnd = target.length - 10;
|
|
1673
|
+
newRecord(transition, keys, newTransitions);
|
|
1674
|
+
keysTarget = target;
|
|
1675
|
+
let keysPosition = position$1;
|
|
1676
|
+
target = mainTarget;
|
|
1677
|
+
position$1 = mainPosition;
|
|
1678
|
+
safeEnd = mainSafeEnd;
|
|
1679
|
+
start = mainStart;
|
|
1680
|
+
if (keysPosition > 1) {
|
|
1681
|
+
let newEnd = position$1 + keysPosition - 1;
|
|
1682
|
+
if (newEnd > safeEnd)
|
|
1683
|
+
makeRoom(newEnd);
|
|
1684
|
+
let insertionPosition = insertionOffset + start;
|
|
1685
|
+
target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position$1);
|
|
1686
|
+
target.set(keysTarget.slice(0, keysPosition), insertionPosition);
|
|
1687
|
+
position$1 = newEnd;
|
|
1688
|
+
} else {
|
|
1689
|
+
target[insertionOffset + start] = keysTarget[0];
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1601
1692
|
}
|
|
1602
1693
|
useBuffer(buffer) {
|
|
1603
1694
|
// this means we are finished using our own buffer and we can write over it safely
|
|
@@ -1605,6 +1696,10 @@
|
|
|
1605
1696
|
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1606
1697
|
position$1 = 0;
|
|
1607
1698
|
}
|
|
1699
|
+
clearSharedData() {
|
|
1700
|
+
if (this.structures)
|
|
1701
|
+
this.structures = [];
|
|
1702
|
+
}
|
|
1608
1703
|
}
|
|
1609
1704
|
|
|
1610
1705
|
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
|
|
@@ -1647,8 +1742,8 @@
|
|
|
1647
1742
|
}, {
|
|
1648
1743
|
pack(set, allocateForWrite, pack) {
|
|
1649
1744
|
let array = Array.from(set);
|
|
1650
|
-
let { target, position} = allocateForWrite(this.
|
|
1651
|
-
if (this.
|
|
1745
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1746
|
+
if (this.moreTypes) {
|
|
1652
1747
|
target[position++] = 0xd4;
|
|
1653
1748
|
target[position++] = 0x73; // 's' for Set
|
|
1654
1749
|
target[position++] = 0;
|
|
@@ -1657,8 +1752,8 @@
|
|
|
1657
1752
|
}
|
|
1658
1753
|
}, {
|
|
1659
1754
|
pack(error, allocateForWrite, pack) {
|
|
1660
|
-
let { target, position} = allocateForWrite(this.
|
|
1661
|
-
if (this.
|
|
1755
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1756
|
+
if (this.moreTypes) {
|
|
1662
1757
|
target[position++] = 0xd4;
|
|
1663
1758
|
target[position++] = 0x65; // 'e' for error
|
|
1664
1759
|
target[position++] = 0;
|
|
@@ -1667,8 +1762,8 @@
|
|
|
1667
1762
|
}
|
|
1668
1763
|
}, {
|
|
1669
1764
|
pack(regex, allocateForWrite, pack) {
|
|
1670
|
-
let { target, position} = allocateForWrite(this.
|
|
1671
|
-
if (this.
|
|
1765
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1766
|
+
if (this.moreTypes) {
|
|
1672
1767
|
target[position++] = 0xd4;
|
|
1673
1768
|
target[position++] = 0x78; // 'x' for regeXp
|
|
1674
1769
|
target[position++] = 0;
|
|
@@ -1677,7 +1772,7 @@
|
|
|
1677
1772
|
}
|
|
1678
1773
|
}, {
|
|
1679
1774
|
pack(arrayBuffer, allocateForWrite) {
|
|
1680
|
-
if (this.
|
|
1775
|
+
if (this.moreTypes)
|
|
1681
1776
|
writeExtBuffer(arrayBuffer, 0x10, allocateForWrite);
|
|
1682
1777
|
else
|
|
1683
1778
|
writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
|
|
@@ -1685,7 +1780,7 @@
|
|
|
1685
1780
|
}, {
|
|
1686
1781
|
pack(typedArray, allocateForWrite) {
|
|
1687
1782
|
let constructor = typedArray.constructor;
|
|
1688
|
-
if (constructor !== ByteArray && this.
|
|
1783
|
+
if (constructor !== ByteArray && this.moreTypes)
|
|
1689
1784
|
writeExtBuffer(typedArray, typedArrays.indexOf(constructor.name), allocateForWrite);
|
|
1690
1785
|
else
|
|
1691
1786
|
writeBuffer(typedArray, allocateForWrite);
|
|
@@ -1802,6 +1897,14 @@
|
|
|
1802
1897
|
return serialized
|
|
1803
1898
|
}
|
|
1804
1899
|
|
|
1900
|
+
function writeBundles(start, pack) {
|
|
1901
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
|
|
1902
|
+
let writeStrings = bundledStrings$1;
|
|
1903
|
+
bundledStrings$1 = null;
|
|
1904
|
+
pack(writeStrings[0]);
|
|
1905
|
+
pack(writeStrings[1]);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1805
1908
|
function addExtension$1(extension) {
|
|
1806
1909
|
if (extension.Class) {
|
|
1807
1910
|
if (!extension.pack && !extension.write)
|