msgpackr 1.6.2 → 1.7.0-alpha3
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/LICENSE +21 -21
- package/README.md +335 -335
- package/SECURITY.md +11 -11
- package/benchmark.md +67 -67
- package/dist/index.js +139 -100
- package/dist/index.js.map +1 -0
- package/dist/index.min.js +78 -77
- package/dist/index.min.js.map +1 -0
- package/dist/node.cjs +888 -150
- package/dist/node.cjs.map +1 -0
- package/dist/test.js +2747 -50
- package/dist/test.js.map +1 -0
- package/index.js +5 -5
- package/iterators.js +86 -86
- package/node-index.js +1 -0
- package/pack.d.ts +9 -9
- package/pack.js +37 -10
- package/package.json +83 -83
- package/rollup.config.js +49 -45
- package/stream.js +57 -57
- package/struct.js +711 -0
- package/unpack.js +50 -8
package/dist/test.js
CHANGED
|
@@ -1,9 +1,2643 @@
|
|
|
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;
|
|
8
|
+
try {
|
|
9
|
+
decoder = new TextDecoder();
|
|
10
|
+
} catch(error) {}
|
|
11
|
+
var src;
|
|
12
|
+
var srcEnd;
|
|
13
|
+
var position = 0;
|
|
14
|
+
var currentUnpackr = {};
|
|
15
|
+
var currentStructures;
|
|
16
|
+
var srcString;
|
|
17
|
+
var srcStringStart = 0;
|
|
18
|
+
var srcStringEnd = 0;
|
|
19
|
+
var bundledStrings;
|
|
20
|
+
var referenceMap;
|
|
21
|
+
var currentExtensions = [];
|
|
22
|
+
var dataView;
|
|
23
|
+
var defaultOptions = {
|
|
24
|
+
useRecords: false,
|
|
25
|
+
mapsAsObjects: true
|
|
26
|
+
};
|
|
27
|
+
class C1Type {}
|
|
28
|
+
const C1 = new C1Type();
|
|
29
|
+
C1.name = 'MessagePack 0xC1';
|
|
30
|
+
var sequentialMode = false;
|
|
31
|
+
var inlineObjectReadThreshold = 2;
|
|
32
|
+
var readStruct, onLoadedStructures;
|
|
33
|
+
try {
|
|
34
|
+
new Function('');
|
|
35
|
+
} catch(error) {
|
|
36
|
+
// if eval variants are not supported, do not create inline object readers ever
|
|
37
|
+
inlineObjectReadThreshold = Infinity;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class Unpackr {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
if (options) {
|
|
43
|
+
if (options.useRecords === false && options.mapsAsObjects === undefined)
|
|
44
|
+
options.mapsAsObjects = true;
|
|
45
|
+
if (options.sequential && options.trusted !== false) {
|
|
46
|
+
options.trusted = true;
|
|
47
|
+
if (!options.structures && options.useRecords != false) {
|
|
48
|
+
options.structures = [];
|
|
49
|
+
if (!options.maxSharedStructures)
|
|
50
|
+
options.maxSharedStructures = 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (options.structures)
|
|
54
|
+
options.structures.sharedLength = options.structures.length;
|
|
55
|
+
else if (options.getStructures) {
|
|
56
|
+
(options.structures = []).uninitialized = true; // this is what we use to denote an uninitialized structures
|
|
57
|
+
options.structures.sharedLength = 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
Object.assign(this, options);
|
|
61
|
+
}
|
|
62
|
+
unpack(source, options) {
|
|
63
|
+
if (src) {
|
|
64
|
+
// re-entrant execution, save the state and restore it after we do this unpack
|
|
65
|
+
return saveState(() => {
|
|
66
|
+
clearSource();
|
|
67
|
+
return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
|
|
68
|
+
})
|
|
69
|
+
}
|
|
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
|
+
}
|
|
77
|
+
srcStringEnd = 0;
|
|
78
|
+
srcString = null;
|
|
79
|
+
bundledStrings = null;
|
|
80
|
+
src = source;
|
|
81
|
+
// this provides cached access to the data view for a buffer if it is getting reused, which is a recommend
|
|
82
|
+
// technique for getting data from a database where it can be copied into an existing buffer instead of creating
|
|
83
|
+
// new ones
|
|
84
|
+
try {
|
|
85
|
+
dataView = source.dataView || (source.dataView = new DataView(source.buffer, source.byteOffset, source.byteLength));
|
|
86
|
+
} catch(error) {
|
|
87
|
+
// if it doesn't have a buffer, maybe it is the wrong type of object
|
|
88
|
+
src = null;
|
|
89
|
+
if (source instanceof Uint8Array)
|
|
90
|
+
throw error
|
|
91
|
+
throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source))
|
|
92
|
+
}
|
|
93
|
+
if (this instanceof Unpackr) {
|
|
94
|
+
currentUnpackr = this;
|
|
95
|
+
if (this.structures) {
|
|
96
|
+
currentStructures = this.structures;
|
|
97
|
+
return checkedRead()
|
|
98
|
+
} else if (!currentStructures || currentStructures.length > 0) {
|
|
99
|
+
currentStructures = [];
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
currentUnpackr = defaultOptions;
|
|
103
|
+
if (!currentStructures || currentStructures.length > 0)
|
|
104
|
+
currentStructures = [];
|
|
105
|
+
}
|
|
106
|
+
return checkedRead()
|
|
107
|
+
}
|
|
108
|
+
unpackMultiple(source, forEach) {
|
|
109
|
+
let values, lastPosition = 0;
|
|
110
|
+
try {
|
|
111
|
+
sequentialMode = true;
|
|
112
|
+
let size = source.length;
|
|
113
|
+
let value = this ? this.unpack(source, size) : defaultUnpackr.unpack(source, size);
|
|
114
|
+
if (forEach) {
|
|
115
|
+
forEach(value);
|
|
116
|
+
while(position < size) {
|
|
117
|
+
lastPosition = position;
|
|
118
|
+
if (forEach(checkedRead()) === false) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
values = [ value ];
|
|
125
|
+
while(position < size) {
|
|
126
|
+
lastPosition = position;
|
|
127
|
+
values.push(checkedRead());
|
|
128
|
+
}
|
|
129
|
+
return values
|
|
130
|
+
}
|
|
131
|
+
} catch(error) {
|
|
132
|
+
error.lastPosition = lastPosition;
|
|
133
|
+
error.values = values;
|
|
134
|
+
throw error
|
|
135
|
+
} finally {
|
|
136
|
+
sequentialMode = false;
|
|
137
|
+
clearSource();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
_mergeStructures(loadedStructures, existingStructures) {
|
|
141
|
+
if (onLoadedStructures)
|
|
142
|
+
loadedStructures = onLoadedStructures.call(this, loadedStructures);
|
|
143
|
+
loadedStructures = loadedStructures || [];
|
|
144
|
+
for (let i = 0, l = loadedStructures.length; i < l; i++) {
|
|
145
|
+
let structure = loadedStructures[i];
|
|
146
|
+
if (structure) {
|
|
147
|
+
structure.isShared = true;
|
|
148
|
+
if (i >= 32)
|
|
149
|
+
structure.highByte = (i - 32) >> 5;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
loadedStructures.sharedLength = loadedStructures.length;
|
|
153
|
+
for (let id in existingStructures || []) {
|
|
154
|
+
if (id >= 0) {
|
|
155
|
+
let structure = loadedStructures[id];
|
|
156
|
+
let existing = existingStructures[id];
|
|
157
|
+
if (existing) {
|
|
158
|
+
if (structure)
|
|
159
|
+
(loadedStructures.restoreStructures || (loadedStructures.restoreStructures = []))[id] = structure;
|
|
160
|
+
loadedStructures[id] = existing;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return this.structures = loadedStructures
|
|
165
|
+
}
|
|
166
|
+
decode(source, end) {
|
|
167
|
+
return this.unpack(source, end)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function checkedRead() {
|
|
171
|
+
try {
|
|
172
|
+
if (!currentUnpackr.trusted && !sequentialMode) {
|
|
173
|
+
let sharedLength = currentStructures.sharedLength || 0;
|
|
174
|
+
if (sharedLength < currentStructures.length)
|
|
175
|
+
currentStructures.length = sharedLength;
|
|
176
|
+
}
|
|
177
|
+
let result;
|
|
178
|
+
if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
|
|
179
|
+
result = readStruct(src, position, srcEnd, currentUnpackr);
|
|
180
|
+
position = srcEnd;
|
|
181
|
+
} else
|
|
182
|
+
result = read();
|
|
183
|
+
if (bundledStrings) // bundled strings to skip past
|
|
184
|
+
position = bundledStrings.postBundlePosition;
|
|
185
|
+
|
|
186
|
+
if (position == srcEnd) {
|
|
187
|
+
// finished reading this source, cleanup references
|
|
188
|
+
if (currentStructures.restoreStructures)
|
|
189
|
+
restoreStructures();
|
|
190
|
+
currentStructures = null;
|
|
191
|
+
src = null;
|
|
192
|
+
if (referenceMap)
|
|
193
|
+
referenceMap = null;
|
|
194
|
+
} else if (position > srcEnd) {
|
|
195
|
+
// over read
|
|
196
|
+
throw new Error('Unexpected end of MessagePack data')
|
|
197
|
+
} else if (!sequentialMode) {
|
|
198
|
+
throw new Error('Data read, but end of buffer not reached ' + JSON.stringify(result).slice(0, 100))
|
|
199
|
+
}
|
|
200
|
+
// else more to read, but we are reading sequentially, so don't clear source yet
|
|
201
|
+
return result
|
|
202
|
+
} catch(error) {
|
|
203
|
+
if (currentStructures.restoreStructures)
|
|
204
|
+
restoreStructures();
|
|
205
|
+
clearSource();
|
|
206
|
+
if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position > srcEnd) {
|
|
207
|
+
error.incomplete = true;
|
|
208
|
+
}
|
|
209
|
+
throw error
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function restoreStructures() {
|
|
214
|
+
for (let id in currentStructures.restoreStructures) {
|
|
215
|
+
currentStructures[id] = currentStructures.restoreStructures[id];
|
|
216
|
+
}
|
|
217
|
+
currentStructures.restoreStructures = null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function read() {
|
|
221
|
+
let token = src[position++];
|
|
222
|
+
if (token < 0xa0) {
|
|
223
|
+
if (token < 0x80) {
|
|
224
|
+
if (token < 0x40)
|
|
225
|
+
return token
|
|
226
|
+
else {
|
|
227
|
+
let structure = currentStructures[token & 0x3f] ||
|
|
228
|
+
currentUnpackr.getStructures && loadStructures()[token & 0x3f];
|
|
229
|
+
if (structure) {
|
|
230
|
+
if (!structure.read) {
|
|
231
|
+
structure.read = createStructureReader(structure, token & 0x3f);
|
|
232
|
+
}
|
|
233
|
+
return structure.read()
|
|
234
|
+
} else
|
|
235
|
+
return token
|
|
236
|
+
}
|
|
237
|
+
} else if (token < 0x90) {
|
|
238
|
+
// map
|
|
239
|
+
token -= 0x80;
|
|
240
|
+
if (currentUnpackr.mapsAsObjects) {
|
|
241
|
+
let object = {};
|
|
242
|
+
for (let i = 0; i < token; i++) {
|
|
243
|
+
object[readKey()] = read();
|
|
244
|
+
}
|
|
245
|
+
return object
|
|
246
|
+
} else {
|
|
247
|
+
let map = new Map();
|
|
248
|
+
for (let i = 0; i < token; i++) {
|
|
249
|
+
map.set(read(), read());
|
|
250
|
+
}
|
|
251
|
+
return map
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
token -= 0x90;
|
|
255
|
+
let array = new Array(token);
|
|
256
|
+
for (let i = 0; i < token; i++) {
|
|
257
|
+
array[i] = read();
|
|
258
|
+
}
|
|
259
|
+
if (currentUnpackr.freezeData)
|
|
260
|
+
return Object.freeze(array)
|
|
261
|
+
return array
|
|
262
|
+
}
|
|
263
|
+
} else if (token < 0xc0) {
|
|
264
|
+
// fixstr
|
|
265
|
+
let length = token - 0xa0;
|
|
266
|
+
if (srcStringEnd >= position) {
|
|
267
|
+
return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
|
|
268
|
+
}
|
|
269
|
+
if (srcStringEnd == 0 && srcEnd < 140) {
|
|
270
|
+
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
271
|
+
let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
|
|
272
|
+
if (string != null)
|
|
273
|
+
return string
|
|
274
|
+
}
|
|
275
|
+
return readFixedString(length)
|
|
276
|
+
} else {
|
|
277
|
+
let value;
|
|
278
|
+
switch (token) {
|
|
279
|
+
case 0xc0: return null
|
|
280
|
+
case 0xc1:
|
|
281
|
+
if (bundledStrings) {
|
|
282
|
+
value = read(); // followed by the length of the string in characters (not bytes!)
|
|
283
|
+
if (value > 0)
|
|
284
|
+
return bundledStrings[1].slice(bundledStrings.position1, bundledStrings.position1 += value)
|
|
285
|
+
else
|
|
286
|
+
return bundledStrings[0].slice(bundledStrings.position0, bundledStrings.position0 -= value)
|
|
287
|
+
}
|
|
288
|
+
return C1; // "never-used", return special object to denote that
|
|
289
|
+
case 0xc2: return false
|
|
290
|
+
case 0xc3: return true
|
|
291
|
+
case 0xc4:
|
|
292
|
+
// bin 8
|
|
293
|
+
value = src[position++];
|
|
294
|
+
if (value === undefined)
|
|
295
|
+
throw new Error('Unexpected end of buffer')
|
|
296
|
+
return readBin(value)
|
|
297
|
+
case 0xc5:
|
|
298
|
+
// bin 16
|
|
299
|
+
value = dataView.getUint16(position);
|
|
300
|
+
position += 2;
|
|
301
|
+
return readBin(value)
|
|
302
|
+
case 0xc6:
|
|
303
|
+
// bin 32
|
|
304
|
+
value = dataView.getUint32(position);
|
|
305
|
+
position += 4;
|
|
306
|
+
return readBin(value)
|
|
307
|
+
case 0xc7:
|
|
308
|
+
// ext 8
|
|
309
|
+
return readExt(src[position++])
|
|
310
|
+
case 0xc8:
|
|
311
|
+
// ext 16
|
|
312
|
+
value = dataView.getUint16(position);
|
|
313
|
+
position += 2;
|
|
314
|
+
return readExt(value)
|
|
315
|
+
case 0xc9:
|
|
316
|
+
// ext 32
|
|
317
|
+
value = dataView.getUint32(position);
|
|
318
|
+
position += 4;
|
|
319
|
+
return readExt(value)
|
|
320
|
+
case 0xca:
|
|
321
|
+
value = dataView.getFloat32(position);
|
|
322
|
+
if (currentUnpackr.useFloat32 > 2) {
|
|
323
|
+
// this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
324
|
+
let multiplier = mult10[((src[position] & 0x7f) << 1) | (src[position + 1] >> 7)];
|
|
325
|
+
position += 4;
|
|
326
|
+
return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
327
|
+
}
|
|
328
|
+
position += 4;
|
|
329
|
+
return value
|
|
330
|
+
case 0xcb:
|
|
331
|
+
value = dataView.getFloat64(position);
|
|
332
|
+
position += 8;
|
|
333
|
+
return value
|
|
334
|
+
// uint handlers
|
|
335
|
+
case 0xcc:
|
|
336
|
+
return src[position++]
|
|
337
|
+
case 0xcd:
|
|
338
|
+
value = dataView.getUint16(position);
|
|
339
|
+
position += 2;
|
|
340
|
+
return value
|
|
341
|
+
case 0xce:
|
|
342
|
+
value = dataView.getUint32(position);
|
|
343
|
+
position += 4;
|
|
344
|
+
return value
|
|
345
|
+
case 0xcf:
|
|
346
|
+
if (currentUnpackr.int64AsNumber) {
|
|
347
|
+
value = dataView.getUint32(position) * 0x100000000;
|
|
348
|
+
value += dataView.getUint32(position + 4);
|
|
349
|
+
} else
|
|
350
|
+
value = dataView.getBigUint64(position);
|
|
351
|
+
position += 8;
|
|
352
|
+
return value
|
|
353
|
+
|
|
354
|
+
// int handlers
|
|
355
|
+
case 0xd0:
|
|
356
|
+
return dataView.getInt8(position++)
|
|
357
|
+
case 0xd1:
|
|
358
|
+
value = dataView.getInt16(position);
|
|
359
|
+
position += 2;
|
|
360
|
+
return value
|
|
361
|
+
case 0xd2:
|
|
362
|
+
value = dataView.getInt32(position);
|
|
363
|
+
position += 4;
|
|
364
|
+
return value
|
|
365
|
+
case 0xd3:
|
|
366
|
+
if (currentUnpackr.int64AsNumber) {
|
|
367
|
+
value = dataView.getInt32(position) * 0x100000000;
|
|
368
|
+
value += dataView.getUint32(position + 4);
|
|
369
|
+
} else
|
|
370
|
+
value = dataView.getBigInt64(position);
|
|
371
|
+
position += 8;
|
|
372
|
+
return value
|
|
373
|
+
|
|
374
|
+
case 0xd4:
|
|
375
|
+
// fixext 1
|
|
376
|
+
value = src[position++];
|
|
377
|
+
if (value == 0x72) {
|
|
378
|
+
return recordDefinition(src[position++] & 0x3f)
|
|
379
|
+
} else {
|
|
380
|
+
let extension = currentExtensions[value];
|
|
381
|
+
if (extension) {
|
|
382
|
+
if (extension.read) {
|
|
383
|
+
position++; // skip filler byte
|
|
384
|
+
return extension.read(read())
|
|
385
|
+
} else if (extension.noBuffer) {
|
|
386
|
+
position++; // skip filler byte
|
|
387
|
+
return extension()
|
|
388
|
+
} else
|
|
389
|
+
return extension(src.subarray(position, ++position))
|
|
390
|
+
} else
|
|
391
|
+
throw new Error('Unknown extension ' + value)
|
|
392
|
+
}
|
|
393
|
+
case 0xd5:
|
|
394
|
+
// fixext 2
|
|
395
|
+
value = src[position];
|
|
396
|
+
if (value == 0x72) {
|
|
397
|
+
position++;
|
|
398
|
+
return recordDefinition(src[position++] & 0x3f, src[position++])
|
|
399
|
+
} else
|
|
400
|
+
return readExt(2)
|
|
401
|
+
case 0xd6:
|
|
402
|
+
// fixext 4
|
|
403
|
+
return readExt(4)
|
|
404
|
+
case 0xd7:
|
|
405
|
+
// fixext 8
|
|
406
|
+
return readExt(8)
|
|
407
|
+
case 0xd8:
|
|
408
|
+
// fixext 16
|
|
409
|
+
return readExt(16)
|
|
410
|
+
case 0xd9:
|
|
411
|
+
// str 8
|
|
412
|
+
value = src[position++];
|
|
413
|
+
if (srcStringEnd >= position) {
|
|
414
|
+
return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
|
|
415
|
+
}
|
|
416
|
+
return readString8(value)
|
|
417
|
+
case 0xda:
|
|
418
|
+
// str 16
|
|
419
|
+
value = dataView.getUint16(position);
|
|
420
|
+
position += 2;
|
|
421
|
+
if (srcStringEnd >= position) {
|
|
422
|
+
return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
|
|
423
|
+
}
|
|
424
|
+
return readString16(value)
|
|
425
|
+
case 0xdb:
|
|
426
|
+
// str 32
|
|
427
|
+
value = dataView.getUint32(position);
|
|
428
|
+
position += 4;
|
|
429
|
+
if (srcStringEnd >= position) {
|
|
430
|
+
return srcString.slice(position - srcStringStart, (position += value) - srcStringStart)
|
|
431
|
+
}
|
|
432
|
+
return readString32(value)
|
|
433
|
+
case 0xdc:
|
|
434
|
+
// array 16
|
|
435
|
+
value = dataView.getUint16(position);
|
|
436
|
+
position += 2;
|
|
437
|
+
return readArray(value)
|
|
438
|
+
case 0xdd:
|
|
439
|
+
// array 32
|
|
440
|
+
value = dataView.getUint32(position);
|
|
441
|
+
position += 4;
|
|
442
|
+
return readArray(value)
|
|
443
|
+
case 0xde:
|
|
444
|
+
// map 16
|
|
445
|
+
value = dataView.getUint16(position);
|
|
446
|
+
position += 2;
|
|
447
|
+
return readMap(value)
|
|
448
|
+
case 0xdf:
|
|
449
|
+
// map 32
|
|
450
|
+
value = dataView.getUint32(position);
|
|
451
|
+
position += 4;
|
|
452
|
+
return readMap(value)
|
|
453
|
+
default: // negative int
|
|
454
|
+
if (token >= 0xe0)
|
|
455
|
+
return token - 0x100
|
|
456
|
+
if (token === undefined) {
|
|
457
|
+
let error = new Error('Unexpected end of MessagePack data');
|
|
458
|
+
error.incomplete = true;
|
|
459
|
+
throw error
|
|
460
|
+
}
|
|
461
|
+
throw new Error('Unknown MessagePack token ' + token)
|
|
462
|
+
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const validName = /^[a-zA-Z_$][a-zA-Z\d_$]*$/;
|
|
467
|
+
function createStructureReader(structure, firstId) {
|
|
468
|
+
function readObject() {
|
|
469
|
+
// This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
|
|
470
|
+
if (readObject.count++ > inlineObjectReadThreshold) {
|
|
471
|
+
let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
|
|
472
|
+
'({' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read);
|
|
473
|
+
if (structure.highByte === 0)
|
|
474
|
+
structure.read = createSecondByteReader(firstId, structure.read);
|
|
475
|
+
return readObject() // second byte is already read, if there is one so immediately read object
|
|
476
|
+
}
|
|
477
|
+
let object = {};
|
|
478
|
+
for (let i = 0, l = structure.length; i < l; i++) {
|
|
479
|
+
let key = structure[i];
|
|
480
|
+
object[key] = read();
|
|
481
|
+
}
|
|
482
|
+
if (currentUnpackr.freezeData)
|
|
483
|
+
return Object.freeze(object);
|
|
484
|
+
return object
|
|
485
|
+
}
|
|
486
|
+
readObject.count = 0;
|
|
487
|
+
if (structure.highByte === 0) {
|
|
488
|
+
return createSecondByteReader(firstId, readObject)
|
|
489
|
+
}
|
|
490
|
+
return readObject
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const createSecondByteReader = (firstId, read0) => {
|
|
494
|
+
return function() {
|
|
495
|
+
let highByte = src[position++];
|
|
496
|
+
if (highByte === 0)
|
|
497
|
+
return read0()
|
|
498
|
+
let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5);
|
|
499
|
+
let structure = currentStructures[id] || loadStructures()[id];
|
|
500
|
+
if (!structure) {
|
|
501
|
+
throw new Error('Record id is not defined for ' + id)
|
|
502
|
+
}
|
|
503
|
+
if (!structure.read)
|
|
504
|
+
structure.read = createStructureReader(structure, firstId);
|
|
505
|
+
return structure.read()
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
function loadStructures() {
|
|
510
|
+
let loadedStructures = saveState(() => {
|
|
511
|
+
// save the state in case getStructures modifies our buffer
|
|
512
|
+
src = null;
|
|
513
|
+
return currentUnpackr.getStructures()
|
|
514
|
+
});
|
|
515
|
+
return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
var readFixedString = readStringJS;
|
|
519
|
+
var readString8 = readStringJS;
|
|
520
|
+
var readString16 = readStringJS;
|
|
521
|
+
var readString32 = readStringJS;
|
|
522
|
+
function readStringJS(length) {
|
|
523
|
+
let result;
|
|
524
|
+
if (length < 16) {
|
|
525
|
+
if (result = shortStringInJS(length))
|
|
526
|
+
return result
|
|
527
|
+
}
|
|
528
|
+
if (length > 64 && decoder)
|
|
529
|
+
return decoder.decode(src.subarray(position, position += length))
|
|
530
|
+
const end = position + length;
|
|
531
|
+
const units = [];
|
|
532
|
+
result = '';
|
|
533
|
+
while (position < end) {
|
|
534
|
+
const byte1 = src[position++];
|
|
535
|
+
if ((byte1 & 0x80) === 0) {
|
|
536
|
+
// 1 byte
|
|
537
|
+
units.push(byte1);
|
|
538
|
+
} else if ((byte1 & 0xe0) === 0xc0) {
|
|
539
|
+
// 2 bytes
|
|
540
|
+
const byte2 = src[position++] & 0x3f;
|
|
541
|
+
units.push(((byte1 & 0x1f) << 6) | byte2);
|
|
542
|
+
} else if ((byte1 & 0xf0) === 0xe0) {
|
|
543
|
+
// 3 bytes
|
|
544
|
+
const byte2 = src[position++] & 0x3f;
|
|
545
|
+
const byte3 = src[position++] & 0x3f;
|
|
546
|
+
units.push(((byte1 & 0x1f) << 12) | (byte2 << 6) | byte3);
|
|
547
|
+
} else if ((byte1 & 0xf8) === 0xf0) {
|
|
548
|
+
// 4 bytes
|
|
549
|
+
const byte2 = src[position++] & 0x3f;
|
|
550
|
+
const byte3 = src[position++] & 0x3f;
|
|
551
|
+
const byte4 = src[position++] & 0x3f;
|
|
552
|
+
let unit = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
|
|
553
|
+
if (unit > 0xffff) {
|
|
554
|
+
unit -= 0x10000;
|
|
555
|
+
units.push(((unit >>> 10) & 0x3ff) | 0xd800);
|
|
556
|
+
unit = 0xdc00 | (unit & 0x3ff);
|
|
557
|
+
}
|
|
558
|
+
units.push(unit);
|
|
559
|
+
} else {
|
|
560
|
+
units.push(byte1);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (units.length >= 0x1000) {
|
|
564
|
+
result += fromCharCode.apply(String, units);
|
|
565
|
+
units.length = 0;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (units.length > 0) {
|
|
570
|
+
result += fromCharCode.apply(String, units);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return result
|
|
574
|
+
}
|
|
575
|
+
function readString(source, start, length) {
|
|
576
|
+
let existingSrc = src;
|
|
577
|
+
src = source;
|
|
578
|
+
position = start;
|
|
579
|
+
try {
|
|
580
|
+
return readStringJS(length);
|
|
581
|
+
} finally {
|
|
582
|
+
src = existingSrc;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function readArray(length) {
|
|
587
|
+
let array = new Array(length);
|
|
588
|
+
for (let i = 0; i < length; i++) {
|
|
589
|
+
array[i] = read();
|
|
590
|
+
}
|
|
591
|
+
if (currentUnpackr.freezeData)
|
|
592
|
+
return Object.freeze(array)
|
|
593
|
+
return array
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function readMap(length) {
|
|
597
|
+
if (currentUnpackr.mapsAsObjects) {
|
|
598
|
+
let object = {};
|
|
599
|
+
for (let i = 0; i < length; i++) {
|
|
600
|
+
object[readKey()] = read();
|
|
601
|
+
}
|
|
602
|
+
return object
|
|
603
|
+
} else {
|
|
604
|
+
let map = new Map();
|
|
605
|
+
for (let i = 0; i < length; i++) {
|
|
606
|
+
map.set(read(), read());
|
|
607
|
+
}
|
|
608
|
+
return map
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
var fromCharCode = String.fromCharCode;
|
|
613
|
+
function longStringInJS(length) {
|
|
614
|
+
let start = position;
|
|
615
|
+
let bytes = new Array(length);
|
|
616
|
+
for (let i = 0; i < length; i++) {
|
|
617
|
+
const byte = src[position++];
|
|
618
|
+
if ((byte & 0x80) > 0) {
|
|
619
|
+
position = start;
|
|
620
|
+
return
|
|
621
|
+
}
|
|
622
|
+
bytes[i] = byte;
|
|
623
|
+
}
|
|
624
|
+
return fromCharCode.apply(String, bytes)
|
|
625
|
+
}
|
|
626
|
+
function shortStringInJS(length) {
|
|
627
|
+
if (length < 4) {
|
|
628
|
+
if (length < 2) {
|
|
629
|
+
if (length === 0)
|
|
630
|
+
return ''
|
|
631
|
+
else {
|
|
632
|
+
let a = src[position++];
|
|
633
|
+
if ((a & 0x80) > 1) {
|
|
634
|
+
position -= 1;
|
|
635
|
+
return
|
|
636
|
+
}
|
|
637
|
+
return fromCharCode(a)
|
|
638
|
+
}
|
|
639
|
+
} else {
|
|
640
|
+
let a = src[position++];
|
|
641
|
+
let b = src[position++];
|
|
642
|
+
if ((a & 0x80) > 0 || (b & 0x80) > 0) {
|
|
643
|
+
position -= 2;
|
|
644
|
+
return
|
|
645
|
+
}
|
|
646
|
+
if (length < 3)
|
|
647
|
+
return fromCharCode(a, b)
|
|
648
|
+
let c = src[position++];
|
|
649
|
+
if ((c & 0x80) > 0) {
|
|
650
|
+
position -= 3;
|
|
651
|
+
return
|
|
652
|
+
}
|
|
653
|
+
return fromCharCode(a, b, c)
|
|
654
|
+
}
|
|
655
|
+
} else {
|
|
656
|
+
let a = src[position++];
|
|
657
|
+
let b = src[position++];
|
|
658
|
+
let c = src[position++];
|
|
659
|
+
let d = src[position++];
|
|
660
|
+
if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
|
|
661
|
+
position -= 4;
|
|
662
|
+
return
|
|
663
|
+
}
|
|
664
|
+
if (length < 6) {
|
|
665
|
+
if (length === 4)
|
|
666
|
+
return fromCharCode(a, b, c, d)
|
|
667
|
+
else {
|
|
668
|
+
let e = src[position++];
|
|
669
|
+
if ((e & 0x80) > 0) {
|
|
670
|
+
position -= 5;
|
|
671
|
+
return
|
|
672
|
+
}
|
|
673
|
+
return fromCharCode(a, b, c, d, e)
|
|
674
|
+
}
|
|
675
|
+
} else if (length < 8) {
|
|
676
|
+
let e = src[position++];
|
|
677
|
+
let f = src[position++];
|
|
678
|
+
if ((e & 0x80) > 0 || (f & 0x80) > 0) {
|
|
679
|
+
position -= 6;
|
|
680
|
+
return
|
|
681
|
+
}
|
|
682
|
+
if (length < 7)
|
|
683
|
+
return fromCharCode(a, b, c, d, e, f)
|
|
684
|
+
let g = src[position++];
|
|
685
|
+
if ((g & 0x80) > 0) {
|
|
686
|
+
position -= 7;
|
|
687
|
+
return
|
|
688
|
+
}
|
|
689
|
+
return fromCharCode(a, b, c, d, e, f, g)
|
|
690
|
+
} else {
|
|
691
|
+
let e = src[position++];
|
|
692
|
+
let f = src[position++];
|
|
693
|
+
let g = src[position++];
|
|
694
|
+
let h = src[position++];
|
|
695
|
+
if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
|
|
696
|
+
position -= 8;
|
|
697
|
+
return
|
|
698
|
+
}
|
|
699
|
+
if (length < 10) {
|
|
700
|
+
if (length === 8)
|
|
701
|
+
return fromCharCode(a, b, c, d, e, f, g, h)
|
|
702
|
+
else {
|
|
703
|
+
let i = src[position++];
|
|
704
|
+
if ((i & 0x80) > 0) {
|
|
705
|
+
position -= 9;
|
|
706
|
+
return
|
|
707
|
+
}
|
|
708
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i)
|
|
709
|
+
}
|
|
710
|
+
} else if (length < 12) {
|
|
711
|
+
let i = src[position++];
|
|
712
|
+
let j = src[position++];
|
|
713
|
+
if ((i & 0x80) > 0 || (j & 0x80) > 0) {
|
|
714
|
+
position -= 10;
|
|
715
|
+
return
|
|
716
|
+
}
|
|
717
|
+
if (length < 11)
|
|
718
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j)
|
|
719
|
+
let k = src[position++];
|
|
720
|
+
if ((k & 0x80) > 0) {
|
|
721
|
+
position -= 11;
|
|
722
|
+
return
|
|
723
|
+
}
|
|
724
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
|
|
725
|
+
} else {
|
|
726
|
+
let i = src[position++];
|
|
727
|
+
let j = src[position++];
|
|
728
|
+
let k = src[position++];
|
|
729
|
+
let l = src[position++];
|
|
730
|
+
if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
|
|
731
|
+
position -= 12;
|
|
732
|
+
return
|
|
733
|
+
}
|
|
734
|
+
if (length < 14) {
|
|
735
|
+
if (length === 12)
|
|
736
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
|
|
737
|
+
else {
|
|
738
|
+
let m = src[position++];
|
|
739
|
+
if ((m & 0x80) > 0) {
|
|
740
|
+
position -= 13;
|
|
741
|
+
return
|
|
742
|
+
}
|
|
743
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
|
|
744
|
+
}
|
|
745
|
+
} else {
|
|
746
|
+
let m = src[position++];
|
|
747
|
+
let n = src[position++];
|
|
748
|
+
if ((m & 0x80) > 0 || (n & 0x80) > 0) {
|
|
749
|
+
position -= 14;
|
|
750
|
+
return
|
|
751
|
+
}
|
|
752
|
+
if (length < 15)
|
|
753
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
|
|
754
|
+
let o = src[position++];
|
|
755
|
+
if ((o & 0x80) > 0) {
|
|
756
|
+
position -= 15;
|
|
757
|
+
return
|
|
758
|
+
}
|
|
759
|
+
return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
function readOnlyJSString() {
|
|
767
|
+
let token = src[position++];
|
|
768
|
+
let length;
|
|
769
|
+
if (token < 0xc0) {
|
|
770
|
+
// fixstr
|
|
771
|
+
length = token - 0xa0;
|
|
772
|
+
} else {
|
|
773
|
+
switch(token) {
|
|
774
|
+
case 0xd9:
|
|
775
|
+
// str 8
|
|
776
|
+
length = src[position++];
|
|
777
|
+
break
|
|
778
|
+
case 0xda:
|
|
779
|
+
// str 16
|
|
780
|
+
length = dataView.getUint16(position);
|
|
781
|
+
position += 2;
|
|
782
|
+
break
|
|
783
|
+
case 0xdb:
|
|
784
|
+
// str 32
|
|
785
|
+
length = dataView.getUint32(position);
|
|
786
|
+
position += 4;
|
|
787
|
+
break
|
|
788
|
+
default:
|
|
789
|
+
throw new Error('Expected string')
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
return readStringJS(length)
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
function readBin(length) {
|
|
797
|
+
return currentUnpackr.copyBuffers ?
|
|
798
|
+
// specifically use the copying slice (not the node one)
|
|
799
|
+
Uint8Array.prototype.slice.call(src, position, position += length) :
|
|
800
|
+
src.subarray(position, position += length)
|
|
801
|
+
}
|
|
802
|
+
function readExt(length) {
|
|
803
|
+
let type = src[position++];
|
|
804
|
+
if (currentExtensions[type]) {
|
|
805
|
+
let end;
|
|
806
|
+
return currentExtensions[type](src.subarray(position, end = (position += length)), (readPosition) => {
|
|
807
|
+
position = readPosition;
|
|
808
|
+
try {
|
|
809
|
+
return read();
|
|
810
|
+
} finally {
|
|
811
|
+
position = end;
|
|
812
|
+
}
|
|
813
|
+
})
|
|
814
|
+
}
|
|
815
|
+
else
|
|
816
|
+
throw new Error('Unknown extension type ' + type)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
var keyCache = new Array(4096);
|
|
820
|
+
function readKey() {
|
|
821
|
+
let length = src[position++];
|
|
822
|
+
if (length >= 0xa0 && length < 0xc0) {
|
|
823
|
+
// fixstr, potentially use key cache
|
|
824
|
+
length = length - 0xa0;
|
|
825
|
+
if (srcStringEnd >= position) // if it has been extracted, must use it (and faster anyway)
|
|
826
|
+
return srcString.slice(position - srcStringStart, (position += length) - srcStringStart)
|
|
827
|
+
else if (!(srcStringEnd == 0 && srcEnd < 180))
|
|
828
|
+
return readFixedString(length)
|
|
829
|
+
} else { // not cacheable, go back and do a standard read
|
|
830
|
+
position--;
|
|
831
|
+
return read()
|
|
832
|
+
}
|
|
833
|
+
let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 0)) & 0xfff;
|
|
834
|
+
let entry = keyCache[key];
|
|
835
|
+
let checkPosition = position;
|
|
836
|
+
let end = position + length - 3;
|
|
837
|
+
let chunk;
|
|
838
|
+
let i = 0;
|
|
839
|
+
if (entry && entry.bytes == length) {
|
|
840
|
+
while (checkPosition < end) {
|
|
841
|
+
chunk = dataView.getUint32(checkPosition);
|
|
842
|
+
if (chunk != entry[i++]) {
|
|
843
|
+
checkPosition = 0x70000000;
|
|
844
|
+
break
|
|
845
|
+
}
|
|
846
|
+
checkPosition += 4;
|
|
847
|
+
}
|
|
848
|
+
end += 3;
|
|
849
|
+
while (checkPosition < end) {
|
|
850
|
+
chunk = src[checkPosition++];
|
|
851
|
+
if (chunk != entry[i++]) {
|
|
852
|
+
checkPosition = 0x70000000;
|
|
853
|
+
break
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
if (checkPosition === end) {
|
|
857
|
+
position = checkPosition;
|
|
858
|
+
return entry.string
|
|
859
|
+
}
|
|
860
|
+
end -= 3;
|
|
861
|
+
checkPosition = position;
|
|
862
|
+
}
|
|
863
|
+
entry = [];
|
|
864
|
+
keyCache[key] = entry;
|
|
865
|
+
entry.bytes = length;
|
|
866
|
+
while (checkPosition < end) {
|
|
867
|
+
chunk = dataView.getUint32(checkPosition);
|
|
868
|
+
entry.push(chunk);
|
|
869
|
+
checkPosition += 4;
|
|
870
|
+
}
|
|
871
|
+
end += 3;
|
|
872
|
+
while (checkPosition < end) {
|
|
873
|
+
chunk = src[checkPosition++];
|
|
874
|
+
entry.push(chunk);
|
|
875
|
+
}
|
|
876
|
+
// for small blocks, avoiding the overhead of the extract call is helpful
|
|
877
|
+
let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
|
|
878
|
+
if (string != null)
|
|
879
|
+
return entry.string = string
|
|
880
|
+
return entry.string = readFixedString(length)
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// the registration of the record definition extension (as "r")
|
|
884
|
+
const recordDefinition = (id, highByte) => {
|
|
885
|
+
var structure = read();
|
|
886
|
+
let firstByte = id;
|
|
887
|
+
if (highByte !== undefined) {
|
|
888
|
+
id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id);
|
|
889
|
+
structure.highByte = highByte;
|
|
890
|
+
}
|
|
891
|
+
let existingStructure = currentStructures[id];
|
|
892
|
+
if (existingStructure && existingStructure.isShared) {
|
|
893
|
+
(currentStructures.restoreStructures || (currentStructures.restoreStructures = []))[id] = existingStructure;
|
|
894
|
+
}
|
|
895
|
+
currentStructures[id] = structure;
|
|
896
|
+
structure.read = createStructureReader(structure, firstByte);
|
|
897
|
+
return structure.read()
|
|
898
|
+
};
|
|
899
|
+
currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
900
|
+
currentExtensions[0].noBuffer = true;
|
|
901
|
+
|
|
902
|
+
currentExtensions[0x65] = () => {
|
|
903
|
+
let data = read();
|
|
904
|
+
return (globalThis[data[0]] || Error)(data[1])
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
currentExtensions[0x69] = (data) => {
|
|
908
|
+
// id extension (for structured clones)
|
|
909
|
+
let id = dataView.getUint32(position - 4);
|
|
910
|
+
if (!referenceMap)
|
|
911
|
+
referenceMap = new Map();
|
|
912
|
+
let token = src[position];
|
|
913
|
+
let target;
|
|
914
|
+
// TODO: handle Maps, Sets, and other types that can cycle; this is complicated, because you potentially need to read
|
|
915
|
+
// ahead past references to record structure definitions
|
|
916
|
+
if (token >= 0x90 && token < 0xa0 || token == 0xdc || token == 0xdd)
|
|
917
|
+
target = [];
|
|
918
|
+
else
|
|
919
|
+
target = {};
|
|
920
|
+
|
|
921
|
+
let refEntry = { target }; // a placeholder object
|
|
922
|
+
referenceMap.set(id, refEntry);
|
|
923
|
+
let targetProperties = read(); // read the next value as the target object to id
|
|
924
|
+
if (refEntry.used) // there is a cycle, so we have to assign properties to original target
|
|
925
|
+
return Object.assign(target, targetProperties)
|
|
926
|
+
refEntry.target = targetProperties; // the placeholder wasn't used, replace with the deserialized one
|
|
927
|
+
return targetProperties // no cycle, can just use the returned read object
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
currentExtensions[0x70] = (data) => {
|
|
931
|
+
// pointer extension (for structured clones)
|
|
932
|
+
let id = dataView.getUint32(position - 4);
|
|
933
|
+
let refEntry = referenceMap.get(id);
|
|
934
|
+
refEntry.used = true;
|
|
935
|
+
return refEntry.target
|
|
936
|
+
};
|
|
937
|
+
|
|
938
|
+
currentExtensions[0x73] = () => new Set(read());
|
|
939
|
+
|
|
940
|
+
const typedArrays = ['Int8','Uint8','Uint8Clamped','Int16','Uint16','Int32','Uint32','Float32','Float64','BigInt64','BigUint64'].map(type => type + 'Array');
|
|
941
|
+
|
|
942
|
+
currentExtensions[0x74] = (data) => {
|
|
943
|
+
let typeCode = data[0];
|
|
944
|
+
let typedArrayName = typedArrays[typeCode];
|
|
945
|
+
if (!typedArrayName)
|
|
946
|
+
throw new Error('Could not find typed array for code ' + typeCode)
|
|
947
|
+
// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
948
|
+
return new globalThis[typedArrayName](Uint8Array.prototype.slice.call(data, 1).buffer)
|
|
949
|
+
};
|
|
950
|
+
currentExtensions[0x78] = () => {
|
|
951
|
+
let data = read();
|
|
952
|
+
return new RegExp(data[0], data[1])
|
|
953
|
+
};
|
|
954
|
+
const TEMP_BUNDLE = [];
|
|
955
|
+
currentExtensions[0x62] = (data) => {
|
|
956
|
+
let dataSize = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
|
|
957
|
+
let dataPosition = position;
|
|
958
|
+
position += dataSize - data.length;
|
|
959
|
+
bundledStrings = TEMP_BUNDLE;
|
|
960
|
+
bundledStrings = [readOnlyJSString(), readOnlyJSString()];
|
|
961
|
+
bundledStrings.position0 = 0;
|
|
962
|
+
bundledStrings.position1 = 0;
|
|
963
|
+
bundledStrings.postBundlePosition = position;
|
|
964
|
+
position = dataPosition;
|
|
965
|
+
return read()
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
currentExtensions[0xff] = (data) => {
|
|
969
|
+
// 32-bit date extension
|
|
970
|
+
if (data.length == 4)
|
|
971
|
+
return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
|
|
972
|
+
else if (data.length == 8)
|
|
973
|
+
return new Date(
|
|
974
|
+
((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
|
|
975
|
+
((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
|
|
976
|
+
else if (data.length == 12)// TODO: Implement support for negative
|
|
977
|
+
return new Date(
|
|
978
|
+
((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
|
|
979
|
+
(((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
|
|
980
|
+
else
|
|
981
|
+
return new Date('invalid')
|
|
982
|
+
}; // notepack defines extension 0 to mean undefined, so use that as the default here
|
|
983
|
+
// registration of bulk record definition?
|
|
984
|
+
// currentExtensions[0x52] = () =>
|
|
985
|
+
|
|
986
|
+
function saveState(callback) {
|
|
987
|
+
let savedSrcEnd = srcEnd;
|
|
988
|
+
let savedPosition = position;
|
|
989
|
+
let savedSrcStringStart = srcStringStart;
|
|
990
|
+
let savedSrcStringEnd = srcStringEnd;
|
|
991
|
+
let savedSrcString = srcString;
|
|
992
|
+
let savedReferenceMap = referenceMap;
|
|
993
|
+
let savedBundledStrings = bundledStrings;
|
|
994
|
+
|
|
995
|
+
// TODO: We may need to revisit this if we do more external calls to user code (since it could be slow)
|
|
996
|
+
let savedSrc = new Uint8Array(src.slice(0, srcEnd)); // we copy the data in case it changes while external data is processed
|
|
997
|
+
let savedStructures = currentStructures;
|
|
998
|
+
let savedStructuresContents = currentStructures.slice(0, currentStructures.length);
|
|
999
|
+
let savedPackr = currentUnpackr;
|
|
1000
|
+
let savedSequentialMode = sequentialMode;
|
|
1001
|
+
let value = callback();
|
|
1002
|
+
srcEnd = savedSrcEnd;
|
|
1003
|
+
position = savedPosition;
|
|
1004
|
+
srcStringStart = savedSrcStringStart;
|
|
1005
|
+
srcStringEnd = savedSrcStringEnd;
|
|
1006
|
+
srcString = savedSrcString;
|
|
1007
|
+
referenceMap = savedReferenceMap;
|
|
1008
|
+
bundledStrings = savedBundledStrings;
|
|
1009
|
+
src = savedSrc;
|
|
1010
|
+
sequentialMode = savedSequentialMode;
|
|
1011
|
+
currentStructures = savedStructures;
|
|
1012
|
+
currentStructures.splice(0, currentStructures.length, ...savedStructuresContents);
|
|
1013
|
+
currentUnpackr = savedPackr;
|
|
1014
|
+
dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
|
|
1015
|
+
return value
|
|
1016
|
+
}
|
|
1017
|
+
function clearSource() {
|
|
1018
|
+
src = null;
|
|
1019
|
+
referenceMap = null;
|
|
1020
|
+
currentStructures = null;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
1024
|
+
for (let i = 0; i < 256; i++) {
|
|
1025
|
+
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
|
1026
|
+
}
|
|
1027
|
+
var defaultUnpackr = new Unpackr({ useRecords: false });
|
|
1028
|
+
function setReadStruct(updatedReadStruct, loadedStructs) {
|
|
1029
|
+
readStruct = updatedReadStruct;
|
|
1030
|
+
onLoadedStructures = loadedStructs;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let textEncoder;
|
|
1034
|
+
try {
|
|
1035
|
+
textEncoder = new TextEncoder();
|
|
1036
|
+
} catch (error) {}
|
|
1037
|
+
let extensions, extensionClasses;
|
|
1038
|
+
const hasNodeBuffer = typeof Buffer !== 'undefined';
|
|
1039
|
+
const ByteArrayAllocate = hasNodeBuffer ?
|
|
1040
|
+
function(length) { return Buffer.allocUnsafeSlow(length) } : Uint8Array;
|
|
1041
|
+
const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
|
|
1042
|
+
const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
|
|
1043
|
+
let target, keysTarget;
|
|
1044
|
+
let targetView;
|
|
1045
|
+
let position$1 = 0;
|
|
1046
|
+
let safeEnd;
|
|
1047
|
+
let bundledStrings$1 = null;
|
|
1048
|
+
let writeStructSlots, prepareStructures;
|
|
1049
|
+
const MAX_BUNDLE_SIZE = 0xf000;
|
|
1050
|
+
const hasNonLatin = /[\u0080-\uFFFF]/;
|
|
1051
|
+
const RECORD_SYMBOL = Symbol('record-id');
|
|
1052
|
+
class Packr extends Unpackr {
|
|
1053
|
+
constructor(options) {
|
|
1054
|
+
super(options);
|
|
1055
|
+
this.offset = 0;
|
|
1056
|
+
let start;
|
|
1057
|
+
let hasSharedUpdate;
|
|
1058
|
+
let structures;
|
|
1059
|
+
let referenceMap;
|
|
1060
|
+
let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
|
|
1061
|
+
return target.utf8Write(string, position, 0xffffffff)
|
|
1062
|
+
} : (textEncoder && textEncoder.encodeInto) ?
|
|
1063
|
+
function(string, position) {
|
|
1064
|
+
return textEncoder.encodeInto(string, target.subarray(position)).written
|
|
1065
|
+
} : false;
|
|
1066
|
+
|
|
1067
|
+
let packr = this;
|
|
1068
|
+
if (!options)
|
|
1069
|
+
options = {};
|
|
1070
|
+
let isSequential = options && options.sequential;
|
|
1071
|
+
let hasSharedStructures = options.structures || options.saveStructures;
|
|
1072
|
+
let maxSharedStructures = options.maxSharedStructures;
|
|
1073
|
+
if (maxSharedStructures == null)
|
|
1074
|
+
maxSharedStructures = hasSharedStructures ? 32 : 0;
|
|
1075
|
+
if (maxSharedStructures > 8160)
|
|
1076
|
+
throw new Error('Maximum maxSharedStructure is 8160')
|
|
1077
|
+
if (options.structuredClone && options.moreTypes == undefined) {
|
|
1078
|
+
options.moreTypes = true;
|
|
1079
|
+
}
|
|
1080
|
+
let maxOwnStructures = options.maxOwnStructures;
|
|
1081
|
+
if (maxOwnStructures == null)
|
|
1082
|
+
maxOwnStructures = hasSharedStructures ? 32 : 64;
|
|
1083
|
+
if (!this.structures && options.useRecords != false)
|
|
1084
|
+
this.structures = [];
|
|
1085
|
+
// two byte record ids for shared structures
|
|
1086
|
+
let useTwoByteRecords = maxSharedStructures > 32 || (maxOwnStructures + maxSharedStructures > 64);
|
|
1087
|
+
let sharedLimitId = maxSharedStructures + 0x40;
|
|
1088
|
+
let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
|
|
1089
|
+
if (maxStructureId > 8256) {
|
|
1090
|
+
throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192')
|
|
1091
|
+
}
|
|
1092
|
+
let recordIdsToRemove = [];
|
|
1093
|
+
let transitionsCount = 0;
|
|
1094
|
+
let serializationsSinceTransitionRebuild = 0;
|
|
1095
|
+
|
|
1096
|
+
this.pack = this.encode = function(value, encodeOptions) {
|
|
1097
|
+
if (!target) {
|
|
1098
|
+
target = new ByteArrayAllocate(8192);
|
|
1099
|
+
targetView = target.dataView = new DataView(target.buffer, 0, 8192);
|
|
1100
|
+
position$1 = 0;
|
|
1101
|
+
}
|
|
1102
|
+
safeEnd = target.length - 10;
|
|
1103
|
+
if (safeEnd - position$1 < 0x800) {
|
|
1104
|
+
// don't start too close to the end,
|
|
1105
|
+
target = new ByteArrayAllocate(target.length);
|
|
1106
|
+
targetView = target.dataView = new DataView(target.buffer, 0, target.length);
|
|
1107
|
+
safeEnd = target.length - 10;
|
|
1108
|
+
position$1 = 0;
|
|
1109
|
+
} else
|
|
1110
|
+
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
1111
|
+
start = position$1;
|
|
1112
|
+
referenceMap = packr.structuredClone ? new Map() : null;
|
|
1113
|
+
if (packr.bundleStrings && typeof value !== 'string') {
|
|
1114
|
+
bundledStrings$1 = [];
|
|
1115
|
+
bundledStrings$1.size = Infinity; // force a new bundle start on first string
|
|
1116
|
+
} else
|
|
1117
|
+
bundledStrings$1 = null;
|
|
1118
|
+
structures = packr.structures;
|
|
1119
|
+
if (structures) {
|
|
1120
|
+
if (structures.uninitialized)
|
|
1121
|
+
structures = packr._mergeStructures(packr.getStructures());
|
|
1122
|
+
let sharedLength = structures.sharedLength || 0;
|
|
1123
|
+
if (sharedLength > maxSharedStructures) {
|
|
1124
|
+
//if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
|
|
1125
|
+
throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
|
|
1126
|
+
}
|
|
1127
|
+
if (!structures.transitions) {
|
|
1128
|
+
// rebuild our structure transitions
|
|
1129
|
+
structures.transitions = Object.create(null);
|
|
1130
|
+
for (let i = 0; i < sharedLength; i++) {
|
|
1131
|
+
let keys = structures[i];
|
|
1132
|
+
if (!keys)
|
|
1133
|
+
continue
|
|
1134
|
+
let nextTransition, transition = structures.transitions;
|
|
1135
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
1136
|
+
let key = keys[j];
|
|
1137
|
+
nextTransition = transition[key];
|
|
1138
|
+
if (!nextTransition) {
|
|
1139
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1140
|
+
}
|
|
1141
|
+
transition = nextTransition;
|
|
1142
|
+
}
|
|
1143
|
+
transition[RECORD_SYMBOL] = i + 0x40;
|
|
1144
|
+
}
|
|
1145
|
+
this.lastNamedStructuresLength = sharedLength;
|
|
1146
|
+
}
|
|
1147
|
+
if (!isSequential) {
|
|
1148
|
+
structures.nextId = sharedLength + 0x40;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
if (hasSharedUpdate)
|
|
1152
|
+
hasSharedUpdate = false;
|
|
1153
|
+
try {
|
|
1154
|
+
if (packr.randomAccessStructure && value.constructor && value.constructor === Object)
|
|
1155
|
+
writeStruct(value);
|
|
1156
|
+
else
|
|
1157
|
+
pack(value);
|
|
1158
|
+
if (bundledStrings$1) {
|
|
1159
|
+
writeBundles(start, pack);
|
|
1160
|
+
}
|
|
1161
|
+
packr.offset = position$1; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
1162
|
+
if (referenceMap && referenceMap.idsToInsert) {
|
|
1163
|
+
position$1 += referenceMap.idsToInsert.length * 6;
|
|
1164
|
+
if (position$1 > safeEnd)
|
|
1165
|
+
makeRoom(position$1);
|
|
1166
|
+
packr.offset = position$1;
|
|
1167
|
+
let serialized = insertIds(target.subarray(start, position$1), referenceMap.idsToInsert);
|
|
1168
|
+
referenceMap = null;
|
|
1169
|
+
return serialized
|
|
1170
|
+
}
|
|
1171
|
+
if (encodeOptions & REUSE_BUFFER_MODE) {
|
|
1172
|
+
target.start = start;
|
|
1173
|
+
target.end = position$1;
|
|
1174
|
+
return target
|
|
1175
|
+
}
|
|
1176
|
+
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
1177
|
+
} finally {
|
|
1178
|
+
if (structures) {
|
|
1179
|
+
if (serializationsSinceTransitionRebuild < 10)
|
|
1180
|
+
serializationsSinceTransitionRebuild++;
|
|
1181
|
+
let sharedLength = structures.sharedLength || maxSharedStructures;
|
|
1182
|
+
if (structures.length > sharedLength)
|
|
1183
|
+
structures.length = sharedLength;
|
|
1184
|
+
if (transitionsCount > 10000) {
|
|
1185
|
+
// force a rebuild occasionally after a lot of transitions so it can get cleaned up
|
|
1186
|
+
structures.transitions = null;
|
|
1187
|
+
serializationsSinceTransitionRebuild = 0;
|
|
1188
|
+
transitionsCount = 0;
|
|
1189
|
+
if (recordIdsToRemove.length > 0)
|
|
1190
|
+
recordIdsToRemove = [];
|
|
1191
|
+
} else if (recordIdsToRemove.length > 0 && !isSequential) {
|
|
1192
|
+
for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
|
|
1193
|
+
recordIdsToRemove[i][RECORD_SYMBOL] = 0;
|
|
1194
|
+
}
|
|
1195
|
+
recordIdsToRemove = [];
|
|
1196
|
+
}
|
|
1197
|
+
if (hasSharedUpdate && packr.saveStructures) {
|
|
1198
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
1199
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
1200
|
+
let newSharedData = prepareStructures ? prepareStructures(structures, packr) : structures;
|
|
1201
|
+
if (packr.saveStructures(newSharedData, newSharedData.isCompatible || packr.lastNamedStructuresLength || 0) === false) {
|
|
1202
|
+
// get updated structures and try again if the update failed
|
|
1203
|
+
packr._mergeStructures(packr.getStructures());
|
|
1204
|
+
return packr.pack(value)
|
|
1205
|
+
}
|
|
1206
|
+
packr.lastNamedStructuresLength = sharedLength;
|
|
1207
|
+
return returnBuffer
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
if (encodeOptions & RESET_BUFFER_MODE)
|
|
1211
|
+
position$1 = start;
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
const pack = (value) => {
|
|
1215
|
+
if (position$1 > safeEnd)
|
|
1216
|
+
target = makeRoom(position$1);
|
|
1217
|
+
|
|
1218
|
+
var type = typeof value;
|
|
1219
|
+
var length;
|
|
1220
|
+
if (type === 'string') {
|
|
1221
|
+
let strLength = value.length;
|
|
1222
|
+
if (bundledStrings$1 && strLength >= 4 && strLength < 0x1000) {
|
|
1223
|
+
if ((bundledStrings$1.size += strLength) > MAX_BUNDLE_SIZE) {
|
|
1224
|
+
let extStart;
|
|
1225
|
+
let maxBytes = (bundledStrings$1[0] ? bundledStrings$1[0].length * 3 + bundledStrings$1[1].length : 0) + 10;
|
|
1226
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1227
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1228
|
+
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
|
|
1229
|
+
target[position$1] = 0xc8; // ext 16
|
|
1230
|
+
position$1 += 3; // reserve for the writing bundle size
|
|
1231
|
+
target[position$1++] = 0x62; // 'b'
|
|
1232
|
+
extStart = position$1 - start;
|
|
1233
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1234
|
+
writeBundles(start, pack); // write the last bundles
|
|
1235
|
+
targetView.setUint16(extStart + start - 3, position$1 - start - extStart);
|
|
1236
|
+
} 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)
|
|
1237
|
+
target[position$1++] = 0xd6; // fixext 4
|
|
1238
|
+
target[position$1++] = 0x62; // 'b'
|
|
1239
|
+
extStart = position$1 - start;
|
|
1240
|
+
position$1 += 4; // reserve for writing bundle reference
|
|
1241
|
+
}
|
|
1242
|
+
bundledStrings$1 = ['', '']; // create new ones
|
|
1243
|
+
bundledStrings$1.size = 0;
|
|
1244
|
+
bundledStrings$1.position = extStart;
|
|
1245
|
+
}
|
|
1246
|
+
let twoByte = hasNonLatin.test(value);
|
|
1247
|
+
bundledStrings$1[twoByte ? 0 : 1] += value;
|
|
1248
|
+
target[position$1++] = 0xc1;
|
|
1249
|
+
pack(twoByte ? -strLength : strLength);
|
|
1250
|
+
return
|
|
1251
|
+
}
|
|
1252
|
+
let headerSize;
|
|
1253
|
+
// first we estimate the header size, so we can write to the correct location
|
|
1254
|
+
if (strLength < 0x20) {
|
|
1255
|
+
headerSize = 1;
|
|
1256
|
+
} else if (strLength < 0x100) {
|
|
1257
|
+
headerSize = 2;
|
|
1258
|
+
} else if (strLength < 0x10000) {
|
|
1259
|
+
headerSize = 3;
|
|
1260
|
+
} else {
|
|
1261
|
+
headerSize = 5;
|
|
1262
|
+
}
|
|
1263
|
+
let maxBytes = strLength * 3;
|
|
1264
|
+
if (position$1 + maxBytes > safeEnd)
|
|
1265
|
+
target = makeRoom(position$1 + maxBytes);
|
|
1266
|
+
|
|
1267
|
+
if (strLength < 0x40 || !encodeUtf8) {
|
|
1268
|
+
let i, c1, c2, strPosition = position$1 + headerSize;
|
|
1269
|
+
for (i = 0; i < strLength; i++) {
|
|
1270
|
+
c1 = value.charCodeAt(i);
|
|
1271
|
+
if (c1 < 0x80) {
|
|
1272
|
+
target[strPosition++] = c1;
|
|
1273
|
+
} else if (c1 < 0x800) {
|
|
1274
|
+
target[strPosition++] = c1 >> 6 | 0xc0;
|
|
1275
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1276
|
+
} else if (
|
|
1277
|
+
(c1 & 0xfc00) === 0xd800 &&
|
|
1278
|
+
((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
|
|
1279
|
+
) {
|
|
1280
|
+
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
|
|
1281
|
+
i++;
|
|
1282
|
+
target[strPosition++] = c1 >> 18 | 0xf0;
|
|
1283
|
+
target[strPosition++] = c1 >> 12 & 0x3f | 0x80;
|
|
1284
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1285
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1286
|
+
} else {
|
|
1287
|
+
target[strPosition++] = c1 >> 12 | 0xe0;
|
|
1288
|
+
target[strPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
1289
|
+
target[strPosition++] = c1 & 0x3f | 0x80;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
length = strPosition - position$1 - headerSize;
|
|
1293
|
+
} else {
|
|
1294
|
+
length = encodeUtf8(value, position$1 + headerSize);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
if (length < 0x20) {
|
|
1298
|
+
target[position$1++] = 0xa0 | length;
|
|
1299
|
+
} else if (length < 0x100) {
|
|
1300
|
+
if (headerSize < 2) {
|
|
1301
|
+
target.copyWithin(position$1 + 2, position$1 + 1, position$1 + 1 + length);
|
|
1302
|
+
}
|
|
1303
|
+
target[position$1++] = 0xd9;
|
|
1304
|
+
target[position$1++] = length;
|
|
1305
|
+
} else if (length < 0x10000) {
|
|
1306
|
+
if (headerSize < 3) {
|
|
1307
|
+
target.copyWithin(position$1 + 3, position$1 + 2, position$1 + 2 + length);
|
|
1308
|
+
}
|
|
1309
|
+
target[position$1++] = 0xda;
|
|
1310
|
+
target[position$1++] = length >> 8;
|
|
1311
|
+
target[position$1++] = length & 0xff;
|
|
1312
|
+
} else {
|
|
1313
|
+
if (headerSize < 5) {
|
|
1314
|
+
target.copyWithin(position$1 + 5, position$1 + 3, position$1 + 3 + length);
|
|
1315
|
+
}
|
|
1316
|
+
target[position$1++] = 0xdb;
|
|
1317
|
+
targetView.setUint32(position$1, length);
|
|
1318
|
+
position$1 += 4;
|
|
1319
|
+
}
|
|
1320
|
+
position$1 += length;
|
|
1321
|
+
} else if (type === 'number') {
|
|
1322
|
+
if (value >>> 0 === value) {// positive integer, 32-bit or less
|
|
1323
|
+
// positive uint
|
|
1324
|
+
if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
|
|
1325
|
+
target[position$1++] = value;
|
|
1326
|
+
} else if (value < 0x100) {
|
|
1327
|
+
target[position$1++] = 0xcc;
|
|
1328
|
+
target[position$1++] = value;
|
|
1329
|
+
} else if (value < 0x10000) {
|
|
1330
|
+
target[position$1++] = 0xcd;
|
|
1331
|
+
target[position$1++] = value >> 8;
|
|
1332
|
+
target[position$1++] = value & 0xff;
|
|
1333
|
+
} else {
|
|
1334
|
+
target[position$1++] = 0xce;
|
|
1335
|
+
targetView.setUint32(position$1, value);
|
|
1336
|
+
position$1 += 4;
|
|
1337
|
+
}
|
|
1338
|
+
} else if (value >> 0 === value) { // negative integer
|
|
1339
|
+
if (value >= -0x20) {
|
|
1340
|
+
target[position$1++] = 0x100 + value;
|
|
1341
|
+
} else if (value >= -0x80) {
|
|
1342
|
+
target[position$1++] = 0xd0;
|
|
1343
|
+
target[position$1++] = value + 0x100;
|
|
1344
|
+
} else if (value >= -0x8000) {
|
|
1345
|
+
target[position$1++] = 0xd1;
|
|
1346
|
+
targetView.setInt16(position$1, value);
|
|
1347
|
+
position$1 += 2;
|
|
1348
|
+
} else {
|
|
1349
|
+
target[position$1++] = 0xd2;
|
|
1350
|
+
targetView.setInt32(position$1, value);
|
|
1351
|
+
position$1 += 4;
|
|
1352
|
+
}
|
|
1353
|
+
} else {
|
|
1354
|
+
let useFloat32;
|
|
1355
|
+
if ((useFloat32 = this.useFloat32) > 0 && value < 0x100000000 && value >= -0x80000000) {
|
|
1356
|
+
target[position$1++] = 0xca;
|
|
1357
|
+
targetView.setFloat32(position$1, value);
|
|
1358
|
+
let xShifted;
|
|
1359
|
+
if (useFloat32 < 4 ||
|
|
1360
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1361
|
+
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1362
|
+
position$1 += 4;
|
|
1363
|
+
return
|
|
1364
|
+
} else
|
|
1365
|
+
position$1--; // move back into position for writing a double
|
|
1366
|
+
}
|
|
1367
|
+
target[position$1++] = 0xcb;
|
|
1368
|
+
targetView.setFloat64(position$1, value);
|
|
1369
|
+
position$1 += 8;
|
|
1370
|
+
}
|
|
1371
|
+
} else if (type === 'object') {
|
|
1372
|
+
if (!value)
|
|
1373
|
+
target[position$1++] = 0xc0;
|
|
1374
|
+
else {
|
|
1375
|
+
if (referenceMap) {
|
|
1376
|
+
let referee = referenceMap.get(value);
|
|
1377
|
+
if (referee) {
|
|
1378
|
+
if (!referee.id) {
|
|
1379
|
+
let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = []);
|
|
1380
|
+
referee.id = idsToInsert.push(referee);
|
|
1381
|
+
}
|
|
1382
|
+
target[position$1++] = 0xd6; // fixext 4
|
|
1383
|
+
target[position$1++] = 0x70; // "p" for pointer
|
|
1384
|
+
targetView.setUint32(position$1, referee.id);
|
|
1385
|
+
position$1 += 4;
|
|
1386
|
+
return
|
|
1387
|
+
} else
|
|
1388
|
+
referenceMap.set(value, { offset: position$1 - start });
|
|
1389
|
+
}
|
|
1390
|
+
let constructor = value.constructor;
|
|
1391
|
+
if (constructor === Object) {
|
|
1392
|
+
writeObject(value, true);
|
|
1393
|
+
} else if (constructor === Array) {
|
|
1394
|
+
length = value.length;
|
|
1395
|
+
if (length < 0x10) {
|
|
1396
|
+
target[position$1++] = 0x90 | length;
|
|
1397
|
+
} else if (length < 0x10000) {
|
|
1398
|
+
target[position$1++] = 0xdc;
|
|
1399
|
+
target[position$1++] = length >> 8;
|
|
1400
|
+
target[position$1++] = length & 0xff;
|
|
1401
|
+
} else {
|
|
1402
|
+
target[position$1++] = 0xdd;
|
|
1403
|
+
targetView.setUint32(position$1, length);
|
|
1404
|
+
position$1 += 4;
|
|
1405
|
+
}
|
|
1406
|
+
for (let i = 0; i < length; i++) {
|
|
1407
|
+
pack(value[i]);
|
|
1408
|
+
}
|
|
1409
|
+
} else if (constructor === Map) {
|
|
1410
|
+
length = value.size;
|
|
1411
|
+
if (length < 0x10) {
|
|
1412
|
+
target[position$1++] = 0x80 | length;
|
|
1413
|
+
} else if (length < 0x10000) {
|
|
1414
|
+
target[position$1++] = 0xde;
|
|
1415
|
+
target[position$1++] = length >> 8;
|
|
1416
|
+
target[position$1++] = length & 0xff;
|
|
1417
|
+
} else {
|
|
1418
|
+
target[position$1++] = 0xdf;
|
|
1419
|
+
targetView.setUint32(position$1, length);
|
|
1420
|
+
position$1 += 4;
|
|
1421
|
+
}
|
|
1422
|
+
for (let [ key, entryValue ] of value) {
|
|
1423
|
+
pack(key);
|
|
1424
|
+
pack(entryValue);
|
|
1425
|
+
}
|
|
1426
|
+
} else {
|
|
1427
|
+
for (let i = 0, l = extensions.length; i < l; i++) {
|
|
1428
|
+
let extensionClass = extensionClasses[i];
|
|
1429
|
+
if (value instanceof extensionClass) {
|
|
1430
|
+
let extension = extensions[i];
|
|
1431
|
+
if (extension.write) {
|
|
1432
|
+
if (extension.type) {
|
|
1433
|
+
target[position$1++] = 0xd4; // one byte "tag" extension
|
|
1434
|
+
target[position$1++] = extension.type;
|
|
1435
|
+
target[position$1++] = 0;
|
|
1436
|
+
}
|
|
1437
|
+
pack(extension.write.call(this, value));
|
|
1438
|
+
return
|
|
1439
|
+
}
|
|
1440
|
+
let currentTarget = target;
|
|
1441
|
+
let currentTargetView = targetView;
|
|
1442
|
+
let currentPosition = position$1;
|
|
1443
|
+
target = null;
|
|
1444
|
+
let result;
|
|
1445
|
+
try {
|
|
1446
|
+
result = extension.pack.call(this, value, (size) => {
|
|
1447
|
+
// restore target and use it
|
|
1448
|
+
target = currentTarget;
|
|
1449
|
+
currentTarget = null;
|
|
1450
|
+
position$1 += size;
|
|
1451
|
+
if (position$1 > safeEnd)
|
|
1452
|
+
makeRoom(position$1);
|
|
1453
|
+
return {
|
|
1454
|
+
target, targetView, position: position$1 - size
|
|
1455
|
+
}
|
|
1456
|
+
}, pack);
|
|
1457
|
+
} finally {
|
|
1458
|
+
// restore current target information (unless already restored)
|
|
1459
|
+
if (currentTarget) {
|
|
1460
|
+
target = currentTarget;
|
|
1461
|
+
targetView = currentTargetView;
|
|
1462
|
+
position$1 = currentPosition;
|
|
1463
|
+
safeEnd = target.length - 10;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (result) {
|
|
1467
|
+
if (result.length + position$1 > safeEnd)
|
|
1468
|
+
makeRoom(result.length + position$1);
|
|
1469
|
+
position$1 = writeExtensionData(result, target, position$1, extension.type);
|
|
1470
|
+
}
|
|
1471
|
+
return
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
// no extension found, write as object
|
|
1475
|
+
writeObject(value, !value.hasOwnProperty); // if it doesn't have hasOwnProperty, don't do hasOwnProperty checks
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
} else if (type === 'boolean') {
|
|
1479
|
+
target[position$1++] = value ? 0xc3 : 0xc2;
|
|
1480
|
+
} else if (type === 'bigint') {
|
|
1481
|
+
if (value < (BigInt(1)<<BigInt(63)) && value >= -(BigInt(1)<<BigInt(63))) {
|
|
1482
|
+
// use a signed int as long as it fits
|
|
1483
|
+
target[position$1++] = 0xd3;
|
|
1484
|
+
targetView.setBigInt64(position$1, value);
|
|
1485
|
+
} else if (value < (BigInt(1)<<BigInt(64)) && value > 0) {
|
|
1486
|
+
// if we can fit an unsigned int, use that
|
|
1487
|
+
target[position$1++] = 0xcf;
|
|
1488
|
+
targetView.setBigUint64(position$1, value);
|
|
1489
|
+
} else {
|
|
1490
|
+
// overflow
|
|
1491
|
+
if (this.largeBigIntToFloat) {
|
|
1492
|
+
target[position$1++] = 0xcb;
|
|
1493
|
+
targetView.setFloat64(position$1, Number(value));
|
|
1494
|
+
} else {
|
|
1495
|
+
throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, set largeBigIntToFloat to convert to float-64')
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
position$1 += 8;
|
|
1499
|
+
} else if (type === 'undefined') {
|
|
1500
|
+
if (this.encodeUndefinedAsNil)
|
|
1501
|
+
target[position$1++] = 0xc0;
|
|
1502
|
+
else {
|
|
1503
|
+
target[position$1++] = 0xd4; // a number of implementations use fixext1 with type 0, data 0 to denote undefined, so we follow suite
|
|
1504
|
+
target[position$1++] = 0;
|
|
1505
|
+
target[position$1++] = 0;
|
|
1506
|
+
}
|
|
1507
|
+
} else if (type === 'function') {
|
|
1508
|
+
pack(this.writeFunction && this.writeFunction()); // if there is a writeFunction, use it, otherwise just encode as undefined
|
|
1509
|
+
} else {
|
|
1510
|
+
throw new Error('Unknown type: ' + type)
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
|
|
1514
|
+
const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
|
|
1515
|
+
// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
1516
|
+
let keys = Object.keys(object);
|
|
1517
|
+
let length = keys.length;
|
|
1518
|
+
if (length < 0x10) {
|
|
1519
|
+
target[position$1++] = 0x80 | length;
|
|
1520
|
+
} else if (length < 0x10000) {
|
|
1521
|
+
target[position$1++] = 0xde;
|
|
1522
|
+
target[position$1++] = length >> 8;
|
|
1523
|
+
target[position$1++] = length & 0xff;
|
|
1524
|
+
} else {
|
|
1525
|
+
target[position$1++] = 0xdf;
|
|
1526
|
+
targetView.setUint32(position$1, length);
|
|
1527
|
+
position$1 += 4;
|
|
1528
|
+
}
|
|
1529
|
+
let key;
|
|
1530
|
+
for (let i = 0; i < length; i++) {
|
|
1531
|
+
pack(key = keys[i]);
|
|
1532
|
+
pack(object[key]);
|
|
1533
|
+
}
|
|
1534
|
+
} :
|
|
1535
|
+
(object, safePrototype) => {
|
|
1536
|
+
target[position$1++] = 0xde; // always using map 16, so we can preallocate and set the length afterwards
|
|
1537
|
+
let objectOffset = position$1 - start;
|
|
1538
|
+
position$1 += 2;
|
|
1539
|
+
let size = 0;
|
|
1540
|
+
for (let key in object) {
|
|
1541
|
+
if (safePrototype || object.hasOwnProperty(key)) {
|
|
1542
|
+
pack(key);
|
|
1543
|
+
pack(object[key]);
|
|
1544
|
+
size++;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
target[objectOffset++ + start] = size >> 8;
|
|
1548
|
+
target[objectOffset + start] = size & 0xff;
|
|
1549
|
+
} :
|
|
1550
|
+
(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)
|
|
1551
|
+
(object, safePrototype) => {
|
|
1552
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1553
|
+
let objectOffset = position$1++ - start;
|
|
1554
|
+
let wroteKeys;
|
|
1555
|
+
for (let key in object) {
|
|
1556
|
+
if (safePrototype || object.hasOwnProperty(key)) {
|
|
1557
|
+
nextTransition = transition[key];
|
|
1558
|
+
if (nextTransition)
|
|
1559
|
+
transition = nextTransition;
|
|
1560
|
+
else {
|
|
1561
|
+
// record doesn't exist, create full new record and insert it
|
|
1562
|
+
let keys = Object.keys(object);
|
|
1563
|
+
let lastTransition = transition;
|
|
1564
|
+
transition = structures.transitions;
|
|
1565
|
+
let newTransitions = 0;
|
|
1566
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1567
|
+
let key = keys[i];
|
|
1568
|
+
nextTransition = transition[key];
|
|
1569
|
+
if (!nextTransition) {
|
|
1570
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1571
|
+
newTransitions++;
|
|
1572
|
+
}
|
|
1573
|
+
transition = nextTransition;
|
|
1574
|
+
}
|
|
1575
|
+
if (objectOffset + start + 1 == position$1) {
|
|
1576
|
+
// first key, so we don't need to insert, we can just write record directly
|
|
1577
|
+
position$1--;
|
|
1578
|
+
newRecord(transition, keys, newTransitions);
|
|
1579
|
+
} else // otherwise we need to insert the record, moving existing data after the record
|
|
1580
|
+
insertNewRecord(transition, keys, objectOffset, newTransitions);
|
|
1581
|
+
wroteKeys = true;
|
|
1582
|
+
transition = lastTransition[key];
|
|
1583
|
+
}
|
|
1584
|
+
pack(object[key]);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
if (!wroteKeys) {
|
|
1588
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1589
|
+
if (recordId)
|
|
1590
|
+
target[objectOffset + start] = recordId;
|
|
1591
|
+
else
|
|
1592
|
+
insertNewRecord(transition, Object.keys(object), objectOffset, 0);
|
|
1593
|
+
}
|
|
1594
|
+
} :
|
|
1595
|
+
(object, safePrototype) => {
|
|
1596
|
+
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1597
|
+
let newTransitions = 0;
|
|
1598
|
+
for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
|
|
1599
|
+
nextTransition = transition[key];
|
|
1600
|
+
if (!nextTransition) {
|
|
1601
|
+
nextTransition = transition[key] = Object.create(null);
|
|
1602
|
+
newTransitions++;
|
|
1603
|
+
}
|
|
1604
|
+
transition = nextTransition;
|
|
1605
|
+
}
|
|
1606
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
1607
|
+
if (recordId) {
|
|
1608
|
+
if (recordId >= 0x60 && useTwoByteRecords) {
|
|
1609
|
+
target[position$1++] = ((recordId -= 0x60) & 0x1f) + 0x60;
|
|
1610
|
+
target[position$1++] = recordId >> 5;
|
|
1611
|
+
} else
|
|
1612
|
+
target[position$1++] = recordId;
|
|
1613
|
+
} else {
|
|
1614
|
+
newRecord(transition, transition.__keys__ || Object.keys(object), newTransitions);
|
|
1615
|
+
}
|
|
1616
|
+
// now write the values
|
|
1617
|
+
for (let key in object)
|
|
1618
|
+
if (safePrototype || object.hasOwnProperty(key))
|
|
1619
|
+
pack(object[key]);
|
|
1620
|
+
};
|
|
1621
|
+
const makeRoom = (end) => {
|
|
1622
|
+
let newSize;
|
|
1623
|
+
if (end > 0x1000000) {
|
|
1624
|
+
// special handling for really large buffers
|
|
1625
|
+
if ((end - start) > MAX_BUFFER_SIZE)
|
|
1626
|
+
throw new Error('Packed buffer would be larger than maximum buffer size')
|
|
1627
|
+
newSize = Math.min(MAX_BUFFER_SIZE,
|
|
1628
|
+
Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
|
|
1629
|
+
} else // faster handling for smaller buffers
|
|
1630
|
+
newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12;
|
|
1631
|
+
let newBuffer = new ByteArrayAllocate(newSize);
|
|
1632
|
+
targetView = newBuffer.dataView = new DataView(newBuffer.buffer, 0, newSize);
|
|
1633
|
+
end = Math.min(end, target.length);
|
|
1634
|
+
if (target.copy)
|
|
1635
|
+
target.copy(newBuffer, 0, start, end);
|
|
1636
|
+
else
|
|
1637
|
+
newBuffer.set(target.slice(start, end));
|
|
1638
|
+
position$1 -= start;
|
|
1639
|
+
start = 0;
|
|
1640
|
+
safeEnd = newBuffer.length - 10;
|
|
1641
|
+
return target = newBuffer
|
|
1642
|
+
};
|
|
1643
|
+
const newRecord = (transition, keys, newTransitions) => {
|
|
1644
|
+
let recordId = structures.nextId;
|
|
1645
|
+
if (!recordId)
|
|
1646
|
+
recordId = 0x40;
|
|
1647
|
+
if (recordId < sharedLimitId && this.shouldShareStructure && !this.shouldShareStructure(keys)) {
|
|
1648
|
+
recordId = structures.nextOwnId;
|
|
1649
|
+
if (!(recordId < maxStructureId))
|
|
1650
|
+
recordId = sharedLimitId;
|
|
1651
|
+
structures.nextOwnId = recordId + 1;
|
|
1652
|
+
} else {
|
|
1653
|
+
if (recordId >= maxStructureId)// cycle back around
|
|
1654
|
+
recordId = sharedLimitId;
|
|
1655
|
+
structures.nextId = recordId + 1;
|
|
1656
|
+
}
|
|
1657
|
+
let highByte = keys.highByte = recordId >= 0x60 && useTwoByteRecords ? (recordId - 0x60) >> 5 : -1;
|
|
1658
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
1659
|
+
transition.__keys__ = keys;
|
|
1660
|
+
structures[recordId - 0x40] = keys;
|
|
1661
|
+
|
|
1662
|
+
if (recordId < sharedLimitId) {
|
|
1663
|
+
keys.isShared = true;
|
|
1664
|
+
structures.sharedLength = recordId - 0x3f;
|
|
1665
|
+
hasSharedUpdate = true;
|
|
1666
|
+
if (highByte >= 0) {
|
|
1667
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1668
|
+
target[position$1++] = highByte;
|
|
1669
|
+
} else {
|
|
1670
|
+
target[position$1++] = recordId;
|
|
1671
|
+
}
|
|
1672
|
+
} else {
|
|
1673
|
+
if (highByte >= 0) {
|
|
1674
|
+
target[position$1++] = 0xd5; // fixext 2
|
|
1675
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1676
|
+
target[position$1++] = (recordId & 0x1f) + 0x60;
|
|
1677
|
+
target[position$1++] = highByte;
|
|
1678
|
+
} else {
|
|
1679
|
+
target[position$1++] = 0xd4; // fixext 1
|
|
1680
|
+
target[position$1++] = 0x72; // "r" record defintion extension type
|
|
1681
|
+
target[position$1++] = recordId;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
if (newTransitions)
|
|
1685
|
+
transitionsCount += serializationsSinceTransitionRebuild * newTransitions;
|
|
1686
|
+
// record the removal of the id, we can maintain our shared structure
|
|
1687
|
+
if (recordIdsToRemove.length >= maxOwnStructures)
|
|
1688
|
+
recordIdsToRemove.shift()[RECORD_SYMBOL] = 0; // we are cycling back through, and have to remove old ones
|
|
1689
|
+
recordIdsToRemove.push(transition);
|
|
1690
|
+
pack(keys);
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
const insertNewRecord = (transition, keys, insertionOffset, newTransitions) => {
|
|
1694
|
+
let mainTarget = target;
|
|
1695
|
+
let mainPosition = position$1;
|
|
1696
|
+
let mainSafeEnd = safeEnd;
|
|
1697
|
+
let mainStart = start;
|
|
1698
|
+
target = keysTarget;
|
|
1699
|
+
position$1 = 0;
|
|
1700
|
+
start = 0;
|
|
1701
|
+
if (!target)
|
|
1702
|
+
keysTarget = target = new ByteArrayAllocate(8192);
|
|
1703
|
+
safeEnd = target.length - 10;
|
|
1704
|
+
newRecord(transition, keys, newTransitions);
|
|
1705
|
+
keysTarget = target;
|
|
1706
|
+
let keysPosition = position$1;
|
|
1707
|
+
target = mainTarget;
|
|
1708
|
+
position$1 = mainPosition;
|
|
1709
|
+
safeEnd = mainSafeEnd;
|
|
1710
|
+
start = mainStart;
|
|
1711
|
+
if (keysPosition > 1) {
|
|
1712
|
+
let newEnd = position$1 + keysPosition - 1;
|
|
1713
|
+
if (newEnd > safeEnd)
|
|
1714
|
+
makeRoom(newEnd);
|
|
1715
|
+
let insertionPosition = insertionOffset + start;
|
|
1716
|
+
target.copyWithin(insertionPosition + keysPosition, insertionPosition + 1, position$1);
|
|
1717
|
+
target.set(keysTarget.slice(0, keysPosition), insertionPosition);
|
|
1718
|
+
position$1 = newEnd;
|
|
1719
|
+
} else {
|
|
1720
|
+
target[insertionOffset + start] = keysTarget[0];
|
|
1721
|
+
}
|
|
1722
|
+
};
|
|
1723
|
+
const writeStruct = (object, safePrototype) => {
|
|
1724
|
+
let newPosition = writeStructSlots(object, target, position$1, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
|
|
1725
|
+
if (notifySharedUpdate)
|
|
1726
|
+
hasSharedUpdate = true;
|
|
1727
|
+
position$1 = newPosition;
|
|
1728
|
+
if (start > 0) {
|
|
1729
|
+
pack(value);
|
|
1730
|
+
if (start == 0)
|
|
1731
|
+
return { position: position$1, targetView, target }; // indicate the buffer was re-allocated
|
|
1732
|
+
} else
|
|
1733
|
+
pack(value);
|
|
1734
|
+
return position$1;
|
|
1735
|
+
}, this);
|
|
1736
|
+
if (newPosition === 0) // bail and go to a msgpack object
|
|
1737
|
+
return writeObject(object, true);
|
|
1738
|
+
position$1 = newPosition;
|
|
1739
|
+
};
|
|
1740
|
+
}
|
|
1741
|
+
useBuffer(buffer) {
|
|
1742
|
+
// this means we are finished using our own buffer and we can write over it safely
|
|
1743
|
+
target = buffer;
|
|
1744
|
+
targetView = new DataView(target.buffer, target.byteOffset, target.byteLength);
|
|
1745
|
+
position$1 = 0;
|
|
1746
|
+
}
|
|
1747
|
+
clearSharedData() {
|
|
1748
|
+
if (this.structures)
|
|
1749
|
+
this.structures = [];
|
|
1750
|
+
if (this.typedStructs)
|
|
1751
|
+
this.typedStructs = [];
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/, C1Type ];
|
|
1756
|
+
extensions = [{
|
|
1757
|
+
pack(date, allocateForWrite, pack) {
|
|
1758
|
+
let seconds = date.getTime() / 1000;
|
|
1759
|
+
if ((this.useTimestamp32 || date.getMilliseconds() === 0) && seconds >= 0 && seconds < 0x100000000) {
|
|
1760
|
+
// Timestamp 32
|
|
1761
|
+
let { target, targetView, position} = allocateForWrite(6);
|
|
1762
|
+
target[position++] = 0xd6;
|
|
1763
|
+
target[position++] = 0xff;
|
|
1764
|
+
targetView.setUint32(position, seconds);
|
|
1765
|
+
} else if (seconds > 0 && seconds < 0x100000000) {
|
|
1766
|
+
// Timestamp 64
|
|
1767
|
+
let { target, targetView, position} = allocateForWrite(10);
|
|
1768
|
+
target[position++] = 0xd7;
|
|
1769
|
+
target[position++] = 0xff;
|
|
1770
|
+
targetView.setUint32(position, date.getMilliseconds() * 4000000 + ((seconds / 1000 / 0x100000000) >> 0));
|
|
1771
|
+
targetView.setUint32(position + 4, seconds);
|
|
1772
|
+
} else if (isNaN(seconds)) {
|
|
1773
|
+
if (this.onInvalidDate) {
|
|
1774
|
+
allocateForWrite(0);
|
|
1775
|
+
return pack(this.onInvalidDate())
|
|
1776
|
+
}
|
|
1777
|
+
// Intentionally invalid timestamp
|
|
1778
|
+
let { target, targetView, position} = allocateForWrite(3);
|
|
1779
|
+
target[position++] = 0xd4;
|
|
1780
|
+
target[position++] = 0xff;
|
|
1781
|
+
target[position++] = 0xff;
|
|
1782
|
+
} else {
|
|
1783
|
+
// Timestamp 96
|
|
1784
|
+
let { target, targetView, position} = allocateForWrite(15);
|
|
1785
|
+
target[position++] = 0xc7;
|
|
1786
|
+
target[position++] = 12;
|
|
1787
|
+
target[position++] = 0xff;
|
|
1788
|
+
targetView.setUint32(position, date.getMilliseconds() * 1000000);
|
|
1789
|
+
targetView.setBigInt64(position + 4, BigInt(Math.floor(seconds)));
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
}, {
|
|
1793
|
+
pack(set, allocateForWrite, pack) {
|
|
1794
|
+
let array = Array.from(set);
|
|
1795
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1796
|
+
if (this.moreTypes) {
|
|
1797
|
+
target[position++] = 0xd4;
|
|
1798
|
+
target[position++] = 0x73; // 's' for Set
|
|
1799
|
+
target[position++] = 0;
|
|
1800
|
+
}
|
|
1801
|
+
pack(array);
|
|
1802
|
+
}
|
|
1803
|
+
}, {
|
|
1804
|
+
pack(error, allocateForWrite, pack) {
|
|
1805
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1806
|
+
if (this.moreTypes) {
|
|
1807
|
+
target[position++] = 0xd4;
|
|
1808
|
+
target[position++] = 0x65; // 'e' for error
|
|
1809
|
+
target[position++] = 0;
|
|
1810
|
+
}
|
|
1811
|
+
pack([ error.name, error.message ]);
|
|
1812
|
+
}
|
|
1813
|
+
}, {
|
|
1814
|
+
pack(regex, allocateForWrite, pack) {
|
|
1815
|
+
let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
|
|
1816
|
+
if (this.moreTypes) {
|
|
1817
|
+
target[position++] = 0xd4;
|
|
1818
|
+
target[position++] = 0x78; // 'x' for regeXp
|
|
1819
|
+
target[position++] = 0;
|
|
1820
|
+
}
|
|
1821
|
+
pack([ regex.source, regex.flags ]);
|
|
1822
|
+
}
|
|
1823
|
+
}, {
|
|
1824
|
+
pack(arrayBuffer, allocateForWrite) {
|
|
1825
|
+
if (this.moreTypes)
|
|
1826
|
+
writeExtBuffer(arrayBuffer, 0x10, allocateForWrite);
|
|
1827
|
+
else
|
|
1828
|
+
writeBuffer(hasNodeBuffer ? Buffer.from(arrayBuffer) : new Uint8Array(arrayBuffer), allocateForWrite);
|
|
1829
|
+
}
|
|
1830
|
+
}, {
|
|
1831
|
+
pack(typedArray, allocateForWrite) {
|
|
1832
|
+
let constructor = typedArray.constructor;
|
|
1833
|
+
if (constructor !== ByteArray && this.moreTypes)
|
|
1834
|
+
writeExtBuffer(typedArray, typedArrays.indexOf(constructor.name), allocateForWrite);
|
|
1835
|
+
else
|
|
1836
|
+
writeBuffer(typedArray, allocateForWrite);
|
|
1837
|
+
}
|
|
1838
|
+
}, {
|
|
1839
|
+
pack(c1, allocateForWrite) { // specific 0xC1 object
|
|
1840
|
+
let { target, position} = allocateForWrite(1);
|
|
1841
|
+
target[position] = 0xc1;
|
|
1842
|
+
}
|
|
1843
|
+
}];
|
|
1844
|
+
|
|
1845
|
+
function writeExtBuffer(typedArray, type, allocateForWrite, encode) {
|
|
1846
|
+
let length = typedArray.byteLength;
|
|
1847
|
+
if (length + 1 < 0x100) {
|
|
1848
|
+
var { target, position } = allocateForWrite(4 + length);
|
|
1849
|
+
target[position++] = 0xc7;
|
|
1850
|
+
target[position++] = length + 1;
|
|
1851
|
+
} else if (length + 1 < 0x10000) {
|
|
1852
|
+
var { target, position } = allocateForWrite(5 + length);
|
|
1853
|
+
target[position++] = 0xc8;
|
|
1854
|
+
target[position++] = (length + 1) >> 8;
|
|
1855
|
+
target[position++] = (length + 1) & 0xff;
|
|
1856
|
+
} else {
|
|
1857
|
+
var { target, position, targetView } = allocateForWrite(7 + length);
|
|
1858
|
+
target[position++] = 0xc9;
|
|
1859
|
+
targetView.setUint32(position, length + 1); // plus one for the type byte
|
|
1860
|
+
position += 4;
|
|
1861
|
+
}
|
|
1862
|
+
target[position++] = 0x74; // "t" for typed array
|
|
1863
|
+
target[position++] = type;
|
|
1864
|
+
target.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength), position);
|
|
1865
|
+
}
|
|
1866
|
+
function writeBuffer(buffer, allocateForWrite) {
|
|
1867
|
+
let length = buffer.byteLength;
|
|
1868
|
+
var target, position;
|
|
1869
|
+
if (length < 0x100) {
|
|
1870
|
+
var { target, position } = allocateForWrite(length + 2);
|
|
1871
|
+
target[position++] = 0xc4;
|
|
1872
|
+
target[position++] = length;
|
|
1873
|
+
} else if (length < 0x10000) {
|
|
1874
|
+
var { target, position } = allocateForWrite(length + 3);
|
|
1875
|
+
target[position++] = 0xc5;
|
|
1876
|
+
target[position++] = length >> 8;
|
|
1877
|
+
target[position++] = length & 0xff;
|
|
1878
|
+
} else {
|
|
1879
|
+
var { target, position, targetView } = allocateForWrite(length + 5);
|
|
1880
|
+
target[position++] = 0xc6;
|
|
1881
|
+
targetView.setUint32(position, length);
|
|
1882
|
+
position += 4;
|
|
1883
|
+
}
|
|
1884
|
+
target.set(buffer, position);
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
function writeExtensionData(result, target, position, type) {
|
|
1888
|
+
let length = result.length;
|
|
1889
|
+
switch (length) {
|
|
1890
|
+
case 1:
|
|
1891
|
+
target[position++] = 0xd4;
|
|
1892
|
+
break
|
|
1893
|
+
case 2:
|
|
1894
|
+
target[position++] = 0xd5;
|
|
1895
|
+
break
|
|
1896
|
+
case 4:
|
|
1897
|
+
target[position++] = 0xd6;
|
|
1898
|
+
break
|
|
1899
|
+
case 8:
|
|
1900
|
+
target[position++] = 0xd7;
|
|
1901
|
+
break
|
|
1902
|
+
case 16:
|
|
1903
|
+
target[position++] = 0xd8;
|
|
1904
|
+
break
|
|
1905
|
+
default:
|
|
1906
|
+
if (length < 0x100) {
|
|
1907
|
+
target[position++] = 0xc7;
|
|
1908
|
+
target[position++] = length;
|
|
1909
|
+
} else if (length < 0x10000) {
|
|
1910
|
+
target[position++] = 0xc8;
|
|
1911
|
+
target[position++] = length >> 8;
|
|
1912
|
+
target[position++] = length & 0xff;
|
|
1913
|
+
} else {
|
|
1914
|
+
target[position++] = 0xc9;
|
|
1915
|
+
target[position++] = length >> 24;
|
|
1916
|
+
target[position++] = (length >> 16) & 0xff;
|
|
1917
|
+
target[position++] = (length >> 8) & 0xff;
|
|
1918
|
+
target[position++] = length & 0xff;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
target[position++] = type;
|
|
1922
|
+
target.set(result, position);
|
|
1923
|
+
position += length;
|
|
1924
|
+
return position
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
function insertIds(serialized, idsToInsert) {
|
|
1928
|
+
// insert the ids that need to be referenced for structured clones
|
|
1929
|
+
let nextId;
|
|
1930
|
+
let distanceToMove = idsToInsert.length * 6;
|
|
1931
|
+
let lastEnd = serialized.length - distanceToMove;
|
|
1932
|
+
idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1);
|
|
1933
|
+
while (nextId = idsToInsert.pop()) {
|
|
1934
|
+
let offset = nextId.offset;
|
|
1935
|
+
let id = nextId.id;
|
|
1936
|
+
serialized.copyWithin(offset + distanceToMove, offset, lastEnd);
|
|
1937
|
+
distanceToMove -= 6;
|
|
1938
|
+
let position = offset + distanceToMove;
|
|
1939
|
+
serialized[position++] = 0xd6;
|
|
1940
|
+
serialized[position++] = 0x69; // 'i'
|
|
1941
|
+
serialized[position++] = id >> 24;
|
|
1942
|
+
serialized[position++] = (id >> 16) & 0xff;
|
|
1943
|
+
serialized[position++] = (id >> 8) & 0xff;
|
|
1944
|
+
serialized[position++] = id & 0xff;
|
|
1945
|
+
lastEnd = offset;
|
|
1946
|
+
}
|
|
1947
|
+
return serialized
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
function writeBundles(start, pack) {
|
|
1951
|
+
if (bundledStrings$1.length > 0) {
|
|
1952
|
+
targetView.setUint32(bundledStrings$1.position + start, position$1 - bundledStrings$1.position - start);
|
|
1953
|
+
let writeStrings = bundledStrings$1;
|
|
1954
|
+
bundledStrings$1 = null;
|
|
1955
|
+
pack(writeStrings[0]);
|
|
1956
|
+
pack(writeStrings[1]);
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
function setWriteStructSlots(writeSlots, makeStructures) {
|
|
1960
|
+
writeStructSlots = writeSlots;
|
|
1961
|
+
prepareStructures = makeStructures;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
let defaultPackr = new Packr({ useRecords: false });
|
|
1965
|
+
const REUSE_BUFFER_MODE = 512;
|
|
1966
|
+
const RESET_BUFFER_MODE = 1024;
|
|
1967
|
+
|
|
1968
|
+
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)
|
|
1969
|
+
const NUMBER = 0;
|
|
1970
|
+
const UTF8 = 2;
|
|
1971
|
+
const OBJECT_DATA = 1;
|
|
1972
|
+
const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
|
|
1973
|
+
const float32Headers = [false, true, true, false, false, true, true, false];
|
|
1974
|
+
let updatedPosition;
|
|
1975
|
+
const hasNodeBuffer$1 = typeof Buffer !== 'undefined';
|
|
1976
|
+
let textEncoder$1;
|
|
1977
|
+
try {
|
|
1978
|
+
textEncoder$1 = new TextEncoder();
|
|
1979
|
+
} catch (error) {}
|
|
1980
|
+
const encodeUtf8 = hasNodeBuffer$1 ? function(target, string, position) {
|
|
1981
|
+
return target.utf8Write(string, position, 0xffffffff)
|
|
1982
|
+
} : (textEncoder$1 && textEncoder$1.encodeInto) ?
|
|
1983
|
+
function(target, string, position) {
|
|
1984
|
+
return textEncoder$1.encodeInto(string, target.subarray(position)).written
|
|
1985
|
+
} : false;
|
|
1986
|
+
setWriteStructSlots(writeStruct, prepareStructures$1);
|
|
1987
|
+
function writeStruct(object, target, position, structures, makeRoom, pack, packr) {
|
|
1988
|
+
let typedStructs = packr.typedStructs || (packr.typedStructs = []);
|
|
1989
|
+
// note that we rely on pack.js to load stored structures before we get to this point
|
|
1990
|
+
packr.lastTypedStructuresLength = typedStructs.length;
|
|
1991
|
+
let targetView = target.dataView;
|
|
1992
|
+
let refsStartPosition = (typedStructs.lastStringStart || 100) + position;
|
|
1993
|
+
let safeEnd = target.length - 10;
|
|
1994
|
+
let start = position;
|
|
1995
|
+
if (position > safeEnd) {
|
|
1996
|
+
let lastStart = start;
|
|
1997
|
+
target = makeRoom(position);
|
|
1998
|
+
targetView = target.dataView;
|
|
1999
|
+
position -= lastStart;
|
|
2000
|
+
refsStartPosition -= lastStart;
|
|
2001
|
+
start = 0;
|
|
2002
|
+
safeEnd = target.length - 10;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
let refOffset, refPosition = refsStartPosition;
|
|
2006
|
+
|
|
2007
|
+
let transition = typedStructs.transitions || (typedStructs.transitions = Object.create(null));
|
|
2008
|
+
let nextId = typedStructs.nextId || typedStructs.length;
|
|
2009
|
+
let headerSize =
|
|
2010
|
+
nextId < 0xf ? 1 :
|
|
2011
|
+
nextId < 0xf0 ? 2 :
|
|
2012
|
+
nextId < 0xf000 ? 3 :
|
|
2013
|
+
nextId < 0xf00000 ? 4 : 0;
|
|
2014
|
+
if (headerSize === 0)
|
|
2015
|
+
return 0;
|
|
2016
|
+
position += headerSize;
|
|
2017
|
+
let queuedReferences = [];
|
|
2018
|
+
let keyIndex = 0;
|
|
2019
|
+
for (let key in object) {
|
|
2020
|
+
let value = object[key];
|
|
2021
|
+
let nextTransition = transition[key];
|
|
2022
|
+
if (!nextTransition) {
|
|
2023
|
+
transition[key] = nextTransition = {
|
|
2024
|
+
key,
|
|
2025
|
+
parent: transition,
|
|
2026
|
+
enumerationOffset: 0,
|
|
2027
|
+
ascii0: null,
|
|
2028
|
+
ascii8: null,
|
|
2029
|
+
num8: null,
|
|
2030
|
+
string16: null,
|
|
2031
|
+
object16: null,
|
|
2032
|
+
num32: null,
|
|
2033
|
+
float64: null
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
2036
|
+
if (position > safeEnd) {
|
|
2037
|
+
let lastStart = start;
|
|
2038
|
+
target = makeRoom(position);
|
|
2039
|
+
targetView = target.dataView;
|
|
2040
|
+
position -= lastStart;
|
|
2041
|
+
refsStartPosition -= lastStart;
|
|
2042
|
+
refPosition -= lastStart;
|
|
2043
|
+
start = 0;
|
|
2044
|
+
safeEnd = target.length - 10;
|
|
2045
|
+
}
|
|
2046
|
+
switch (typeof value) {
|
|
2047
|
+
case 'number':
|
|
2048
|
+
let number = value;
|
|
2049
|
+
if (number >> 0 === number && number < 0x20000000 && number > -0x1f000000) {
|
|
2050
|
+
if (number < 0xf6 && number >= 0 && (nextTransition.num8 || number < 0x20 && !nextTransition.num32)) {
|
|
2051
|
+
transition = nextTransition.num8 || createTypeTransition(nextTransition, NUMBER, 1);
|
|
2052
|
+
target[position++] = number;
|
|
2053
|
+
} else {
|
|
2054
|
+
transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
|
|
2055
|
+
targetView.setUint32(position, number, true);
|
|
2056
|
+
position += 4;
|
|
2057
|
+
}
|
|
2058
|
+
break;
|
|
2059
|
+
} else if (number < 0x100000000 && number >= -0x80000000) {
|
|
2060
|
+
targetView.setFloat32(position, number, true);
|
|
2061
|
+
if (float32Headers[target[position + 3] >>> 5]) {
|
|
2062
|
+
let xShifted;
|
|
2063
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
2064
|
+
if (((xShifted = number * mult10[((target[position + 3] & 0x7f) << 1) | (target[position + 2] >> 7)]) >> 0) === xShifted) {
|
|
2065
|
+
transition = nextTransition.num32 || createTypeTransition(nextTransition, NUMBER, 4);
|
|
2066
|
+
position += 4;
|
|
2067
|
+
break;
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
transition = nextTransition.num64 || createTypeTransition(nextTransition, NUMBER, 8);
|
|
2072
|
+
targetView.setFloat64(position, number, true);
|
|
2073
|
+
position += 8;
|
|
2074
|
+
break;
|
|
2075
|
+
case 'string':
|
|
2076
|
+
let strLength = value.length;
|
|
2077
|
+
refOffset = refPosition - refsStartPosition;
|
|
2078
|
+
if ((strLength << 2) + position > safeEnd) {
|
|
2079
|
+
let lastStart = start;
|
|
2080
|
+
target = makeRoom(refPosition);
|
|
2081
|
+
targetView = target.dataView;
|
|
2082
|
+
position -= lastStart;
|
|
2083
|
+
refsStartPosition -= lastStart;
|
|
2084
|
+
refPosition -= lastStart;
|
|
2085
|
+
start = 0;
|
|
2086
|
+
safeEnd = target.length - 10;
|
|
2087
|
+
}
|
|
2088
|
+
if (strLength > ((0xff00 + refOffset) >> 2)) {
|
|
2089
|
+
queuedReferences.push(key, value, position - start);
|
|
2090
|
+
break;
|
|
2091
|
+
}
|
|
2092
|
+
let isNotAscii;
|
|
2093
|
+
let strStart = refPosition;
|
|
2094
|
+
if (strLength < 0x40) {
|
|
2095
|
+
let i, c1, c2;
|
|
2096
|
+
for (i = 0; i < strLength; i++) {
|
|
2097
|
+
c1 = value.charCodeAt(i);
|
|
2098
|
+
if (c1 < 0x80) {
|
|
2099
|
+
target[refPosition++] = c1;
|
|
2100
|
+
} else if (c1 < 0x800) {
|
|
2101
|
+
isNotAscii = true;
|
|
2102
|
+
target[refPosition++] = c1 >> 6 | 0xc0;
|
|
2103
|
+
target[refPosition++] = c1 & 0x3f | 0x80;
|
|
2104
|
+
} else if (
|
|
2105
|
+
(c1 & 0xfc00) === 0xd800 &&
|
|
2106
|
+
((c2 = value.charCodeAt(i + 1)) & 0xfc00) === 0xdc00
|
|
2107
|
+
) {
|
|
2108
|
+
isNotAscii = true;
|
|
2109
|
+
c1 = 0x10000 + ((c1 & 0x03ff) << 10) + (c2 & 0x03ff);
|
|
2110
|
+
i++;
|
|
2111
|
+
target[refPosition++] = c1 >> 18 | 0xf0;
|
|
2112
|
+
target[refPosition++] = c1 >> 12 & 0x3f | 0x80;
|
|
2113
|
+
target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
2114
|
+
target[refPosition++] = c1 & 0x3f | 0x80;
|
|
2115
|
+
} else {
|
|
2116
|
+
isNotAscii = true;
|
|
2117
|
+
target[refPosition++] = c1 >> 12 | 0xe0;
|
|
2118
|
+
target[refPosition++] = c1 >> 6 & 0x3f | 0x80;
|
|
2119
|
+
target[refPosition++] = c1 & 0x3f | 0x80;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
} else {
|
|
2123
|
+
refPosition += encodeUtf8(target, value, refPosition);
|
|
2124
|
+
isNotAscii = refPosition - strStart > strLength;
|
|
2125
|
+
}
|
|
2126
|
+
if (refOffset < 0x100) {
|
|
2127
|
+
if (isNotAscii)
|
|
2128
|
+
transition = nextTransition.string8 || createTypeTransition(nextTransition, UTF8, 1);
|
|
2129
|
+
else
|
|
2130
|
+
transition = nextTransition.ascii8 || createTypeTransition(nextTransition, ASCII, 1);
|
|
2131
|
+
target[position++] = refOffset;
|
|
2132
|
+
} else {
|
|
2133
|
+
if (isNotAscii)
|
|
2134
|
+
transition = nextTransition.string16 || createTypeTransition(nextTransition, UTF8, 2);
|
|
2135
|
+
else
|
|
2136
|
+
transition = nextTransition.ascii16 || createTypeTransition(nextTransition, ASCII, 2);
|
|
2137
|
+
targetView.setUint16(position, refOffset, true);
|
|
2138
|
+
position += 2;
|
|
2139
|
+
}
|
|
2140
|
+
break;
|
|
2141
|
+
case 'object':
|
|
2142
|
+
if (value) {
|
|
2143
|
+
//transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
|
|
2144
|
+
queuedReferences.push(key, value, keyIndex);
|
|
2145
|
+
break;
|
|
2146
|
+
} else { // null
|
|
2147
|
+
nextTransition = anyType(nextTransition, position, targetView, -10); // match CBOR with this
|
|
2148
|
+
if (nextTransition) {
|
|
2149
|
+
transition = nextTransition;
|
|
2150
|
+
position = updatedPosition;
|
|
2151
|
+
} else queuedReferences.push(key, value, keyIndex);
|
|
2152
|
+
}
|
|
2153
|
+
break;
|
|
2154
|
+
case 'boolean':
|
|
2155
|
+
transition = nextTransition.num8 || nextTransition.ascii8 || createTypeTransition(nextTransition, NUMBER, 1);
|
|
2156
|
+
target[position++] = value ? 0xf9 : 0xf8; // match CBOR with these
|
|
2157
|
+
break;
|
|
2158
|
+
case 'undefined':
|
|
2159
|
+
nextTransition = anyType(nextTransition, position, targetView, -9); // match CBOR with this
|
|
2160
|
+
if (nextTransition) {
|
|
2161
|
+
transition = nextTransition;
|
|
2162
|
+
position = updatedPosition;
|
|
2163
|
+
} else queuedReferences.push(key, value, keyIndex);
|
|
2164
|
+
break;
|
|
2165
|
+
}
|
|
2166
|
+
keyIndex++;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
for (let i = 0, l = queuedReferences.length; i < l;) {
|
|
2170
|
+
let key = queuedReferences[i++];
|
|
2171
|
+
let value = queuedReferences[i++];
|
|
2172
|
+
let propertyIndex = queuedReferences[i++];
|
|
2173
|
+
let nextTransition = transition[key];
|
|
2174
|
+
if (!nextTransition) {
|
|
2175
|
+
transition[key] = nextTransition = {
|
|
2176
|
+
key,
|
|
2177
|
+
parent: transition,
|
|
2178
|
+
enumerationOffset: propertyIndex - keyIndex,
|
|
2179
|
+
ascii0: null,
|
|
2180
|
+
ascii8: null,
|
|
2181
|
+
num8: null,
|
|
2182
|
+
string16: null,
|
|
2183
|
+
object16: null,
|
|
2184
|
+
num32: null,
|
|
2185
|
+
float64: null
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
let newPosition;
|
|
2189
|
+
if (value) {
|
|
2190
|
+
/*if (typeof value === 'string') { // TODO: we could re-enable long strings
|
|
2191
|
+
if (position + value.length * 3 > safeEnd) {
|
|
2192
|
+
target = makeRoom(position + value.length * 3);
|
|
2193
|
+
position -= start;
|
|
2194
|
+
targetView = target.dataView;
|
|
2195
|
+
start = 0;
|
|
2196
|
+
}
|
|
2197
|
+
newPosition = position + target.utf8Write(value, position, 0xffffffff);
|
|
2198
|
+
} else { */
|
|
2199
|
+
let size;
|
|
2200
|
+
refOffset = refPosition - refsStartPosition;
|
|
2201
|
+
if (refOffset < 0xff00) {
|
|
2202
|
+
transition = nextTransition.object16;
|
|
2203
|
+
if (transition)
|
|
2204
|
+
size = 2;
|
|
2205
|
+
else if ((transition = nextTransition.object32))
|
|
2206
|
+
size = 4;
|
|
2207
|
+
else {
|
|
2208
|
+
transition = createTypeTransition(nextTransition, OBJECT_DATA, 2);
|
|
2209
|
+
size = 2;
|
|
2210
|
+
}
|
|
2211
|
+
} else {
|
|
2212
|
+
transition = nextTransition.object32 || createTypeTransition(nextTransition, OBJECT_DATA, 4);
|
|
2213
|
+
size = 4;
|
|
2214
|
+
}
|
|
2215
|
+
newPosition = pack(value, refPosition);
|
|
2216
|
+
//}
|
|
2217
|
+
if (typeof newPosition === 'object') {
|
|
2218
|
+
// re-allocated
|
|
2219
|
+
refPosition = newPosition.position;
|
|
2220
|
+
targetView = newPosition.targetView;
|
|
2221
|
+
target = newPosition.target;
|
|
2222
|
+
refsStartPosition -= start;
|
|
2223
|
+
position -= start;
|
|
2224
|
+
start = 0;
|
|
2225
|
+
} else
|
|
2226
|
+
refPosition = newPosition;
|
|
2227
|
+
if (size === 2) {
|
|
2228
|
+
targetView.setUint16(position, refOffset, true);
|
|
2229
|
+
position += 2;
|
|
2230
|
+
} else {
|
|
2231
|
+
targetView.setUint32(position, refOffset, true);
|
|
2232
|
+
position += 4;
|
|
2233
|
+
}
|
|
2234
|
+
} else {
|
|
2235
|
+
transition = nextTransition.object16 || createTypeTransition(nextTransition, OBJECT_DATA, 2);
|
|
2236
|
+
targetView.setInt16(position, value === null ? -10 : -9, true);
|
|
2237
|
+
position += 2;
|
|
2238
|
+
}
|
|
2239
|
+
keyIndex++;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
|
|
2243
|
+
let recordId = transition[RECORD_SYMBOL];
|
|
2244
|
+
if (recordId == null) {
|
|
2245
|
+
recordId = packr.typedStructs.length;
|
|
2246
|
+
let structure = [];
|
|
2247
|
+
let nextTransition = transition;
|
|
2248
|
+
let key, type;
|
|
2249
|
+
while ((type = nextTransition.__type) !== undefined) {
|
|
2250
|
+
let size = nextTransition.__size;
|
|
2251
|
+
nextTransition = nextTransition.__parent;
|
|
2252
|
+
key = nextTransition.key;
|
|
2253
|
+
let property = [type, size, key];
|
|
2254
|
+
if (nextTransition.enumerationOffset)
|
|
2255
|
+
property.push(nextTransition.enumerationOffset);
|
|
2256
|
+
structure.push(property);
|
|
2257
|
+
nextTransition = nextTransition.parent;
|
|
2258
|
+
}
|
|
2259
|
+
structure.reverse();
|
|
2260
|
+
transition[RECORD_SYMBOL] = recordId;
|
|
2261
|
+
packr.typedStructs[recordId] = structure;
|
|
2262
|
+
pack(null, 0, true); // special call to notify that structures have been updated
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
switch (headerSize) {
|
|
2267
|
+
case 1:
|
|
2268
|
+
if (recordId >= 0x10) return 0;
|
|
2269
|
+
target[start] = recordId + 0x20;
|
|
2270
|
+
break;
|
|
2271
|
+
case 2:
|
|
2272
|
+
if (recordId >= 0x100) return 0;
|
|
2273
|
+
target[start] = 0x38;
|
|
2274
|
+
target[start + 1] = recordId;
|
|
2275
|
+
break;
|
|
2276
|
+
case 3:
|
|
2277
|
+
if (recordId >= 0x10000) return 0;
|
|
2278
|
+
target[start] = 0x39;
|
|
2279
|
+
target.setUint16(start + 1, recordId, true);
|
|
2280
|
+
break;
|
|
2281
|
+
case 4:
|
|
2282
|
+
if (recordId >= 0x1000000) return 0;
|
|
2283
|
+
target.setUint32(start, (recordId << 8) + 0x3a, true);
|
|
2284
|
+
break;
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
if (position < refsStartPosition) {
|
|
2288
|
+
if (refsStartPosition === refPosition)
|
|
2289
|
+
return position; // no refs
|
|
2290
|
+
// adjust positioning
|
|
2291
|
+
target.copyWithin(position, refsStartPosition, refPosition);
|
|
2292
|
+
refPosition += position - refsStartPosition;
|
|
2293
|
+
typedStructs.lastStringStart = position - start;
|
|
2294
|
+
} else if (position > refsStartPosition) {
|
|
2295
|
+
if (refsStartPosition === refPosition)
|
|
2296
|
+
return position; // no refs
|
|
2297
|
+
typedStructs.lastStringStart = position - start;
|
|
2298
|
+
return writeStruct(object, target, start, structures, makeRoom, pack, packr);
|
|
2299
|
+
}
|
|
2300
|
+
return refPosition;
|
|
2301
|
+
}
|
|
2302
|
+
function anyType(transition, position, targetView, value) {
|
|
2303
|
+
let nextTransition;
|
|
2304
|
+
if ((nextTransition = transition.ascii8 || transition.num8)) {
|
|
2305
|
+
targetView.setInt8(position, value, true);
|
|
2306
|
+
updatedPosition = position + 1;
|
|
2307
|
+
return nextTransition;
|
|
2308
|
+
}
|
|
2309
|
+
if ((nextTransition = transition.string16 || transition.object16)) {
|
|
2310
|
+
targetView.setInt16(position, value, true);
|
|
2311
|
+
updatedPosition = position + 2;
|
|
2312
|
+
return nextTransition;
|
|
2313
|
+
}
|
|
2314
|
+
if (nextTransition = transition.num32) {
|
|
2315
|
+
targetView.setUint32(position, 0xe0000100 + value, true);
|
|
2316
|
+
updatedPosition = position + 4;
|
|
2317
|
+
return nextTransition;
|
|
2318
|
+
}
|
|
2319
|
+
// transition.float64
|
|
2320
|
+
if (nextTransition = transition.num64) {
|
|
2321
|
+
targetView.setFloat64(position, NaN, true);
|
|
2322
|
+
targetView.setInt8(position, value);
|
|
2323
|
+
updatedPosition = position + 8;
|
|
2324
|
+
return nextTransition;
|
|
2325
|
+
}
|
|
2326
|
+
updatedPosition = position;
|
|
2327
|
+
// TODO: can we do an "any" type where we defer the decision?
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
function createTypeTransition(transition, type, size) {
|
|
2331
|
+
let typeName = TYPE_NAMES[type] + (size << 3);
|
|
2332
|
+
let newTransition = transition[typeName] || (transition[typeName] = Object.create(null));
|
|
2333
|
+
newTransition.__type = type;
|
|
2334
|
+
newTransition.__size = size;
|
|
2335
|
+
newTransition.__parent = transition;
|
|
2336
|
+
return newTransition;
|
|
2337
|
+
}
|
|
2338
|
+
function onLoadedStructures$1(sharedData) {
|
|
2339
|
+
if (!(sharedData instanceof Map))
|
|
2340
|
+
return sharedData;
|
|
2341
|
+
let typed = sharedData.get('typed') || [];
|
|
2342
|
+
let named = sharedData.get('named');
|
|
2343
|
+
let transitions = Object.create(null);
|
|
2344
|
+
for (let i = 0, l = typed.length; i < l; i++) {
|
|
2345
|
+
let structure = typed[i];
|
|
2346
|
+
let transition = transitions;
|
|
2347
|
+
for (let [type, size, key] of structure) {
|
|
2348
|
+
let nextTransition = transition[key];
|
|
2349
|
+
if (!nextTransition) {
|
|
2350
|
+
transition[key] = nextTransition = {
|
|
2351
|
+
key,
|
|
2352
|
+
parent: transition,
|
|
2353
|
+
enumerationOffset: 0,
|
|
2354
|
+
ascii0: null,
|
|
2355
|
+
ascii8: null,
|
|
2356
|
+
num8: null,
|
|
2357
|
+
string16: null,
|
|
2358
|
+
object16: null,
|
|
2359
|
+
num32: null,
|
|
2360
|
+
float64: null
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
transition = createTypeTransition(nextTransition, type, size);
|
|
2364
|
+
}
|
|
2365
|
+
transition[RECORD_SYMBOL] = i;
|
|
2366
|
+
}
|
|
2367
|
+
typed.transitions = transitions;
|
|
2368
|
+
this.typedStructs = typed;
|
|
2369
|
+
return named;
|
|
2370
|
+
}
|
|
2371
|
+
var sourceSymbol = Symbol('source');
|
|
2372
|
+
function readStruct$1(src, position, srcEnd, unpackr) {
|
|
2373
|
+
// var stringLength = (src[position++] << 8) | src[position++];
|
|
2374
|
+
let recordId = src[position++] - 0x20;
|
|
2375
|
+
if (recordId >= 24) {
|
|
2376
|
+
switch(recordId) {
|
|
2377
|
+
case 24: recordId = src[position++]; break;
|
|
2378
|
+
// little endian:
|
|
2379
|
+
case 25: recordId = src[position++] + (src[position++] << 8); break;
|
|
2380
|
+
case 26: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16); break;
|
|
2381
|
+
case 27: recordId = src[position++] + (src[position++] << 8) + (src[position++] << 16) + (src[position++] << 24); break;
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
let structure = unpackr.typedStructs?.[recordId];
|
|
2385
|
+
if (!structure) {
|
|
2386
|
+
// copy src buffer because getStructures will override it
|
|
2387
|
+
src = Uint8Array.prototype.slice.call(src, position, srcEnd);
|
|
2388
|
+
srcEnd -= position;
|
|
2389
|
+
position = 0;
|
|
2390
|
+
unpackr._mergeStructures(unpackr.getStructures());
|
|
2391
|
+
if (!unpackr.typedStructs)
|
|
2392
|
+
throw new Error('Could not find any shared typed structures');
|
|
2393
|
+
unpackr.lastTypedStructuresLength = unpackr.typedStructs.length;
|
|
2394
|
+
structure = unpackr.typedStructs[recordId];
|
|
2395
|
+
if (!structure)
|
|
2396
|
+
throw new Error('Could not find typed structure ' + recordId);
|
|
2397
|
+
}
|
|
2398
|
+
var construct = structure.construct;
|
|
2399
|
+
if (!construct) {
|
|
2400
|
+
construct = structure.construct = function() {
|
|
2401
|
+
};
|
|
2402
|
+
var prototype = construct.prototype;
|
|
2403
|
+
Object.defineProperty(prototype, 'toJSON', {
|
|
2404
|
+
get() {
|
|
2405
|
+
// return an enumerable object with own properties to JSON stringify
|
|
2406
|
+
let resolved = {};
|
|
2407
|
+
for (let i = 0, l = structure.length; i < l; i++) {
|
|
2408
|
+
let key = structure[i];
|
|
2409
|
+
resolved[key] = this[key];
|
|
2410
|
+
}
|
|
2411
|
+
return resolved;
|
|
2412
|
+
},
|
|
2413
|
+
// not enumerable or anything
|
|
2414
|
+
});
|
|
2415
|
+
let currentOffset = 0;
|
|
2416
|
+
let lastRefProperty;
|
|
2417
|
+
let properties = [];
|
|
2418
|
+
for (let i = 0, l = structure.length; i < l; i++) {
|
|
2419
|
+
let definition = structure[i];
|
|
2420
|
+
let [ type, size, key, enumerationOffset ] = definition;
|
|
2421
|
+
let property = {
|
|
2422
|
+
key,
|
|
2423
|
+
offset: currentOffset,
|
|
2424
|
+
};
|
|
2425
|
+
if (enumerationOffset)
|
|
2426
|
+
properties.splice(i + enumerationOffset, 0, property);
|
|
2427
|
+
else
|
|
2428
|
+
properties.push(property);
|
|
2429
|
+
let getRef;
|
|
2430
|
+
switch(size) { // TODO: Move into a separate function
|
|
2431
|
+
case 0: getRef = () => 0; break;
|
|
2432
|
+
case 1:
|
|
2433
|
+
getRef = (source, position) => {
|
|
2434
|
+
let ref = source.src[position + property.offset];
|
|
2435
|
+
return ref >= 0xf6 ? toConstant(ref) : ref;
|
|
2436
|
+
};
|
|
2437
|
+
break;
|
|
2438
|
+
case 2:
|
|
2439
|
+
getRef = (source, position) => {
|
|
2440
|
+
let src = source.src;
|
|
2441
|
+
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2442
|
+
let ref = dataView.getUint16(position + property.offset, true);
|
|
2443
|
+
return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
|
|
2444
|
+
};
|
|
2445
|
+
break;
|
|
2446
|
+
case 4:
|
|
2447
|
+
getRef = (source, position) => {
|
|
2448
|
+
let src = source.src;
|
|
2449
|
+
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2450
|
+
let ref = dataView.getUint32(position + property.offset, true);
|
|
2451
|
+
return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
|
|
2452
|
+
};
|
|
2453
|
+
break;
|
|
2454
|
+
}
|
|
2455
|
+
property.getRef = getRef;
|
|
2456
|
+
currentOffset += size;
|
|
2457
|
+
let get;
|
|
2458
|
+
switch(type) {
|
|
2459
|
+
case ASCII:
|
|
2460
|
+
if (lastRefProperty && !lastRefProperty.next)
|
|
2461
|
+
lastRefProperty.next = property;
|
|
2462
|
+
lastRefProperty = property;
|
|
2463
|
+
property.multiGetCount = 0;
|
|
2464
|
+
get = function() {
|
|
2465
|
+
let source = this[sourceSymbol];
|
|
2466
|
+
let src = source.src;
|
|
2467
|
+
let position = source.position;
|
|
2468
|
+
let refStart = currentOffset + position;
|
|
2469
|
+
let ref = getRef(source, position);
|
|
2470
|
+
if (typeof ref !== 'number') return ref;
|
|
2471
|
+
|
|
2472
|
+
let end, next = property.next;
|
|
2473
|
+
while(next) {
|
|
2474
|
+
end = next.getRef(source, position);
|
|
2475
|
+
if (typeof end === 'number')
|
|
2476
|
+
break;
|
|
2477
|
+
else
|
|
2478
|
+
end = null;
|
|
2479
|
+
next = next.next;
|
|
2480
|
+
}
|
|
2481
|
+
if (end == null)
|
|
2482
|
+
end = srcEnd - refStart;
|
|
2483
|
+
if (source.srcString) {
|
|
2484
|
+
return source.srcString.slice(ref, end);
|
|
2485
|
+
}
|
|
2486
|
+
/*if (property.multiGetCount > 0) {
|
|
2487
|
+
let asciiEnd;
|
|
2488
|
+
next = firstRefProperty;
|
|
2489
|
+
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2490
|
+
do {
|
|
2491
|
+
asciiEnd = dataView.getUint16(source.position + next.offset, true);
|
|
2492
|
+
if (asciiEnd < 0xff00)
|
|
2493
|
+
break;
|
|
2494
|
+
else
|
|
2495
|
+
asciiEnd = null;
|
|
2496
|
+
} while((next = next.next));
|
|
2497
|
+
if (asciiEnd == null)
|
|
2498
|
+
asciiEnd = srcEnd - refStart
|
|
2499
|
+
source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
|
|
2500
|
+
return source.srcString.slice(ref, end);
|
|
2501
|
+
}
|
|
2502
|
+
if (source.prevStringGet) {
|
|
2503
|
+
source.prevStringGet.multiGetCount += 2;
|
|
2504
|
+
} else {
|
|
2505
|
+
source.prevStringGet = property;
|
|
2506
|
+
property.multiGetCount--;
|
|
2507
|
+
}*/
|
|
2508
|
+
return readString(src, ref + refStart, end - ref);
|
|
2509
|
+
//return src.toString('latin1', ref + refStart, end + refStart);
|
|
2510
|
+
};
|
|
2511
|
+
break;
|
|
2512
|
+
case UTF8: case OBJECT_DATA:
|
|
2513
|
+
if (lastRefProperty && !lastRefProperty.next)
|
|
2514
|
+
lastRefProperty.next = property;
|
|
2515
|
+
lastRefProperty = property;
|
|
2516
|
+
get = function() {
|
|
2517
|
+
let source = this[sourceSymbol];
|
|
2518
|
+
let position = source.position;
|
|
2519
|
+
let refStart = currentOffset + position;
|
|
2520
|
+
let ref = getRef(source, position);
|
|
2521
|
+
if (typeof ref !== 'number') return ref;
|
|
2522
|
+
let src = source.src;
|
|
2523
|
+
let end, next = property.next;
|
|
2524
|
+
while(next) {
|
|
2525
|
+
end = next.getRef(source, position);
|
|
2526
|
+
if (typeof end === 'number')
|
|
2527
|
+
break;
|
|
2528
|
+
else
|
|
2529
|
+
end = null;
|
|
2530
|
+
next = next.next;
|
|
2531
|
+
}
|
|
2532
|
+
if (end == null)
|
|
2533
|
+
end = srcEnd - refStart;
|
|
2534
|
+
if (type === UTF8) {
|
|
2535
|
+
return src.toString('utf8', ref + refStart, end + refStart);
|
|
2536
|
+
} else {
|
|
2537
|
+
return unpackr.unpack(src, { start: ref + refStart, end: end + refStart }); // could reuse this object
|
|
2538
|
+
}
|
|
2539
|
+
};
|
|
2540
|
+
break;
|
|
2541
|
+
case NUMBER:
|
|
2542
|
+
switch(size) {
|
|
2543
|
+
case 4:
|
|
2544
|
+
get = function () {
|
|
2545
|
+
let source = this[sourceSymbol];
|
|
2546
|
+
let src = source.src;
|
|
2547
|
+
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2548
|
+
let position = source.position + property.offset;
|
|
2549
|
+
let value = dataView.getInt32(position, true);
|
|
2550
|
+
if (value < 0x20000000) {
|
|
2551
|
+
if (value > -0x1f000000)
|
|
2552
|
+
return value;
|
|
2553
|
+
if (value > -0x20000000)
|
|
2554
|
+
return toConstant(value & 0xff);
|
|
2555
|
+
}
|
|
2556
|
+
let fValue = dataView.getFloat32(position, true);
|
|
2557
|
+
// this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
2558
|
+
let multiplier = mult10[((src[position + 3] & 0x7f) << 1) | (src[position + 2] >> 7)];
|
|
2559
|
+
return ((multiplier * fValue + (fValue > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
|
|
2560
|
+
};
|
|
2561
|
+
break;
|
|
2562
|
+
case 8:
|
|
2563
|
+
get = function () {
|
|
2564
|
+
let source = this[sourceSymbol];
|
|
2565
|
+
let src = source.src;
|
|
2566
|
+
let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
|
|
2567
|
+
let value = dataView.getFloat64(source.position + property.offset, true);
|
|
2568
|
+
if (isNaN(value)) {
|
|
2569
|
+
let byte = src[source.position + property.offset];
|
|
2570
|
+
if (byte >= 0xf6)
|
|
2571
|
+
return toConstant(byte);
|
|
2572
|
+
}
|
|
2573
|
+
return value;
|
|
2574
|
+
};
|
|
2575
|
+
break;
|
|
2576
|
+
case 1:
|
|
2577
|
+
get = function () {
|
|
2578
|
+
let source = this[sourceSymbol];
|
|
2579
|
+
let src = source.src;
|
|
2580
|
+
let value = src[source.position + property.offset];
|
|
2581
|
+
return value < 0xf6 ? value : toConstant(value);
|
|
2582
|
+
};
|
|
2583
|
+
break;
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
property.get = get;
|
|
2587
|
+
}
|
|
2588
|
+
for (let property of properties) // assign in enumeration order
|
|
2589
|
+
Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
|
|
2590
|
+
}
|
|
2591
|
+
var instance = new construct();
|
|
2592
|
+
instance[sourceSymbol] = {
|
|
2593
|
+
src,
|
|
2594
|
+
position,
|
|
2595
|
+
srcString: '',
|
|
2596
|
+
srcEnd
|
|
2597
|
+
};
|
|
2598
|
+
return instance;
|
|
2599
|
+
}
|
|
2600
|
+
function toConstant(code) {
|
|
2601
|
+
switch(code) {
|
|
2602
|
+
case 0xf6: return null;
|
|
2603
|
+
case 0xf7: return undefined;
|
|
2604
|
+
case 0xf8: return false;
|
|
2605
|
+
case 0xf9: return true;
|
|
2606
|
+
}
|
|
2607
|
+
throw new Error('Unknown constant');
|
|
2608
|
+
}
|
|
2609
|
+
function prepareStructures$1(structures, packr) {
|
|
2610
|
+
if (!packr.typedStructs)
|
|
2611
|
+
return structures;
|
|
2612
|
+
let structMap = new Map();
|
|
2613
|
+
structMap.set('named', structures);
|
|
2614
|
+
structMap.set('typed', packr.typedStructs);
|
|
2615
|
+
let lastTypedStructuresLength = packr.lastTypedStructuresLength || 0;
|
|
2616
|
+
structMap.isCompatible = existing => {
|
|
2617
|
+
if (existing instanceof Map) {
|
|
2618
|
+
let named = existing.get('named') || [];
|
|
2619
|
+
if (named.length !== (packr.lastNamedStructuresLength || 0))
|
|
2620
|
+
return false;
|
|
2621
|
+
let typed = existing.get('typed') || [];
|
|
2622
|
+
if (typed.length !== lastTypedStructuresLength)
|
|
2623
|
+
return false;
|
|
2624
|
+
} else if (existing instanceof Array) {
|
|
2625
|
+
if (existing.length !== (packr.lastNamedStructuresLength || 0))
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
return true;
|
|
2629
|
+
};
|
|
2630
|
+
packr.lastTypedStructuresLength = packr.typedStructs?.length;
|
|
2631
|
+
return structMap;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
setReadStruct(readStruct$1, onLoadedStructures$1);
|
|
2635
|
+
|
|
2636
|
+
let allSampleData = [];
|
|
2637
|
+
for (let i = 1; i < 6; i++) {
|
|
2638
|
+
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)))));
|
|
2639
|
+
}
|
|
2640
|
+
const sampleData = allSampleData[3];
|
|
7
2641
|
function tryRequire(module) {
|
|
8
2642
|
try {
|
|
9
2643
|
return require(module)
|
|
@@ -11,11 +2645,18 @@
|
|
|
11
2645
|
return {}
|
|
12
2646
|
}
|
|
13
2647
|
}
|
|
2648
|
+
|
|
2649
|
+
let seed = 0;
|
|
2650
|
+
function random() {
|
|
2651
|
+
seed++;
|
|
2652
|
+
let a = seed * 15485863;
|
|
2653
|
+
return (a * a * a % 2038074743) / 2038074743;
|
|
2654
|
+
}
|
|
14
2655
|
//if (typeof chai === 'undefined') { chai = require('chai') }
|
|
15
2656
|
var assert = chai.assert;
|
|
16
2657
|
//if (typeof msgpackr === 'undefined') { msgpackr = require('..') }
|
|
17
|
-
var Packr = msgpackr.Packr;
|
|
18
|
-
var Unpackr = msgpackr.Unpackr;
|
|
2658
|
+
var Packr$1 = msgpackr.Packr;
|
|
2659
|
+
var Unpackr$1 = msgpackr.Unpackr;
|
|
19
2660
|
var unpack = msgpackr.unpack;
|
|
20
2661
|
var unpackMultiple = msgpackr.unpackMultiple;
|
|
21
2662
|
var roundFloat32 = msgpackr.roundFloat32;
|
|
@@ -56,7 +2697,7 @@
|
|
|
56
2697
|
]
|
|
57
2698
|
};
|
|
58
2699
|
let structures = [];
|
|
59
|
-
let packr = new Packr({ structures });
|
|
2700
|
+
let packr = new Packr$1({ structures });
|
|
60
2701
|
var serialized = packr.pack(data);
|
|
61
2702
|
serialized = packr.pack(data);
|
|
62
2703
|
serialized = packr.pack(data);
|
|
@@ -69,7 +2710,7 @@
|
|
|
69
2710
|
let data2 = { a: 1, b: 2, d: 4 };
|
|
70
2711
|
let data3 = { a: 1, b: 2, e: 5 };
|
|
71
2712
|
let structures = [];
|
|
72
|
-
let packr = new Packr({ structures });
|
|
2713
|
+
let packr = new Packr$1({ structures });
|
|
73
2714
|
var serialized = packr.pack(data1);
|
|
74
2715
|
var deserialized = packr.unpack(serialized);
|
|
75
2716
|
assert.deepEqual(deserialized, data1);
|
|
@@ -97,7 +2738,7 @@
|
|
|
97
2738
|
]
|
|
98
2739
|
];
|
|
99
2740
|
let structures = [];
|
|
100
|
-
let packr = new Packr({ structures });
|
|
2741
|
+
let packr = new Packr$1({ structures });
|
|
101
2742
|
var serialized = packr.pack(data);
|
|
102
2743
|
var deserialized = packr.unpack(serialized);
|
|
103
2744
|
assert.deepEqual(deserialized, data);
|
|
@@ -109,42 +2750,85 @@
|
|
|
109
2750
|
var deserialized = unpack(serialized);
|
|
110
2751
|
assert.equal(deserialized, data);
|
|
111
2752
|
});
|
|
112
|
-
|
|
113
|
-
test('pack/unpack sample data', function(){
|
|
114
|
-
var data = sampleData;
|
|
115
|
-
var serialized = pack(data);
|
|
116
|
-
var deserialized = unpack(serialized);
|
|
117
|
-
assert.deepEqual(deserialized, data);
|
|
118
|
-
var serialized = pack(data);
|
|
119
|
-
var deserialized = unpack(serialized);
|
|
120
|
-
assert.deepEqual(deserialized, data);
|
|
121
|
-
});
|
|
122
|
-
test('pack/unpack sample data with records', function(){
|
|
123
|
-
var data = sampleData;
|
|
2753
|
+
test('pack/unpack varying data with random access structures', function() {
|
|
124
2754
|
let structures = [];
|
|
125
|
-
let packr = new Packr({ structures, useRecords: true
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
2755
|
+
let packr = new Packr$1({ structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
|
|
2756
|
+
}, getStructures() {
|
|
2757
|
+
console.log('getStructures');
|
|
2758
|
+
} });
|
|
2759
|
+
for (let i = 0; i < 20; i++) {
|
|
2760
|
+
let data = {};
|
|
2761
|
+
let props = ['foo', 'bar', 'a', 'b', 'c','name', 'age', 'd'];
|
|
2762
|
+
function makeString() {
|
|
2763
|
+
let str = '';
|
|
2764
|
+
while (random() < 0.9) {
|
|
2765
|
+
str += random() < 0.8 ? 'hello world' : String.fromCharCode(300);
|
|
2766
|
+
}
|
|
2767
|
+
return str;
|
|
2768
|
+
}
|
|
2769
|
+
for (let i = 0; i < random() * 20; i++) {
|
|
2770
|
+
data[props[Math.floor(random() * 8)]] =
|
|
2771
|
+
random() < 0.3 ? Math.floor(random() * 400) / 2 :
|
|
2772
|
+
random() < 0.3 ? makeString() : random() < 0.3 ? true : random() < 0.3 ? sampleData : null;
|
|
2773
|
+
}
|
|
2774
|
+
var serialized = packr.pack(data);
|
|
2775
|
+
var deserialized = packr.unpack(serialized);
|
|
2776
|
+
for (let key in deserialized) {
|
|
2777
|
+
let a = deserialized[key];
|
|
2778
|
+
}
|
|
2779
|
+
assert.deepEqual(deserialized, data);
|
|
2780
|
+
}
|
|
136
2781
|
});
|
|
2782
|
+
|
|
2783
|
+
for (let sampleData of allSampleData) {
|
|
2784
|
+
let snippet = JSON.stringify(sampleData).slice(0, 20) + '...';
|
|
2785
|
+
test('pack/unpack sample data ' + snippet, function(){
|
|
2786
|
+
var data = sampleData;
|
|
2787
|
+
var serialized = pack(data);
|
|
2788
|
+
var deserialized = unpack(serialized);
|
|
2789
|
+
assert.deepEqual(deserialized, data);
|
|
2790
|
+
var serialized = pack(data);
|
|
2791
|
+
var deserialized = unpack(serialized);
|
|
2792
|
+
assert.deepEqual(deserialized, data);
|
|
2793
|
+
});
|
|
2794
|
+
test('pack/unpack sample data with random access structures ' + snippet, function() {
|
|
2795
|
+
var data = sampleData;
|
|
2796
|
+
let structures = [];
|
|
2797
|
+
let packr = new Packr$1({ structures, useRecords: true, randomAccessStructure: true, freezeData: true, saveStructures(structures) {
|
|
2798
|
+
}, getStructures() {
|
|
2799
|
+
console.log('getStructures');
|
|
2800
|
+
} });
|
|
2801
|
+
for (let i = 0; i < 20; i++) {
|
|
2802
|
+
var serialized = packr.pack(data);
|
|
2803
|
+
var deserialized = packr.unpack(serialized);
|
|
2804
|
+
var copied = {};
|
|
2805
|
+
for (let key in deserialized) {
|
|
2806
|
+
copied[key] = deserialized[key];
|
|
2807
|
+
}
|
|
2808
|
+
assert.deepEqual(copied, data);
|
|
2809
|
+
}
|
|
2810
|
+
});
|
|
2811
|
+
test('pack/unpack sample data with bundled strings ' + snippet, function(){
|
|
2812
|
+
var data = sampleData;
|
|
2813
|
+
let packr = new Packr$1({ /*structures,*/ useRecords: false, bundleStrings: true });
|
|
2814
|
+
var serialized = packr.pack(data);
|
|
2815
|
+
var deserialized = packr.unpack(serialized);
|
|
2816
|
+
assert.deepEqual(deserialized, data);
|
|
2817
|
+
});
|
|
2818
|
+
break;
|
|
2819
|
+
}
|
|
2820
|
+
|
|
137
2821
|
test('pack/unpack empty data with bundled strings', function(){
|
|
138
2822
|
var data = {};
|
|
139
|
-
let packr = new Packr({ bundleStrings: true });
|
|
2823
|
+
let packr = new Packr$1({ bundleStrings: true });
|
|
140
2824
|
var serialized = packr.pack(data);
|
|
141
2825
|
var deserialized = packr.unpack(serialized);
|
|
142
2826
|
assert.deepEqual(deserialized, data);
|
|
143
2827
|
});
|
|
144
2828
|
test('pack/unpack sequential data', function(){
|
|
145
2829
|
var data = { foo:1, bar: 2 };
|
|
146
|
-
let packr = new Packr({ sequential: true });
|
|
147
|
-
let unpackr = new Unpackr({ sequential: true });
|
|
2830
|
+
let packr = new Packr$1({ sequential: true });
|
|
2831
|
+
let unpackr = new Unpackr$1({ sequential: true });
|
|
148
2832
|
var serialized = packr.pack(data);
|
|
149
2833
|
var deserialized = unpackr.unpack(serialized);
|
|
150
2834
|
assert.deepEqual(deserialized, data);
|
|
@@ -205,7 +2889,7 @@
|
|
|
205
2889
|
prop2: 'more string',
|
|
206
2890
|
num: 3,
|
|
207
2891
|
};
|
|
208
|
-
let packr = new Packr();
|
|
2892
|
+
let packr = new Packr$1();
|
|
209
2893
|
addExtension({
|
|
210
2894
|
Class: Extended,
|
|
211
2895
|
type: 11,
|
|
@@ -259,7 +2943,7 @@
|
|
|
259
2943
|
prop2: 'more string',
|
|
260
2944
|
num: 3,
|
|
261
2945
|
};
|
|
262
|
-
let packr = new Packr();
|
|
2946
|
+
let packr = new Packr$1();
|
|
263
2947
|
addExtension({
|
|
264
2948
|
Class: Extended,
|
|
265
2949
|
type: 12,
|
|
@@ -304,7 +2988,7 @@
|
|
|
304
2988
|
object.children[1] = object;
|
|
305
2989
|
object.children[2] = object.children[0];
|
|
306
2990
|
object.childrenAgain = object.children;
|
|
307
|
-
let packr = new Packr({
|
|
2991
|
+
let packr = new Packr$1({
|
|
308
2992
|
moreTypes: true,
|
|
309
2993
|
structuredClone: true,
|
|
310
2994
|
});
|
|
@@ -329,7 +3013,7 @@
|
|
|
329
3013
|
float32Array: fa,
|
|
330
3014
|
uint16Array: new Uint16Array([3,4])
|
|
331
3015
|
};
|
|
332
|
-
let packr = new Packr({
|
|
3016
|
+
let packr = new Packr$1({
|
|
333
3017
|
moreTypes: true,
|
|
334
3018
|
structuredClone: true,
|
|
335
3019
|
});
|
|
@@ -354,6 +3038,18 @@
|
|
|
354
3038
|
assert.deepEqual(deserialized, data);
|
|
355
3039
|
});
|
|
356
3040
|
|
|
3041
|
+
test('separate instances', function() {
|
|
3042
|
+
const packr = new Packr$1({
|
|
3043
|
+
structures: [['m', 'e'], ['action', 'share']]
|
|
3044
|
+
});
|
|
3045
|
+
const packr2 = new Packr$1({
|
|
3046
|
+
structures: [['m', 'e'], ['action', 'share']]
|
|
3047
|
+
});
|
|
3048
|
+
let packed = packr.pack([{m: 1, e: 2}, {action: 3, share: 4}]);
|
|
3049
|
+
// also tried directly decoding this without the first Packr instance packed = new Uint8Array([0x92, 0x40, 0x01, 0x02, 0x41, 0x03, 0x04]);
|
|
3050
|
+
console.log(packr2.unpack(packed));
|
|
3051
|
+
});
|
|
3052
|
+
|
|
357
3053
|
test('many shared structures', function() {
|
|
358
3054
|
let data = [];
|
|
359
3055
|
for (let i = 0; i < 200; i++) {
|
|
@@ -361,7 +3057,7 @@
|
|
|
361
3057
|
}
|
|
362
3058
|
let structures = [];
|
|
363
3059
|
let savedStructures;
|
|
364
|
-
let packr = new Packr({
|
|
3060
|
+
let packr = new Packr$1({
|
|
365
3061
|
structures,
|
|
366
3062
|
saveStructures(structures) {
|
|
367
3063
|
savedStructures = structures;
|
|
@@ -372,7 +3068,7 @@
|
|
|
372
3068
|
var deserialized = packr.unpack(serializedWith32);
|
|
373
3069
|
assert.deepEqual(deserialized, data);
|
|
374
3070
|
structures = structures.slice(0, 32);
|
|
375
|
-
packr = new Packr({
|
|
3071
|
+
packr = new Packr$1({
|
|
376
3072
|
structures,
|
|
377
3073
|
maxSharedStructures: 100,
|
|
378
3074
|
saveStructures(structures) {
|
|
@@ -382,7 +3078,7 @@
|
|
|
382
3078
|
deserialized = packr.unpack(serializedWith32);
|
|
383
3079
|
assert.deepEqual(deserialized, data);
|
|
384
3080
|
structures = structures.slice(0, 32);
|
|
385
|
-
packr = new Packr({
|
|
3081
|
+
packr = new Packr$1({
|
|
386
3082
|
structures,
|
|
387
3083
|
maxSharedStructures: 100,
|
|
388
3084
|
saveStructures(structures) {
|
|
@@ -408,7 +3104,7 @@
|
|
|
408
3104
|
structures.push(['a' + i]);
|
|
409
3105
|
}
|
|
410
3106
|
const structures2 = [...structures];
|
|
411
|
-
const packr = new Packr({
|
|
3107
|
+
const packr = new Packr$1({
|
|
412
3108
|
getStructures() {
|
|
413
3109
|
return structures
|
|
414
3110
|
},
|
|
@@ -416,7 +3112,7 @@
|
|
|
416
3112
|
},
|
|
417
3113
|
maxSharedStructures: 100
|
|
418
3114
|
});
|
|
419
|
-
const packr2 = new Packr({
|
|
3115
|
+
const packr2 = new Packr$1({
|
|
420
3116
|
getStructures() {
|
|
421
3117
|
return structures2
|
|
422
3118
|
},
|
|
@@ -466,7 +3162,7 @@
|
|
|
466
3162
|
ancient: new Date(-3532219539133),
|
|
467
3163
|
invalidDate: new Date('invalid')
|
|
468
3164
|
};
|
|
469
|
-
let packr = new Packr();
|
|
3165
|
+
let packr = new Packr$1();
|
|
470
3166
|
var serialized = packr.pack(data);
|
|
471
3167
|
var deserialized = packr.unpack(serialized);
|
|
472
3168
|
assert.equal(deserialized.map.get(4), 'four');
|
|
@@ -488,7 +3184,7 @@
|
|
|
488
3184
|
date: new Date(1532219539011),
|
|
489
3185
|
invalidDate: new Date('invalid')
|
|
490
3186
|
};
|
|
491
|
-
let packr = new Packr({
|
|
3187
|
+
let packr = new Packr$1({
|
|
492
3188
|
mapsAsObjects: true,
|
|
493
3189
|
useTimestamp32: true,
|
|
494
3190
|
onInvalidDate: () => 'Custom invalid date'
|
|
@@ -544,7 +3240,7 @@
|
|
|
544
3240
|
c: 0.00000000000352501,
|
|
545
3241
|
d: 3252.77,
|
|
546
3242
|
};
|
|
547
|
-
let packr = new Packr({
|
|
3243
|
+
let packr = new Packr$1({
|
|
548
3244
|
useFloat32: DECIMAL_FIT
|
|
549
3245
|
});
|
|
550
3246
|
var serialized = packr.pack(data);
|
|
@@ -556,7 +3252,7 @@
|
|
|
556
3252
|
var data = {
|
|
557
3253
|
a: 325283295382932843n
|
|
558
3254
|
};
|
|
559
|
-
let packr = new Packr({
|
|
3255
|
+
let packr = new Packr$1({
|
|
560
3256
|
int64AsNumber: true
|
|
561
3257
|
});
|
|
562
3258
|
var serialized = packr.pack(data);
|
|
@@ -595,7 +3291,7 @@
|
|
|
595
3291
|
tooBig: 2n**66n
|
|
596
3292
|
};
|
|
597
3293
|
assert.throws(function(){ serialized = pack(tooBigInt); });
|
|
598
|
-
let packr = new Packr({
|
|
3294
|
+
let packr = new Packr$1({
|
|
599
3295
|
largeBigIntToFloat: true
|
|
600
3296
|
});
|
|
601
3297
|
serialized = packr.pack(tooBigInt);
|
|
@@ -678,7 +3374,7 @@
|
|
|
678
3374
|
let structures = [];
|
|
679
3375
|
var serialized = pack(data);
|
|
680
3376
|
console.log('MessagePack size', serialized.length);
|
|
681
|
-
let packr = new Packr({ structures, bundleStrings: false });
|
|
3377
|
+
let packr = new Packr$1({ structures, bundleStrings: false });
|
|
682
3378
|
var serialized = packr.pack(data);
|
|
683
3379
|
console.log('msgpackr w/ record ext size', serialized.length);
|
|
684
3380
|
for (var i = 0; i < ITERATIONS; i++) {
|
|
@@ -689,7 +3385,7 @@
|
|
|
689
3385
|
var data = sampleData;
|
|
690
3386
|
this.timeout(10000);
|
|
691
3387
|
let structures = [];
|
|
692
|
-
let packr = new Packr({ structures, bundleStrings: false });
|
|
3388
|
+
let packr = new Packr$1({ structures, bundleStrings: false });
|
|
693
3389
|
let buffer = typeof Buffer != 'undefined' ? Buffer.alloc(0x10000) : new Uint8Array(0x10000);
|
|
694
3390
|
|
|
695
3391
|
for (var i = 0; i < ITERATIONS; i++) {
|
|
@@ -702,4 +3398,5 @@
|
|
|
702
3398
|
});
|
|
703
3399
|
});
|
|
704
3400
|
|
|
705
|
-
}(msgpackr, chai, fs));
|
|
3401
|
+
}(msgpackr, chai, inspector, fs));
|
|
3402
|
+
//# sourceMappingURL=test.js.map
|