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/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++ > 2) {
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 - 4;
917
- bundledStrings = [read(), read()];
958
+ position += dataSize - data.length;
959
+ bundledStrings = TEMP_BUNDLE;
960
+ bundledStrings = [readOnlyJSString(), readOnlyJSString()];
918
961
  bundledStrings.position0 = 0;
919
962
  bundledStrings.position1 = 0;
920
- let postBundlePosition = position;
963
+ bundledStrings.postBundlePosition = position;
921
964
  position = dataPosition;
922
- try {
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 (isSequential && !options.saveStructures)
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
- target[position$1++] = 0xd6;
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
- sharedStructures = packr.structures;
1103
- if (sharedStructures) {
1104
- if (sharedStructures.uninitialized)
1105
- sharedStructures = packr._mergeStructures(packr.getStructures());
1106
- let sharedLength = sharedStructures.sharedLength || 0;
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 && sharedStructures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
1109
- throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + sharedStructures.sharedLength)
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 (!sharedStructures.transitions) {
1150
+ if (!structures.transitions) {
1112
1151
  // rebuild our structure transitions
1113
- sharedStructures.transitions = Object.create(null);
1152
+ structures.transitions = Object.create(null);
1114
1153
  for (let i = 0; i < sharedLength; i++) {
1115
- let keys = sharedStructures[i];
1154
+ let keys = structures[i];
1116
1155
  if (!keys)
1117
1156
  continue
1118
- let nextTransition, transition = sharedStructures.transitions;
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
- sharedStructures.nextId = sharedLength + 0x40;
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
- targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
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 (sharedStructures) {
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
- sharedStructures.transitions = null;
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(sharedStructures, lastSharedStructuresLength) === false) {
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 >= 8 && strLength < 0x1000) {
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 (!nextTransition) {
1523
- nextTransition = transition[key] = Object.create(null)
1524
- nextTransition.__keys__ = (transition.__keys__ || []).concat([key])
1525
- /*let keys = Object.keys(object)
1526
- if
1527
- let size = 0
1528
- let startBranch = transition.__keys__ ? transition.__keys__.length : 0
1529
- for (let i = 0, l = keys.length; i++) {
1530
- let key = keys[i]
1531
- size += key.length << 2
1532
- if (i >= startBranch) {
1533
- nextTransition = nextTransition[key] = Object.create(null)
1534
- nextTransition.__keys__ = keys.slice(0, i + 1)
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
- makeRoom(position + size)
1538
- nextTransition = transition[key]
1539
- target.copy(target, )
1540
- objectOffset
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
- transition = nextTransition
1543
- pack(object[key])
1603
+ pack(object[key]);
1544
1604
  }
1545
1605
  }
1546
- let id = transition.id
1547
- if (!id) {
1548
- id = transition.id = structures.push(transition.__keys__) + 63
1549
- if (sharedStructures.onUpdate)
1550
- sharedStructures.onUpdate(id, transition.__keys__)
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
- target[objectOffset + start] = id
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 i = 0, l = keys.length; i < l; i++) {
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
- recordId = structures.nextId;
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 i = 0, l = keys.length; i < l; i++)
1625
- pack(object[keys[i]]);
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.structuredClone ? 3 : 0);
1698
- if (this.structuredClone) {
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.structuredClone ? 3 : 0);
1708
- if (this.structuredClone) {
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.structuredClone ? 3 : 0);
1718
- if (this.structuredClone) {
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.structuredClone)
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.structuredClone)
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 structures = [];
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);