msgpackr 1.7.0-alpha1 → 1.7.0-alpha4

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/test.js CHANGED
@@ -1,7 +1,8 @@
1
- (function (msgpackr, chai, fs) {
1
+ (function (msgpackr, chai, inspector, fs) {
2
2
  'use strict';
3
3
 
4
4
  chai = chai && Object.prototype.hasOwnProperty.call(chai, 'default') ? chai['default'] : chai;
5
+ inspector = inspector && Object.prototype.hasOwnProperty.call(inspector, 'default') ? inspector['default'] : inspector;
5
6
 
6
7
  var decoder;
7
8
  try {
@@ -28,7 +29,7 @@
28
29
  C1.name = 'MessagePack 0xC1';
29
30
  var sequentialMode = false;
30
31
  var inlineObjectReadThreshold = 2;
31
- var readStruct;
32
+ var readStruct, onLoadedStructures;
32
33
  try {
33
34
  new Function('');
34
35
  } catch(error) {
@@ -58,16 +59,21 @@
58
59
  }
59
60
  Object.assign(this, options);
60
61
  }
61
- unpack(source, end) {
62
+ unpack(source, options) {
62
63
  if (src) {
63
64
  // re-entrant execution, save the state and restore it after we do this unpack
64
65
  return saveState(() => {
65
66
  clearSource();
66
- return this ? this.unpack(source, end) : Unpackr.prototype.unpack.call(defaultOptions, source, end)
67
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
67
68
  })
68
69
  }
69
- srcEnd = end > -1 ? end : source.length;
70
- position = 0;
70
+ if (typeof options === 'object') {
71
+ srcEnd = options.end || source.length;
72
+ position = options.start || 0;
73
+ } else {
74
+ position = 0;
75
+ srcEnd = options > -1 ? options : source.length;
76
+ }
71
77
  srcStringEnd = 0;
72
78
  srcString = null;
73
79
  bundledStrings = null;
@@ -132,7 +138,11 @@
132
138
  }
133
139
  }
134
140
  _mergeStructures(loadedStructures, existingStructures) {
141
+ if (onLoadedStructures)
142
+ loadedStructures = onLoadedStructures.call(this, loadedStructures);
135
143
  loadedStructures = loadedStructures || [];
144
+ if (Object.isFrozen(loadedStructures))
145
+ loadedStructures = loadedStructures.map(structure => structure.slice(0));
136
146
  for (let i = 0, l = loadedStructures.length; i < l; i++) {
137
147
  let structure = loadedStructures[i];
138
148
  if (structure) {
@@ -167,9 +177,8 @@
167
177
  currentStructures.length = sharedLength;
168
178
  }
169
179
  let result;
170
- if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && readStruct) {
171
- let id = (src[position++] << 8) + src[position++];
172
- result = readStruct(src, position, srcEnd, currentStructures[id - 0x40] || loadStructures()[id - 0x40], currentUnpackr);
180
+ if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
181
+ result = readStruct(src, position, srcEnd, currentUnpackr);
173
182
  position = srcEnd;
174
183
  } else
175
184
  result = read();
@@ -565,6 +574,16 @@
565
574
 
566
575
  return result
567
576
  }
577
+ function readString(source, start, length) {
578
+ let existingSrc = src;
579
+ src = source;
580
+ position = start;
581
+ try {
582
+ return readStringJS(length);
583
+ } finally {
584
+ src = existingSrc;
585
+ }
586
+ }
568
587
 
569
588
  function readArray(length) {
570
589
  let array = new Array(length);
@@ -785,7 +804,15 @@
785
804
  function readExt(length) {
786
805
  let type = src[position++];
787
806
  if (currentExtensions[type]) {
788
- return currentExtensions[type](src.subarray(position, position += length))
807
+ let end;
808
+ return currentExtensions[type](src.subarray(position, end = (position += length)), (readPosition) => {
809
+ position = readPosition;
810
+ try {
811
+ return read();
812
+ } finally {
813
+ position = end;
814
+ }
815
+ })
789
816
  }
790
817
  else
791
818
  throw new Error('Unknown extension type ' + type)
@@ -1000,8 +1027,9 @@
1000
1027
  mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
1001
1028
  }
1002
1029
  var defaultUnpackr = new Unpackr({ useRecords: false });
1003
- function setReadStruct(func) {
1004
- readStruct = func;
1030
+ function setReadStruct(updatedReadStruct, loadedStructs) {
1031
+ readStruct = updatedReadStruct;
1032
+ onLoadedStructures = loadedStructs;
1005
1033
  }
1006
1034
 
1007
1035
  let textEncoder;
@@ -1031,7 +1059,6 @@
1031
1059
  let hasSharedUpdate;
1032
1060
  let structures;
1033
1061
  let referenceMap;
1034
- let lastSharedStructuresLength = 0;
1035
1062
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1036
1063
  return target.utf8Write(string, position, 0xffffffff)
1037
1064
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -1117,7 +1144,7 @@
1117
1144
  }
1118
1145
  transition[RECORD_SYMBOL] = i + 0x40;
1119
1146
  }
1120
- lastSharedStructuresLength = sharedLength;
1147
+ this.lastNamedStructuresLength = sharedLength;
1121
1148
  }
1122
1149
  if (!isSequential) {
1123
1150
  structures.nextId = sharedLength + 0x40;
@@ -1126,7 +1153,7 @@
1126
1153
  if (hasSharedUpdate)
1127
1154
  hasSharedUpdate = false;
1128
1155
  try {
1129
- if (packr.randomAccessStructure)
1156
+ if (packr.randomAccessStructure && value.constructor && value.constructor === Object)
1130
1157
  writeStruct(value);
1131
1158
  else
1132
1159
  pack(value);
@@ -1153,7 +1180,7 @@
1153
1180
  if (structures) {
1154
1181
  if (serializationsSinceTransitionRebuild < 10)
1155
1182
  serializationsSinceTransitionRebuild++;
1156
- let sharedLength = structures.sharedLength || maxSharedStructures;
1183
+ let sharedLength = structures.sharedLength || 0;
1157
1184
  if (structures.length > sharedLength)
1158
1185
  structures.length = sharedLength;
1159
1186
  if (transitionsCount > 10000) {
@@ -1172,12 +1199,12 @@
1172
1199
  if (hasSharedUpdate && packr.saveStructures) {
1173
1200
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1174
1201
  let returnBuffer = target.subarray(start, position$1);
1175
- if (packr.saveStructures(structures, lastSharedStructuresLength) === false) {
1202
+ let newSharedData = prepareStructures(structures, packr);
1203
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1176
1204
  // get updated structures and try again if the update failed
1177
- packr._mergeStructures(packr.getStructures());
1178
1205
  return packr.pack(value)
1179
1206
  }
1180
- lastSharedStructuresLength = sharedLength;
1207
+ packr.lastNamedStructuresLength = sharedLength;
1181
1208
  return returnBuffer
1182
1209
  }
1183
1210
  }
@@ -1295,7 +1322,7 @@
1295
1322
  } else if (type === 'number') {
1296
1323
  if (value >>> 0 === value) {// positive integer, 32-bit or less
1297
1324
  // positive uint
1298
- if (value < 0x40 || (value < 0x80 && this.useRecords === false)) {
1325
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
1299
1326
  target[position$1++] = value;
1300
1327
  } else if (value < 0x100) {
1301
1328
  target[position$1++] = 0xcc;
@@ -1695,16 +1722,18 @@
1695
1722
  }
1696
1723
  };
1697
1724
  const writeStruct = (object, safePrototype) => {
1698
- let newPosition = writeStructSlots(object, target, position$1, structures, makeRoom, (value, newPosition) => {
1725
+ let newPosition = writeStructSlots(object, target, position$1, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1726
+ if (notifySharedUpdate)
1727
+ return hasSharedUpdate = true;
1699
1728
  position$1 = newPosition;
1700
1729
  if (start > 0) {
1701
1730
  pack(value);
1702
1731
  if (start == 0)
1703
- return { position: position$1, targetView }; // indicate the buffer was re-allocated
1732
+ return { position: position$1, targetView, target }; // indicate the buffer was re-allocated
1704
1733
  } else
1705
1734
  pack(value);
1706
1735
  return position$1;
1707
- });
1736
+ }, this);
1708
1737
  if (newPosition === 0) // bail and go to a msgpack object
1709
1738
  return writeObject(object, true);
1710
1739
  position$1 = newPosition;
@@ -1719,6 +1748,8 @@
1719
1748
  clearSharedData() {
1720
1749
  if (this.structures)
1721
1750
  this.structures = [];
1751
+ if (this.typedStructs)
1752
+ this.typedStructs = [];
1722
1753
  }
1723
1754
  }
1724
1755
 
@@ -1926,159 +1957,459 @@
1926
1957
  pack(writeStrings[1]);
1927
1958
  }
1928
1959
  }
1929
- function setWriteStructSlots(func) {
1930
- writeStructSlots = func;
1960
+ function prepareStructures(structures, packr) {
1961
+ structures.isCompatible = (existingStructures) => {
1962
+ let compatible = !existingStructures || ((packr.lastNamedStructuresLength || 0) === existingStructures.length);
1963
+ if (!compatible) // we want to merge these existing structures immediately since we already have it and we are in the right transaction
1964
+ packr._mergeStructures(existingStructures);
1965
+ return compatible;
1966
+ };
1967
+ return structures
1968
+ }
1969
+ function setWriteStructSlots(writeSlots, makeStructures) {
1970
+ writeStructSlots = writeSlots;
1971
+ prepareStructures = makeStructures;
1931
1972
  }
1932
1973
 
1933
1974
  let defaultPackr = new Packr({ useRecords: false });
1934
1975
  const REUSE_BUFFER_MODE = 512;
1935
1976
  const RESET_BUFFER_MODE = 1024;
1936
1977
 
1937
- // first four bits
1938
- const hasNonLatin$1 = /[\u0080-\uFFFF]/;
1978
+ const ASCII = 3; // the MIBenum from https://www.iana.org/assignments/character-sets/character-sets.xhtml (and other character encodings could be referenced by MIBenum)
1979
+ const NUMBER = 0;
1980
+ const UTF8 = 2;
1981
+ const OBJECT_DATA = 1;
1982
+ const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
1939
1983
  const float32Headers = [false, true, true, false, false, true, true, false];
1940
- setWriteStructSlots(writeStruct);
1941
- function writeStruct(object, target, position, structures, makeRoom, pack) {
1942
- let transition = structures.transitions || false;
1943
- let start = position;
1944
- position += 4;
1945
- let queuedReferences = [];
1946
- let uint32 = target.uint32 || (target.uint32 = new Uint32Array(target.buffer));
1984
+ let updatedPosition;
1985
+ const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
1986
+ let textEncoder$1;
1987
+ try {
1988
+ textEncoder$1 = new TextEncoder();
1989
+ } catch (error) {}
1990
+ const encodeUtf8 = hasNodeBuffer$1 ? function(target, string, position) {
1991
+ return target.utf8Write(string, position, 0xffffffff)
1992
+ } : (textEncoder$1 && textEncoder$1.encodeInto) ?
1993
+ function(target, string, position) {
1994
+ return textEncoder$1.encodeInto(string, target.subarray(position)).written
1995
+ } : false;
1996
+ setWriteStructSlots(writeStruct, prepareStructures$1);
1997
+ function writeStruct(object, target, position, structures, makeRoom, pack, packr) {
1998
+ let typedStructs = packr.typedStructs || (packr.typedStructs = []);
1999
+ // note that we rely on pack.js to load stored structures before we get to this point
1947
2000
  let targetView = target.dataView;
1948
- let encoded;
1949
- let stringData = '';
2001
+ let refsStartPosition = (typedStructs.lastStringStart || 100) + position;
1950
2002
  let safeEnd = target.length - 10;
2003
+ let start = position;
2004
+ if (position > safeEnd) {
2005
+ let lastStart = start;
2006
+ target = makeRoom(position);
2007
+ targetView = target.dataView;
2008
+ position -= lastStart;
2009
+ refsStartPosition -= lastStart;
2010
+ start = 0;
2011
+ safeEnd = target.length - 10;
2012
+ }
2013
+
2014
+ let refOffset, refPosition = refsStartPosition;
2015
+
2016
+ let transition = typedStructs.transitions || (typedStructs.transitions = Object.create(null));
2017
+ let nextId = typedStructs.nextId || typedStructs.length;
2018
+ let headerSize =
2019
+ nextId < 0xf ? 1 :
2020
+ nextId < 0xf0 ? 2 :
2021
+ nextId < 0xf000 ? 3 :
2022
+ nextId < 0xf00000 ? 4 : 0;
2023
+ if (headerSize === 0)
2024
+ return 0;
2025
+ position += headerSize;
2026
+ let queuedReferences = [];
2027
+ let keyIndex = 0;
1951
2028
  for (let key in object) {
2029
+ let value = object[key];
1952
2030
  let nextTransition = transition[key];
1953
2031
  if (!nextTransition) {
1954
- return 0; // bail
1955
- //nextTransition = transition[key] = Object.create(null)
1956
- //newTransitions++
2032
+ transition[key] = nextTransition = {
2033
+ key,
2034
+ parent: transition,
2035
+ enumerationOffset: 0,
2036
+ ascii0: null,
2037
+ ascii8: null,
2038
+ num8: null,
2039
+ string16: null,
2040
+ object16: null,
2041
+ num32: null,
2042
+ float64: null
2043
+ };
1957
2044
  }
1958
2045
  if (position > safeEnd) {
1959
- let newPosition = position - start;
2046
+ let lastStart = start;
1960
2047
  target = makeRoom(position);
1961
- position = newPosition;
2048
+ targetView = target.dataView;
2049
+ position -= lastStart;
2050
+ refsStartPosition -= lastStart;
2051
+ refPosition -= lastStart;
1962
2052
  start = 0;
1963
2053
  safeEnd = target.length - 10;
1964
2054
  }
1965
- transition = nextTransition;
1966
- let value = object[key];
1967
2055
  switch (typeof value) {
1968
2056
  case 'number':
1969
- if (value >>> 0 === value && value < 0x20000000) {
1970
- encoded = value;
2057
+ let number = value;
2058
+ if (number >> 0 === number && number < 0x20000000 && number > -0x1f000000) {
2059
+ if (number < 0xf6 && number >= 0 && (nextTransition.num8 || number < 0x20 && !nextTransition.num32)) {
2060
+ transition = nextTransition.num8 || createTypeTransition(nextTransition, NUMBER, 1);
2061
+ target[position++] = number;
2062
+ } else {
2063
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
2064
+ targetView.setUint32(position, number, true);
2065
+ position += 4;
2066
+ }
1971
2067
  break;
1972
- } else if (value < 0x100000000 && value >= -0x80000000) {
1973
- targetView.setFloat32(position, value, true);
2068
+ } else if (number < 0x100000000 && number >= -0x80000000) {
2069
+ targetView.setFloat32(position, number, true);
1974
2070
  if (float32Headers[target[position + 3] >>> 5]) {
1975
2071
  let xShifted;
1976
2072
  // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
1977
- if (((xShifted = value * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
2073
+ if (((xShifted = number * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
2074
+ transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
1978
2075
  position += 4;
1979
- continue;
2076
+ break;
1980
2077
  }
1981
2078
  }
1982
2079
  }
1983
- // fall back to msgpack encoding
1984
- queuedReferences.push(value, position - start);
1985
- position += 4;
1986
- continue;
2080
+ transition = nextTransition.num64 || createTypeTransition(nextTransition, NUMBER, 8);
2081
+ targetView.setFloat64(position, number, true);
2082
+ position += 8;
2083
+ break;
1987
2084
  case 'string':
1988
- if (hasNonLatin$1.test(value)) {
1989
- queuedReferences.push(value, position - start);
1990
- position += 4;
1991
- continue;
2085
+ let strLength = value.length;
2086
+ refOffset = refPosition - refsStartPosition;
2087
+ if ((strLength << 2) + position > safeEnd) {
2088
+ let lastStart = start;
2089
+ target = makeRoom(refPosition);
2090
+ targetView = target.dataView;
2091
+ position -= lastStart;
2092
+ refsStartPosition -= lastStart;
2093
+ refPosition -= lastStart;
2094
+ start = 0;
2095
+ safeEnd = target.length - 10;
1992
2096
  }
1993
- if (value.length < 4) { // we can inline really small strings
1994
- encoded = 0xf8000000 + (value.length << 24) + (value.charCodeAt(0) << 16) + (value.charCodeAt(1) << 8) + (value.charCodeAt(2) || 0);
1995
- // TODO: determining remaining and make max value be a ratio of that (probably 1/256th)
1996
- } else if (value.length < 256 && stringData.length < 61440) {
1997
- // bundle these strings
1998
- encoded = 0x60000000 | (value.length << 16) | stringData.length;
1999
- stringData += value;
2000
- } else { // else queue it
2001
- queuedReferences.push(value, position - start);
2002
- position += 4;
2003
- continue;
2097
+ if (strLength > ((0xff00 + refOffset) >> 2)) {
2098
+ queuedReferences.push(key, value, position - start);
2099
+ break;
2100
+ }
2101
+ let isNotAscii;
2102
+ let strStart = refPosition;
2103
+ if (strLength < 0x40) {
2104
+ let i, c1, c2;
2105
+ for (i = 0; i < strLength; i++) {
2106
+ c1 = value.charCodeAt(i);
2107
+ if (c1 < 0x80) {
2108
+ target[refPosition++] = c1;
2109
+ } else if (c1 < 0x800) {
2110
+ isNotAscii = true;
2111
+ target[refPosition++] = c1 >> 6 | 0xc0;
2112
+ target[refPosition++] = c1 & 0x3f | 0x80;
2113
+ } else if (
2114
+ (c1 & 0xfc00) === 0xd800 &&
2115
+ ((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
2116
+ ) {
2117
+ isNotAscii = true;
2118
+ c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
2119
+ i++;
2120
+ target[refPosition++] = c1 >> 18 | 0xf0;
2121
+ target[refPosition++] = c1 >> 12 & 0x3f | 0x80;
2122
+ target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
2123
+ target[refPosition++] = c1 & 0x3f | 0x80;
2124
+ } else {
2125
+ isNotAscii = true;
2126
+ target[refPosition++] = c1 >> 12 | 0xe0;
2127
+ target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
2128
+ target[refPosition++] = c1 & 0x3f | 0x80;
2129
+ }
2130
+ }
2131
+ } else {
2132
+ refPosition += encodeUtf8(target, value, refPosition);
2133
+ isNotAscii = refPosition - strStart > strLength;
2134
+ }
2135
+ if (refOffset < 0x100) {
2136
+ if (isNotAscii)
2137
+ transition = nextTransition.string8 || createTypeTransition(nextTransition, UTF8, 1);
2138
+ else
2139
+ transition = nextTransition.ascii8 || createTypeTransition(nextTransition, ASCII, 1);
2140
+ target[position++] = refOffset;
2141
+ } else {
2142
+ if (isNotAscii)
2143
+ transition = nextTransition.string16 || createTypeTransition(nextTransition, UTF8, 2);
2144
+ else
2145
+ transition = nextTransition.ascii16 || createTypeTransition(nextTransition, ASCII, 2);
2146
+ targetView.setUint16(position, refOffset, true);
2147
+ position += 2;
2004
2148
  }
2005
2149
  break;
2006
2150
  case 'object':
2007
2151
  if (value) {
2008
- queuedReferences.push(value, position - start);
2009
- position += 4;
2010
- continue;
2152
+ //transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
2153
+ queuedReferences.push(key, value, keyIndex);
2154
+ break;
2011
2155
  } else { // null
2012
- encoded = 0xe0000000;
2156
+ nextTransition = anyType(nextTransition, position, targetView, -10); // match CBOR with this
2157
+ if (nextTransition) {
2158
+ transition = nextTransition;
2159
+ position = updatedPosition;
2160
+ } else queuedReferences.push(key, value, keyIndex);
2013
2161
  }
2014
2162
  break;
2015
2163
  case 'boolean':
2016
- encoded = value ? 0xe3000000 : 0xe2000000;
2164
+ transition = nextTransition.num8 || nextTransition.ascii8 || createTypeTransition(nextTransition, NUMBER, 1);
2165
+ target[position++] = value ? 0xf9 : 0xf8; // match CBOR with these
2017
2166
  break;
2018
2167
  case 'undefined':
2019
- encoded = 0xe1000000;
2168
+ nextTransition = anyType(nextTransition, position, targetView, -9); // match CBOR with this
2169
+ if (nextTransition) {
2170
+ transition = nextTransition;
2171
+ position = updatedPosition;
2172
+ } else queuedReferences.push(key, value, keyIndex);
2020
2173
  break;
2021
2174
  }
2022
- targetView.setUint32(position, encoded, true);
2023
- position += 4;
2175
+ keyIndex++;
2024
2176
  }
2025
- let recordId = transition[RECORD_SYMBOL];
2026
- if (!(recordId < 1024)) {
2027
- // for now just punt and go back to writeObject
2028
- return 0;
2029
- // newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions, true)
2030
- }
2031
- let stringLength = stringData.length;
2032
- if (stringData) {
2033
- if (position + stringLength > safeEnd) {
2034
- target = makeRoom(position + stringLength);
2035
- }
2036
- position += target.latin1Write(stringData, position, 0xffffffff);
2037
- }
2038
- target[start] = recordId >> 8;
2039
- target[start + 1] = recordId & 0xff;
2040
- target[start + 2] = stringLength >> 8;
2041
- target[start + 3] = stringLength & 0xff;
2042
- let queued32BitReferences;
2177
+
2043
2178
  for (let i = 0, l = queuedReferences.length; i < l;) {
2179
+ let key = queuedReferences[i++];
2044
2180
  let value = queuedReferences[i++];
2045
- let slotOffset = queuedReferences[i++] + start;
2046
- let offset = position - slotOffset;
2047
- if (offset < 0x1f000000) {
2048
- targetView.setUint32(slotOffset, 0x80000000 | (offset), true);
2181
+ let propertyIndex = queuedReferences[i++];
2182
+ let nextTransition = transition[key];
2183
+ if (!nextTransition) {
2184
+ transition[key] = nextTransition = {
2185
+ key,
2186
+ parent: transition,
2187
+ enumerationOffset: propertyIndex - keyIndex,
2188
+ ascii0: null,
2189
+ ascii8: null,
2190
+ num8: null,
2191
+ string16: null,
2192
+ object16: null,
2193
+ num32: null,
2194
+ float64: null
2195
+ };
2196
+ }
2197
+ let newPosition;
2198
+ if (value) {
2199
+ /*if (typeof value === 'string') { // TODO: we could re-enable long strings
2200
+ if (position + value.length * 3 > safeEnd) {
2201
+ target = makeRoom(position + value.length * 3);
2202
+ position -= start;
2203
+ targetView = target.dataView;
2204
+ start = 0;
2205
+ }
2206
+ newPosition = position + target.utf8Write(value, position, 0xffffffff);
2207
+ } else { */
2208
+ let size;
2209
+ refOffset = refPosition - refsStartPosition;
2210
+ if (refOffset < 0xff00) {
2211
+ transition = nextTransition.object16;
2212
+ if (transition)
2213
+ size = 2;
2214
+ else if ((transition = nextTransition.object32))
2215
+ size = 4;
2216
+ else {
2217
+ transition = createTypeTransition(nextTransition, OBJECT_DATA, 2);
2218
+ size = 2;
2219
+ }
2220
+ } else {
2221
+ transition = nextTransition.object32 || createTypeTransition(nextTransition, OBJECT_DATA, 4);
2222
+ size = 4;
2223
+ }
2224
+ newPosition = pack(value, refPosition);
2225
+ //}
2226
+ if (typeof newPosition === 'object') {
2227
+ // re-allocated
2228
+ refPosition = newPosition.position;
2229
+ targetView = newPosition.targetView;
2230
+ target = newPosition.target;
2231
+ refsStartPosition -= start;
2232
+ position -= start;
2233
+ start = 0;
2234
+ } else
2235
+ refPosition = newPosition;
2236
+ if (size === 2) {
2237
+ targetView.setUint16(position, refOffset, true);
2238
+ position += 2;
2239
+ } else {
2240
+ targetView.setUint32(position, refOffset, true);
2241
+ position += 4;
2242
+ }
2049
2243
  } else {
2050
- if (!queued32BitReferences)
2051
- queued32BitReferences = [];
2052
- queued32BitReferences.push({slotOffset, offset: position - start});
2244
+ transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
2245
+ targetView.setInt16(position, value === null ? -10 : -9, true);
2246
+ position += 2;
2053
2247
  }
2054
- let newPosition = pack(value, position);
2055
- if (typeof newPosition === 'object') {
2056
- // re-allocated
2057
- position = newPosition.position;
2058
- targetView = newPosition.targetView;
2059
- start = 0;
2060
- } else
2061
- position = newPosition;
2248
+ keyIndex++;
2062
2249
  }
2063
- if (queued32BitReferences) {
2064
- // TODO: makeRoom
2065
- for (let i = 0, l = queued32BitReferences.length; i < l; i++) {
2066
- let ref = queued32BitReferences[i];
2067
- targetView.setUint32(ref.slotOffset, 0xa0000000 - ((l - i) << 2), true);
2068
- targetView.setUint32(position, ref.offset, true);
2069
- position += 4;
2250
+
2251
+
2252
+ let recordId = transition[RECORD_SYMBOL];
2253
+ if (recordId == null) {
2254
+ recordId = packr.typedStructs.length;
2255
+ let structure = [];
2256
+ let nextTransition = transition;
2257
+ let key, type;
2258
+ while ((type = nextTransition.__type) !== undefined) {
2259
+ let size = nextTransition.__size;
2260
+ nextTransition = nextTransition.__parent;
2261
+ key = nextTransition.key;
2262
+ let property = [type, size, key];
2263
+ if (nextTransition.enumerationOffset)
2264
+ property.push(nextTransition.enumerationOffset);
2265
+ structure.push(property);
2266
+ nextTransition = nextTransition.parent;
2070
2267
  }
2268
+ structure.reverse();
2269
+ transition[RECORD_SYMBOL] = recordId;
2270
+ packr.typedStructs[recordId] = structure;
2271
+ pack(null, 0, true); // special call to notify that structures have been updated
2272
+ }
2273
+
2274
+
2275
+ switch (headerSize) {
2276
+ case 1:
2277
+ if (recordId >= 0x10) return 0;
2278
+ target[start] = recordId + 0x20;
2279
+ break;
2280
+ case 2:
2281
+ if (recordId >= 0x100) return 0;
2282
+ target[start] = 0x38;
2283
+ target[start + 1] = recordId;
2284
+ break;
2285
+ case 3:
2286
+ if (recordId >= 0x10000) return 0;
2287
+ target[start] = 0x39;
2288
+ target.setUint16(start + 1, recordId, true);
2289
+ break;
2290
+ case 4:
2291
+ if (recordId >= 0x1000000) return 0;
2292
+ target.setUint32(start, (recordId << 8) + 0x3a, true);
2293
+ break;
2071
2294
  }
2072
2295
 
2073
- return position;
2296
+ if (position < refsStartPosition) {
2297
+ if (refsStartPosition === refPosition)
2298
+ return position; // no refs
2299
+ // adjust positioning
2300
+ target.copyWithin(position, refsStartPosition, refPosition);
2301
+ refPosition += position - refsStartPosition;
2302
+ typedStructs.lastStringStart = position - start;
2303
+ } else if (position > refsStartPosition) {
2304
+ if (refsStartPosition === refPosition)
2305
+ return position; // no refs
2306
+ typedStructs.lastStringStart = position - start;
2307
+ return writeStruct(object, target, start, structures, makeRoom, pack, packr);
2308
+ }
2309
+ return refPosition;
2310
+ }
2311
+ function anyType(transition, position, targetView, value) {
2312
+ let nextTransition;
2313
+ if ((nextTransition = transition.ascii8 || transition.num8)) {
2314
+ targetView.setInt8(position, value, true);
2315
+ updatedPosition = position + 1;
2316
+ return nextTransition;
2317
+ }
2318
+ if ((nextTransition = transition.string16 || transition.object16)) {
2319
+ targetView.setInt16(position, value, true);
2320
+ updatedPosition = position + 2;
2321
+ return nextTransition;
2322
+ }
2323
+ if (nextTransition = transition.num32) {
2324
+ targetView.setUint32(position, 0xe0000100 + value, true);
2325
+ updatedPosition = position + 4;
2326
+ return nextTransition;
2327
+ }
2328
+ // transition.float64
2329
+ if (nextTransition = transition.num64) {
2330
+ targetView.setFloat64(position, NaN, true);
2331
+ targetView.setInt8(position, value);
2332
+ updatedPosition = position + 8;
2333
+ return nextTransition;
2334
+ }
2335
+ updatedPosition = position;
2336
+ // TODO: can we do an "any" type where we defer the decision?
2337
+ return;
2338
+ }
2339
+ function createTypeTransition(transition, type, size) {
2340
+ let typeName = TYPE_NAMES[type] + (size << 3);
2341
+ let newTransition = transition[typeName] || (transition[typeName] = Object.create(null));
2342
+ newTransition.__type = type;
2343
+ newTransition.__size = size;
2344
+ newTransition.__parent = transition;
2345
+ return newTransition;
2346
+ }
2347
+ function onLoadedStructures$1(sharedData) {
2348
+ if (!(sharedData instanceof Map))
2349
+ return sharedData;
2350
+ let typed = sharedData.get('typed') || [];
2351
+ if (Object.isFrozen(typed))
2352
+ typed = typed.map(structure => structure.slice(0));
2353
+ let named = sharedData.get('named');
2354
+ let transitions = Object.create(null);
2355
+ for (let i = 0, l = typed.length; i < l; i++) {
2356
+ let structure = typed[i];
2357
+ let transition = transitions;
2358
+ for (let [type, size, key] of structure) {
2359
+ let nextTransition = transition[key];
2360
+ if (!nextTransition) {
2361
+ transition[key] = nextTransition = {
2362
+ key,
2363
+ parent: transition,
2364
+ enumerationOffset: 0,
2365
+ ascii0: null,
2366
+ ascii8: null,
2367
+ num8: null,
2368
+ string16: null,
2369
+ object16: null,
2370
+ num32: null,
2371
+ float64: null
2372
+ };
2373
+ }
2374
+ transition = createTypeTransition(nextTransition, type, size);
2375
+ }
2376
+ transition[RECORD_SYMBOL] = i;
2377
+ }
2378
+ typed.transitions = transitions;
2379
+ this.typedStructs = typed;
2380
+ this.lastTypedStructuresLength = typed.length;
2381
+ return named;
2074
2382
  }
2075
2383
  var sourceSymbol = Symbol('source');
2076
- function readStruct$1(src, position, srcEnd, structure, unpackr) {
2077
- var stringLength = (src[position++] << 8) | src[position++];
2384
+ function readStruct$1(src, position, srcEnd, unpackr) {
2385
+ // var stringLength = (src[position++] << 8) | src[position++];
2386
+ let recordId = src[position++] - 0x20;
2387
+ if (recordId >= 24) {
2388
+ switch(recordId) {
2389
+ case 24: recordId = src[position++]; break;
2390
+ // little endian:
2391
+ case 25: recordId = src[position++] + (src[position++] << 8); break;
2392
+ case 26: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16); break;
2393
+ case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
2394
+ }
2395
+ }
2396
+ let structure = unpackr.typedStructs?.[recordId];
2397
+ if (!structure) {
2398
+ // copy src buffer because getStructures will override it
2399
+ src = Uint8Array.prototype.slice.call(src, position, srcEnd);
2400
+ srcEnd -= position;
2401
+ position = 0;
2402
+ unpackr._mergeStructures(unpackr.getStructures());
2403
+ if (!unpackr.typedStructs)
2404
+ throw new Error('Could not find any shared typed structures');
2405
+ unpackr.lastTypedStructuresLength = unpackr.typedStructs.length;
2406
+ structure = unpackr.typedStructs[recordId];
2407
+ if (!structure)
2408
+ throw new Error('Could not find typed structure ' + recordId);
2409
+ }
2078
2410
  var construct = structure.construct;
2079
- var srcString;
2080
2411
  if (!construct) {
2081
- construct = structure.construct = function() {
2412
+ construct = structure.construct = function LazyObject() {
2082
2413
  };
2083
2414
  var prototype = construct.prototype;
2084
2415
  Object.defineProperty(prototype, 'toJSON', {
@@ -2093,78 +2424,231 @@
2093
2424
  },
2094
2425
  // not enumerable or anything
2095
2426
  });
2427
+ let currentOffset = 0;
2428
+ let lastRefProperty;
2429
+ let properties = [];
2096
2430
  for (let i = 0, l = structure.length; i < l; i++) {
2097
- let key = structure[i];
2098
- Object.defineProperty(prototype, key, {
2099
- get() {
2100
- let source = this[sourceSymbol];
2101
- let src = source.src;
2102
- //let uint32 = src.uint32 || (src.uint32 = new Uint32Array(src.buffer, src.byteOffset, src.byteLength));
2103
- let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2104
- let position = source.position + (i << 2);
2105
- let value = dataView.getUint32(position, true);
2106
- let start;
2107
- switch (value >>> 29) {
2108
- case 0:
2109
- return value;
2110
- case 3:
2111
- if (value & 0x10000000) {
2112
- start = (value & 0xffff) + position;
2113
- return src.toString('utf8', start, start + ((value >> 16) & 0x7ff));
2114
- } else {
2115
- if (!srcString) {
2116
- start = source.position + (l << 2);
2117
- srcString = src.toString('latin1', start, start + stringLength);
2118
- }
2119
- start = value & 0xffff;
2120
- return srcString.slice(start, start + ((value >> 16) & 0x7ff));
2121
- }
2122
- case 4:
2123
- start = (0x1fffffff & value) + position;
2124
- let end = srcEnd;
2125
- for (let next = i + 1; next < l; next++) {
2126
- position = source.position + (next << 2);
2127
- let nextValue = dataView.getUint32(position, true); if ((nextValue & 0xe0000000) == -0x80000000) {
2128
- end = (0x1fffffff & nextValue) + position;
2431
+ let definition = structure[i];
2432
+ let [ type, size, key, enumerationOffset ] = definition;
2433
+ let property = {
2434
+ key,
2435
+ offset: currentOffset,
2436
+ };
2437
+ if (enumerationOffset)
2438
+ properties.splice(i + enumerationOffset, 0, property);
2439
+ else
2440
+ properties.push(property);
2441
+ let getRef;
2442
+ switch(size) { // TODO: Move into a separate function
2443
+ case 0: getRef = () => 0; break;
2444
+ case 1:
2445
+ getRef = (source, position) => {
2446
+ let ref = source.src[position + property.offset];
2447
+ return ref >= 0xf6 ? toConstant(ref) : ref;
2448
+ };
2449
+ break;
2450
+ case 2:
2451
+ getRef = (source, position) => {
2452
+ let src = source.src;
2453
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2454
+ let ref = dataView.getUint16(position + property.offset, true);
2455
+ return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
2456
+ };
2457
+ break;
2458
+ case 4:
2459
+ getRef = (source, position) => {
2460
+ let src = source.src;
2461
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2462
+ let ref = dataView.getUint32(position + property.offset, true);
2463
+ return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
2464
+ };
2465
+ break;
2466
+ }
2467
+ property.getRef = getRef;
2468
+ currentOffset += size;
2469
+ let get;
2470
+ switch(type) {
2471
+ case ASCII:
2472
+ if (lastRefProperty && !lastRefProperty.next)
2473
+ lastRefProperty.next = property;
2474
+ lastRefProperty = property;
2475
+ property.multiGetCount = 0;
2476
+ get = function() {
2477
+ let source = this[sourceSymbol];
2478
+ let src = source.src;
2479
+ let position = source.position;
2480
+ let refStart = currentOffset + position;
2481
+ let ref = getRef(source, position);
2482
+ if (typeof ref !== 'number') return ref;
2483
+
2484
+ let end, next = property.next;
2485
+ while(next) {
2486
+ end = next.getRef(source, position);
2487
+ if (typeof end === 'number')
2488
+ break;
2489
+ else
2490
+ end = null;
2491
+ next = next.next;
2492
+ }
2493
+ if (end == null)
2494
+ end = source.srcEnd - refStart;
2495
+ if (source.srcString) {
2496
+ return source.srcString.slice(ref, end);
2497
+ }
2498
+ /*if (property.multiGetCount > 0) {
2499
+ let asciiEnd;
2500
+ next = firstRefProperty;
2501
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2502
+ do {
2503
+ asciiEnd = dataView.getUint16(source.position + next.offset, true);
2504
+ if (asciiEnd < 0xff00)
2129
2505
  break;
2506
+ else
2507
+ asciiEnd = null;
2508
+ } while((next = next.next));
2509
+ if (asciiEnd == null)
2510
+ asciiEnd = source.srcEnd - refStart
2511
+ source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
2512
+ return source.srcString.slice(ref, end);
2513
+ }
2514
+ if (source.prevStringGet) {
2515
+ source.prevStringGet.multiGetCount += 2;
2516
+ } else {
2517
+ source.prevStringGet = property;
2518
+ property.multiGetCount--;
2519
+ }*/
2520
+ return readString(src, ref + refStart, end - ref);
2521
+ //return src.toString('latin1', ref + refStart, end + refStart);
2522
+ };
2523
+ break;
2524
+ case UTF8: case OBJECT_DATA:
2525
+ if (lastRefProperty && !lastRefProperty.next)
2526
+ lastRefProperty.next = property;
2527
+ lastRefProperty = property;
2528
+ get = function() {
2529
+ let source = this[sourceSymbol];
2530
+ let position = source.position;
2531
+ let refStart = currentOffset + position;
2532
+ let ref = getRef(source, position);
2533
+ if (typeof ref !== 'number') return ref;
2534
+ let src = source.src;
2535
+ let end, next = property.next;
2536
+ while(next) {
2537
+ end = next.getRef(source, position);
2538
+ if (typeof end === 'number')
2539
+ break;
2540
+ else
2541
+ end = null;
2542
+ next = next.next;
2543
+ }
2544
+ if (end == null)
2545
+ end = source.srcEnd - refStart;
2546
+ if (type === UTF8) {
2547
+ return src.toString('utf8', ref + refStart, end + refStart);
2548
+ } else {
2549
+ return unpackr.unpack(src, { start: ref + refStart, end: end + refStart }); // could reuse this object
2550
+ }
2551
+ };
2552
+ break;
2553
+ case NUMBER:
2554
+ switch(size) {
2555
+ case 4:
2556
+ get = function () {
2557
+ let source = this[sourceSymbol];
2558
+ let src = source.src;
2559
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2560
+ let position = source.position + property.offset;
2561
+ let value = dataView.getInt32(position, true);
2562
+ if (value < 0x20000000) {
2563
+ if (value > -0x1f000000)
2564
+ return value;
2565
+ if (value > -0x20000000)
2566
+ return toConstant(value & 0xff);
2130
2567
  }
2131
- }
2132
- return unpackr.unpack(src.slice(start, end));
2133
- case 1: case 2: case 5: case 6:
2134
- let fValue = dataView.getFloat32(position, true);
2135
- // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
2136
- let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
2137
- return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
2138
- case 7:
2139
- switch((value >> 24) & 0x1f) {
2140
- case 0: return null;
2141
- case 1: return undefined;
2142
- case 2: return false;
2143
- case 3: return true;
2144
- case 8: return dataView.getFloat64(position + (value & 0x3ffffff), true);
2145
- case 0x18: return '';
2146
- case 0x19: return String.fromCharCode((value >> 16) & 0xff);
2147
- case 0x20: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff);
2148
- case 0x21: return String.fromCharCode((value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
2149
- default: throw new Error('Unknown constant');
2150
- }
2568
+ let fValue = dataView.getFloat32(position, true);
2569
+ // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
2570
+ let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
2571
+ return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
2572
+ };
2573
+ break;
2574
+ case 8:
2575
+ get = function () {
2576
+ let source = this[sourceSymbol];
2577
+ let src = source.src;
2578
+ let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
2579
+ let value = dataView.getFloat64(source.position + property.offset, true);
2580
+ if (isNaN(value)) {
2581
+ let byte = src[source.position + property.offset];
2582
+ if (byte >= 0xf6)
2583
+ return toConstant(byte);
2584
+ }
2585
+ return value;
2586
+ };
2587
+ break;
2588
+ case 1:
2589
+ get = function () {
2590
+ let source = this[sourceSymbol];
2591
+ let src = source.src;
2592
+ let value = src[source.position + property.offset];
2593
+ return value < 0xf6 ? value : toConstant(value);
2594
+ };
2595
+ break;
2151
2596
  }
2152
- },
2153
- enumerable: true,
2154
- });
2597
+ }
2598
+ property.get = get;
2155
2599
  }
2600
+ for (let property of properties) // assign in enumeration order
2601
+ Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
2156
2602
  }
2157
2603
  var instance = new construct();
2158
2604
  instance[sourceSymbol] = {
2159
2605
  src,
2160
- uint32: src.uint32,
2161
2606
  position,
2607
+ srcString: '',
2608
+ srcEnd
2162
2609
  };
2163
2610
  return instance;
2164
2611
  }
2165
- setReadStruct(readStruct$1);
2612
+ function toConstant(code) {
2613
+ switch(code) {
2614
+ case 0xf6: return null;
2615
+ case 0xf7: return undefined;
2616
+ case 0xf8: return false;
2617
+ case 0xf9: return true;
2618
+ }
2619
+ throw new Error('Unknown constant');
2620
+ }
2621
+ function prepareStructures$1(structures, packr) {
2622
+ if (!packr.typedStructs)
2623
+ return structures;
2624
+ let structMap = new Map();
2625
+ structMap.set('named', structures);
2626
+ structMap.set('typed', packr.typedStructs);
2627
+ let lastTypedStructuresLength = packr.lastTypedStructuresLength || 0;
2628
+ structMap.isCompatible = existing => {
2629
+ let compatible = true;
2630
+ if (existing instanceof Map) {
2631
+ let named = existing.get('named') || [];
2632
+ if (named.length !== (packr.lastNamedStructuresLength || 0))
2633
+ compatible = false;
2634
+ let typed = existing.get('typed') || [];
2635
+ if (typed.length !== lastTypedStructuresLength)
2636
+ compatible = false;
2637
+ } else if (existing instanceof Array) {
2638
+ if (existing.length !== (packr.lastNamedStructuresLength || 0))
2639
+ compatible = false;
2640
+ }
2641
+ if (!compatible)
2642
+ packr._mergeStructures(existing);
2643
+ return compatible;
2644
+ };
2645
+ packr.lastTypedStructuresLength = packr.typedStructs?.length;
2646
+ return structMap;
2647
+ }
2648
+
2649
+ setReadStruct(readStruct$1, onLoadedStructures$1);
2166
2650
 
2167
- const allSampleData = [];
2651
+ let allSampleData = [];
2168
2652
  for (let i = 1; i < 6; i++) {
2169
2653
  allSampleData.push(JSON.parse(fs.readFileSync(new URL(`./example${i > 1 ? i : ''}.json`, (document.currentScript && document.currentScript.src || new URL('test.js', document.baseURI).href)))));
2170
2654
  }
@@ -2176,6 +2660,13 @@
2176
2660
  return {}
2177
2661
  }
2178
2662
  }
2663
+
2664
+ let seed = 0;
2665
+ function random() {
2666
+ seed++;
2667
+ let a = seed * 15485863;
2668
+ return (a * a * a % 2038074743) / 2038074743;
2669
+ }
2179
2670
  //if (typeof chai === 'undefined') { chai = require('chai') }
2180
2671
  var assert = chai.assert;
2181
2672
  //if (typeof msgpackr === 'undefined') { msgpackr = require('..') }
@@ -2274,6 +2765,36 @@
2274
2765
  var deserialized = unpack(serialized);
2275
2766
  assert.equal(deserialized, data);
2276
2767
  });
2768
+ test('pack/unpack varying data with random access structures', function() {
2769
+ let structures = [];
2770
+ let packr = new Packr$1({ structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
2771
+ }, getStructures() {
2772
+ console.log('getStructures');
2773
+ } });
2774
+ for (let i = 0; i < 20; i++) {
2775
+ let data = {};
2776
+ let props = ['foo', 'bar', 'a', 'b', 'c','name', 'age', 'd'];
2777
+ function makeString() {
2778
+ let str = '';
2779
+ while (random() < 0.9) {
2780
+ str += random() < 0.8 ? 'hello world' : String.fromCharCode(300);
2781
+ }
2782
+ return str;
2783
+ }
2784
+ for (let i = 0; i < random() * 20; i++) {
2785
+ data[props[Math.floor(random() * 8)]] =
2786
+ random() < 0.3 ? Math.floor(random() * 400) / 2 :
2787
+ random() < 0.3 ? makeString() : random() < 0.3 ? true : random() < 0.3 ? sampleData : null;
2788
+ }
2789
+ var serialized = packr.pack(data);
2790
+ var deserialized = packr.unpack(serialized);
2791
+ for (let key in deserialized) {
2792
+ let a = deserialized[key];
2793
+ }
2794
+ assert.deepEqual(deserialized, data);
2795
+ }
2796
+ });
2797
+
2277
2798
  for (let sampleData of allSampleData) {
2278
2799
  let snippet = JSON.stringify(sampleData).slice(0, 20) + '...';
2279
2800
  test('pack/unpack sample data ' + snippet, function(){
@@ -2288,11 +2809,18 @@
2288
2809
  test('pack/unpack sample data with random access structures ' + snippet, function() {
2289
2810
  var data = sampleData;
2290
2811
  let structures = [];
2291
- let packr = new Packr$1({ structures, useRecords: true, randomAccessStructure: true, freezeData: true });
2812
+ let packr = new Packr$1({ structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
2813
+ }, getStructures() {
2814
+ console.log('getStructures');
2815
+ } });
2292
2816
  for (let i = 0; i < 20; i++) {
2293
2817
  var serialized = packr.pack(data);
2294
2818
  var deserialized = packr.unpack(serialized);
2295
- assert.deepEqual(deserialized, data);
2819
+ var copied = {};
2820
+ for (let key in deserialized) {
2821
+ copied[key] = deserialized[key];
2822
+ }
2823
+ assert.deepEqual(copied, data);
2296
2824
  }
2297
2825
  });
2298
2826
  test('pack/unpack sample data with bundled strings ' + snippet, function(){
@@ -2302,6 +2830,7 @@
2302
2830
  var deserialized = packr.unpack(serialized);
2303
2831
  assert.deepEqual(deserialized, data);
2304
2832
  });
2833
+ break;
2305
2834
  }
2306
2835
 
2307
2836
  test('pack/unpack empty data with bundled strings', function(){
@@ -2884,4 +3413,5 @@
2884
3413
  });
2885
3414
  });
2886
3415
 
2887
- }(msgpackr, chai, fs));
3416
+ }(msgpackr, chai, inspector, fs));
3417
+ //# sourceMappingURL=test.js.map