msgpackr 1.11.12 → 2.0.1

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.
@@ -29,7 +29,6 @@
29
29
  C1.name = 'MessagePack 0xC1';
30
30
  var sequentialMode = false;
31
31
  var inlineObjectReadThreshold = 2;
32
- var readStruct;
33
32
  var BlockedFunction; // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
34
33
 
35
34
  class Unpackr {
@@ -62,8 +61,8 @@
62
61
  // re-entrant execution, save the state and restore it after we do this unpack
63
62
  return saveState(() => {
64
63
  clearSource();
65
- return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options)
66
- })
64
+ return this ? this.unpack(source, options) : Unpackr.prototype.unpack.call(defaultOptions, source, options);
65
+ });
67
66
  }
68
67
  if (!source.buffer && source.constructor === ArrayBuffer)
69
68
  source = typeof Buffer !== 'undefined' ? Buffer.from(source) : new Uint8Array(source);
@@ -87,14 +86,14 @@
87
86
  // if it doesn't have a buffer, maybe it is the wrong type of object
88
87
  src = null;
89
88
  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))
89
+ throw error;
90
+ throw new Error('Source must be a Uint8Array or Buffer but was a ' + ((source && typeof source == 'object') ? source.constructor.name : typeof source));
92
91
  }
93
92
  if (this instanceof Unpackr) {
94
93
  currentUnpackr = this;
95
94
  if (this.structures) {
96
95
  currentStructures = this.structures;
97
- return checkedRead(options)
96
+ return checkedRead(options);
98
97
  } else if (!currentStructures || currentStructures.length > 0) {
99
98
  currentStructures = [];
100
99
  }
@@ -103,7 +102,7 @@
103
102
  if (!currentStructures || currentStructures.length > 0)
104
103
  currentStructures = [];
105
104
  }
106
- return checkedRead(options)
105
+ return checkedRead(options);
107
106
  }
108
107
  unpackMultiple(source, forEach) {
109
108
  let values, lastPosition = 0;
@@ -116,7 +115,7 @@
116
115
  while(position$1 < size) {
117
116
  lastPosition = position$1;
118
117
  if (forEach(checkedRead(), lastPosition, position$1) === false) {
119
- return
118
+ return;
120
119
  }
121
120
  }
122
121
  }
@@ -126,18 +125,20 @@
126
125
  lastPosition = position$1;
127
126
  values.push(checkedRead());
128
127
  }
129
- return values
128
+ return values;
130
129
  }
131
130
  } catch(error) {
132
131
  error.lastPosition = lastPosition;
133
132
  error.values = values;
134
- throw error
133
+ throw error;
135
134
  } finally {
136
135
  sequentialMode = false;
137
136
  clearSource();
138
137
  }
139
138
  }
140
139
  _mergeStructures(loadedStructures, existingStructures) {
140
+ if (this._onLoadedStructures)
141
+ loadedStructures = this._onLoadedStructures(loadedStructures);
141
142
  loadedStructures = loadedStructures || [];
142
143
  if (Object.isFrozen(loadedStructures))
143
144
  loadedStructures = loadedStructures.map(structure => structure.slice(0));
@@ -161,10 +162,10 @@
161
162
  }
162
163
  }
163
164
  }
164
- return this.structures = loadedStructures
165
+ return this.structures = loadedStructures;
165
166
  }
166
167
  decode(source, options) {
167
- return this.unpack(source, options)
168
+ return this.unpack(source, options);
168
169
  }
169
170
  }
170
171
  function checkedRead(options) {
@@ -175,8 +176,8 @@
175
176
  currentStructures.length = sharedLength;
176
177
  }
177
178
  let result;
178
- if (currentUnpackr.randomAccessStructure && src[position$1] < 0x40 && src[position$1] >= 0x20 && readStruct) {
179
- result = readStruct(src, position$1, srcEnd, currentUnpackr);
179
+ if (currentUnpackr._readStruct && src[position$1] < 0x40 && src[position$1] >= 0x20) {
180
+ result = currentUnpackr._readStruct(src, position$1, srcEnd);
180
181
  src = null; // dispose of this so that recursive unpack calls don't save state
181
182
  if (!(options && options.lazy) && result)
182
183
  result = result.toJSON();
@@ -202,7 +203,7 @@
202
203
  referenceMap = null;
203
204
  } else if (position$1 > srcEnd) {
204
205
  // over read
205
- throw new Error('Unexpected end of MessagePack data')
206
+ throw new Error('Unexpected end of MessagePack data');
206
207
  } else if (!sequentialMode) {
207
208
  let jsonView;
208
209
  try {
@@ -210,10 +211,10 @@
210
211
  } catch(error) {
211
212
  jsonView = '(JSON view not available ' + error + ')';
212
213
  }
213
- throw new Error('Data read, but end of buffer not reached ' + jsonView)
214
+ throw new Error('Data read, but end of buffer not reached ' + jsonView);
214
215
  }
215
216
  // else more to read, but we are reading sequentially, so don't clear source yet
216
- return result
217
+ return result;
217
218
  } catch(error) {
218
219
  if (currentStructures && currentStructures.restoreStructures)
219
220
  restoreStructures();
@@ -221,7 +222,7 @@
221
222
  if (error instanceof RangeError || error.message.startsWith('Unexpected end of buffer') || position$1 > srcEnd) {
222
223
  error.incomplete = true;
223
224
  }
224
- throw error
225
+ throw error;
225
226
  }
226
227
  }
227
228
 
@@ -237,7 +238,7 @@
237
238
  if (token < 0xa0) {
238
239
  if (token < 0x80) {
239
240
  if (token < 0x40)
240
- return token
241
+ return token;
241
242
  else {
242
243
  let structure = currentStructures[token & 0x3f] ||
243
244
  currentUnpackr.getStructures && loadStructures()[token & 0x3f];
@@ -245,9 +246,9 @@
245
246
  if (!structure.read) {
246
247
  structure.read = createStructureReader(structure, token & 0x3f);
247
248
  }
248
- return structure.read()
249
+ return structure.read();
249
250
  } else
250
- return token
251
+ return token;
251
252
  }
252
253
  } else if (token < 0x90) {
253
254
  // map
@@ -260,13 +261,13 @@
260
261
  key = '__proto_';
261
262
  object[key] = read();
262
263
  }
263
- return object
264
+ return object;
264
265
  } else {
265
266
  let map = new Map();
266
267
  for (let i = 0; i < token; i++) {
267
268
  map.set(read(), read());
268
269
  }
269
- return map
270
+ return map;
270
271
  }
271
272
  } else {
272
273
  token -= 0x90;
@@ -275,91 +276,91 @@
275
276
  array[i] = read();
276
277
  }
277
278
  if (currentUnpackr.freezeData)
278
- return Object.freeze(array)
279
- return array
279
+ return Object.freeze(array);
280
+ return array;
280
281
  }
281
282
  } else if (token < 0xc0) {
282
283
  // fixstr
283
284
  let length = token - 0xa0;
284
285
  if (srcStringEnd >= position$1) {
285
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
286
+ return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart);
286
287
  }
287
288
  if (srcStringEnd == 0 && srcEnd < 140) {
288
289
  // for small blocks, avoiding the overhead of the extract call is helpful
289
290
  let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
290
291
  if (string != null)
291
- return string
292
+ return string;
292
293
  }
293
- return readFixedString(length)
294
+ return readFixedString(length);
294
295
  } else {
295
296
  let value;
296
297
  switch (token) {
297
- case 0xc0: return null
298
+ case 0xc0: return null;
298
299
  case 0xc1:
299
300
  if (bundledStrings$1) {
300
301
  value = read(); // followed by the length of the string in characters (not bytes!)
301
302
  if (value > 0)
302
- return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value)
303
+ return bundledStrings$1[1].slice(bundledStrings$1.position1, bundledStrings$1.position1 += value);
303
304
  else
304
- return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value)
305
+ return bundledStrings$1[0].slice(bundledStrings$1.position0, bundledStrings$1.position0 -= value);
305
306
  }
306
307
  return C1; // "never-used", return special object to denote that
307
- case 0xc2: return false
308
- case 0xc3: return true
308
+ case 0xc2: return false;
309
+ case 0xc3: return true;
309
310
  case 0xc4:
310
311
  // bin 8
311
312
  value = src[position$1++];
312
313
  if (value === undefined)
313
- throw new Error('Unexpected end of buffer')
314
- return readBin(value)
314
+ throw new Error('Unexpected end of buffer');
315
+ return readBin(value);
315
316
  case 0xc5:
316
317
  // bin 16
317
318
  value = dataView.getUint16(position$1);
318
319
  position$1 += 2;
319
- return readBin(value)
320
+ return readBin(value);
320
321
  case 0xc6:
321
322
  // bin 32
322
323
  value = dataView.getUint32(position$1);
323
324
  position$1 += 4;
324
- return readBin(value)
325
+ return readBin(value);
325
326
  case 0xc7:
326
327
  // ext 8
327
- return readExt(src[position$1++])
328
+ return readExt(src[position$1++]);
328
329
  case 0xc8:
329
330
  // ext 16
330
331
  value = dataView.getUint16(position$1);
331
332
  position$1 += 2;
332
- return readExt(value)
333
+ return readExt(value);
333
334
  case 0xc9:
334
335
  // ext 32
335
336
  value = dataView.getUint32(position$1);
336
337
  position$1 += 4;
337
- return readExt(value)
338
+ return readExt(value);
338
339
  case 0xca:
339
340
  value = dataView.getFloat32(position$1);
340
341
  if (currentUnpackr.useFloat32 > 2) {
341
342
  // this does rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
342
343
  let multiplier = mult10[((src[position$1] & 0x7f) << 1) | (src[position$1 + 1] >> 7)];
343
344
  position$1 += 4;
344
- return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier
345
+ return ((multiplier * value + (value > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
345
346
  }
346
347
  position$1 += 4;
347
- return value
348
+ return value;
348
349
  case 0xcb:
349
350
  value = dataView.getFloat64(position$1);
350
351
  position$1 += 8;
351
- return value
352
+ return value;
352
353
  // uint handlers
353
354
  case 0xcc:
354
- return src[position$1++]
355
+ return src[position$1++];
355
356
  case 0xcd:
356
357
  value = dataView.getUint16(position$1);
357
358
  position$1 += 2;
358
- return value
359
+ return value;
359
360
  case 0xce:
360
361
  value = dataView.getUint32(position$1);
361
362
  position$1 += 4;
362
- return value
363
+ return value;
363
364
  case 0xcf:
364
365
  if (currentUnpackr.int64AsType === 'number') {
365
366
  value = dataView.getUint32(position$1) * 0x100000000;
@@ -372,19 +373,19 @@
372
373
  } else
373
374
  value = dataView.getBigUint64(position$1);
374
375
  position$1 += 8;
375
- return value
376
+ return value;
376
377
 
377
378
  // int handlers
378
379
  case 0xd0:
379
- return dataView.getInt8(position$1++)
380
+ return dataView.getInt8(position$1++);
380
381
  case 0xd1:
381
382
  value = dataView.getInt16(position$1);
382
383
  position$1 += 2;
383
- return value
384
+ return value;
384
385
  case 0xd2:
385
386
  value = dataView.getInt32(position$1);
386
387
  position$1 += 4;
387
- return value
388
+ return value;
388
389
  case 0xd3:
389
390
  if (currentUnpackr.int64AsType === 'number') {
390
391
  value = dataView.getInt32(position$1) * 0x100000000;
@@ -397,96 +398,96 @@
397
398
  } else
398
399
  value = dataView.getBigInt64(position$1);
399
400
  position$1 += 8;
400
- return value
401
+ return value;
401
402
 
402
403
  case 0xd4:
403
404
  // fixext 1
404
405
  value = src[position$1++];
405
406
  if (value == 0x72) {
406
- return recordDefinition(src[position$1++] & 0x3f)
407
+ return recordDefinition(src[position$1++] & 0x3f);
407
408
  } else {
408
409
  let extension = currentExtensions[value];
409
410
  if (extension) {
410
411
  if (extension.read) {
411
412
  position$1++; // skip filler byte
412
- return extension.read(read())
413
+ return extension.read(read());
413
414
  } else if (extension.noBuffer) {
414
415
  position$1++; // skip filler byte
415
- return extension()
416
+ return extension();
416
417
  } else
417
- return extension(src.subarray(position$1, ++position$1))
418
+ return extension(src.subarray(position$1, ++position$1));
418
419
  } else
419
- throw new Error('Unknown extension ' + value)
420
+ throw new Error('Unknown extension ' + value);
420
421
  }
421
422
  case 0xd5:
422
423
  // fixext 2
423
424
  value = src[position$1];
424
425
  if (value == 0x72) {
425
426
  position$1++;
426
- return recordDefinition(src[position$1++] & 0x3f, src[position$1++])
427
+ return recordDefinition(src[position$1++] & 0x3f, src[position$1++]);
427
428
  } else
428
- return readExt(2)
429
+ return readExt(2);
429
430
  case 0xd6:
430
431
  // fixext 4
431
- return readExt(4)
432
+ return readExt(4);
432
433
  case 0xd7:
433
434
  // fixext 8
434
- return readExt(8)
435
+ return readExt(8);
435
436
  case 0xd8:
436
437
  // fixext 16
437
- return readExt(16)
438
+ return readExt(16);
438
439
  case 0xd9:
439
440
  // str 8
440
441
  value = src[position$1++];
441
442
  if (srcStringEnd >= position$1) {
442
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
443
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
443
444
  }
444
- return readString8(value)
445
+ return readString8(value);
445
446
  case 0xda:
446
447
  // str 16
447
448
  value = dataView.getUint16(position$1);
448
449
  position$1 += 2;
449
450
  if (srcStringEnd >= position$1) {
450
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
451
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
451
452
  }
452
- return readString16(value)
453
+ return readString16(value);
453
454
  case 0xdb:
454
455
  // str 32
455
456
  value = dataView.getUint32(position$1);
456
457
  position$1 += 4;
457
458
  if (srcStringEnd >= position$1) {
458
- return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart)
459
+ return srcString.slice(position$1 - srcStringStart, (position$1 += value) - srcStringStart);
459
460
  }
460
- return readString32(value)
461
+ return readString32(value);
461
462
  case 0xdc:
462
463
  // array 16
463
464
  value = dataView.getUint16(position$1);
464
465
  position$1 += 2;
465
- return readArray(value)
466
+ return readArray(value);
466
467
  case 0xdd:
467
468
  // array 32
468
469
  value = dataView.getUint32(position$1);
469
470
  position$1 += 4;
470
- return readArray(value)
471
+ return readArray(value);
471
472
  case 0xde:
472
473
  // map 16
473
474
  value = dataView.getUint16(position$1);
474
475
  position$1 += 2;
475
- return readMap(value)
476
+ return readMap(value);
476
477
  case 0xdf:
477
478
  // map 32
478
479
  value = dataView.getUint32(position$1);
479
480
  position$1 += 4;
480
- return readMap(value)
481
+ return readMap(value);
481
482
  default: // negative int
482
483
  if (token >= 0xe0)
483
- return token - 0x100
484
+ return token - 0x100;
484
485
  if (token === undefined) {
485
486
  let error = new Error('Unexpected end of MessagePack data');
486
487
  error.incomplete = true;
487
- throw error
488
+ throw error;
488
489
  }
489
- throw new Error('Unknown MessagePack token ' + token)
490
+ throw new Error('Unknown MessagePack token ' + token);
490
491
 
491
492
  }
492
493
  }
@@ -507,7 +508,7 @@
507
508
  }
508
509
  if (structure.highByte === 0)
509
510
  structure.read = createSecondByteReader(firstId, structure.read);
510
- return optimizedReadObject() // second byte is already read, if there is one so immediately read object
511
+ return optimizedReadObject(); // second byte is already read, if there is one so immediately read object
511
512
  }
512
513
  let object = {};
513
514
  for (let i = 0, l = structure.length; i < l; i++) {
@@ -518,38 +519,38 @@
518
519
  }
519
520
  if (currentUnpackr.freezeData)
520
521
  return Object.freeze(object);
521
- return object
522
+ return object;
522
523
  }
523
524
  readObject.count = 0;
524
525
  if (structure.highByte === 0) {
525
- return createSecondByteReader(firstId, readObject)
526
+ return createSecondByteReader(firstId, readObject);
526
527
  }
527
- return readObject
528
+ return readObject;
528
529
  }
529
530
 
530
531
  const createSecondByteReader = (firstId, read0) => {
531
532
  return function() {
532
533
  let highByte = src[position$1++];
533
534
  if (highByte === 0)
534
- return read0()
535
+ return read0();
535
536
  let id = firstId < 32 ? -(firstId + (highByte << 5)) : firstId + (highByte << 5);
536
537
  let structure = currentStructures[id] || loadStructures()[id];
537
538
  if (!structure) {
538
- throw new Error('Record id is not defined for ' + id)
539
+ throw new Error('Record id is not defined for ' + id);
539
540
  }
540
541
  if (!structure.read)
541
542
  structure.read = createStructureReader(structure, firstId);
542
- return structure.read()
543
- }
543
+ return structure.read();
544
+ };
544
545
  };
545
546
 
546
547
  function loadStructures() {
547
548
  let loadedStructures = saveState(() => {
548
549
  // save the state in case getStructures modifies our buffer
549
550
  src = null;
550
- return currentUnpackr.getStructures()
551
+ return currentUnpackr.getStructures();
551
552
  });
552
- return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures)
553
+ return currentStructures = currentUnpackr._mergeStructures(loadedStructures, currentStructures);
553
554
  }
554
555
 
555
556
  var readFixedString = readStringJS;
@@ -561,10 +562,10 @@
561
562
  let result;
562
563
  if (length < 16) {
563
564
  if (result = shortStringInJS(length))
564
- return result
565
+ return result;
565
566
  }
566
567
  if (length > 64 && decoder)
567
- return decoder.decode(src.subarray(position$1, position$1 += length))
568
+ return decoder.decode(src.subarray(position$1, position$1 += length));
568
569
  const end = position$1 + length;
569
570
  const units = [];
570
571
  result = '';
@@ -627,7 +628,7 @@
627
628
  result += fromCharCode.apply(String, units);
628
629
  }
629
630
 
630
- return result
631
+ return result;
631
632
  }
632
633
 
633
634
  function readArray(length) {
@@ -636,8 +637,8 @@
636
637
  array[i] = read();
637
638
  }
638
639
  if (currentUnpackr.freezeData)
639
- return Object.freeze(array)
640
- return array
640
+ return Object.freeze(array);
641
+ return array;
641
642
  }
642
643
 
643
644
  function readMap(length) {
@@ -649,13 +650,13 @@
649
650
  key = '__proto_';
650
651
  object[key] = read();
651
652
  }
652
- return object
653
+ return object;
653
654
  } else {
654
655
  let map = new Map();
655
656
  for (let i = 0; i < length; i++) {
656
657
  map.set(read(), read());
657
658
  }
658
- return map
659
+ return map;
659
660
  }
660
661
  }
661
662
 
@@ -667,40 +668,40 @@
667
668
  const byte = src[position$1++];
668
669
  if ((byte & 0x80) > 0) {
669
670
  position$1 = start;
670
- return
671
+ return;
671
672
  }
672
673
  bytes[i] = byte;
673
674
  }
674
- return fromCharCode.apply(String, bytes)
675
+ return fromCharCode.apply(String, bytes);
675
676
  }
676
677
  function shortStringInJS(length) {
677
678
  if (length < 4) {
678
679
  if (length < 2) {
679
680
  if (length === 0)
680
- return ''
681
+ return '';
681
682
  else {
682
683
  let a = src[position$1++];
683
684
  if ((a & 0x80) > 1) {
684
685
  position$1 -= 1;
685
- return
686
+ return;
686
687
  }
687
- return fromCharCode(a)
688
+ return fromCharCode(a);
688
689
  }
689
690
  } else {
690
691
  let a = src[position$1++];
691
692
  let b = src[position$1++];
692
693
  if ((a & 0x80) > 0 || (b & 0x80) > 0) {
693
694
  position$1 -= 2;
694
- return
695
+ return;
695
696
  }
696
697
  if (length < 3)
697
- return fromCharCode(a, b)
698
+ return fromCharCode(a, b);
698
699
  let c = src[position$1++];
699
700
  if ((c & 0x80) > 0) {
700
701
  position$1 -= 3;
701
- return
702
+ return;
702
703
  }
703
- return fromCharCode(a, b, c)
704
+ return fromCharCode(a, b, c);
704
705
  }
705
706
  } else {
706
707
  let a = src[position$1++];
@@ -709,34 +710,34 @@
709
710
  let d = src[position$1++];
710
711
  if ((a & 0x80) > 0 || (b & 0x80) > 0 || (c & 0x80) > 0 || (d & 0x80) > 0) {
711
712
  position$1 -= 4;
712
- return
713
+ return;
713
714
  }
714
715
  if (length < 6) {
715
716
  if (length === 4)
716
- return fromCharCode(a, b, c, d)
717
+ return fromCharCode(a, b, c, d);
717
718
  else {
718
719
  let e = src[position$1++];
719
720
  if ((e & 0x80) > 0) {
720
721
  position$1 -= 5;
721
- return
722
+ return;
722
723
  }
723
- return fromCharCode(a, b, c, d, e)
724
+ return fromCharCode(a, b, c, d, e);
724
725
  }
725
726
  } else if (length < 8) {
726
727
  let e = src[position$1++];
727
728
  let f = src[position$1++];
728
729
  if ((e & 0x80) > 0 || (f & 0x80) > 0) {
729
730
  position$1 -= 6;
730
- return
731
+ return;
731
732
  }
732
733
  if (length < 7)
733
- return fromCharCode(a, b, c, d, e, f)
734
+ return fromCharCode(a, b, c, d, e, f);
734
735
  let g = src[position$1++];
735
736
  if ((g & 0x80) > 0) {
736
737
  position$1 -= 7;
737
- return
738
+ return;
738
739
  }
739
- return fromCharCode(a, b, c, d, e, f, g)
740
+ return fromCharCode(a, b, c, d, e, f, g);
740
741
  } else {
741
742
  let e = src[position$1++];
742
743
  let f = src[position$1++];
@@ -744,34 +745,34 @@
744
745
  let h = src[position$1++];
745
746
  if ((e & 0x80) > 0 || (f & 0x80) > 0 || (g & 0x80) > 0 || (h & 0x80) > 0) {
746
747
  position$1 -= 8;
747
- return
748
+ return;
748
749
  }
749
750
  if (length < 10) {
750
751
  if (length === 8)
751
- return fromCharCode(a, b, c, d, e, f, g, h)
752
+ return fromCharCode(a, b, c, d, e, f, g, h);
752
753
  else {
753
754
  let i = src[position$1++];
754
755
  if ((i & 0x80) > 0) {
755
756
  position$1 -= 9;
756
- return
757
+ return;
757
758
  }
758
- return fromCharCode(a, b, c, d, e, f, g, h, i)
759
+ return fromCharCode(a, b, c, d, e, f, g, h, i);
759
760
  }
760
761
  } else if (length < 12) {
761
762
  let i = src[position$1++];
762
763
  let j = src[position$1++];
763
764
  if ((i & 0x80) > 0 || (j & 0x80) > 0) {
764
765
  position$1 -= 10;
765
- return
766
+ return;
766
767
  }
767
768
  if (length < 11)
768
- return fromCharCode(a, b, c, d, e, f, g, h, i, j)
769
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j);
769
770
  let k = src[position$1++];
770
771
  if ((k & 0x80) > 0) {
771
772
  position$1 -= 11;
772
- return
773
+ return;
773
774
  }
774
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k)
775
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k);
775
776
  } else {
776
777
  let i = src[position$1++];
777
778
  let j = src[position$1++];
@@ -779,34 +780,34 @@
779
780
  let l = src[position$1++];
780
781
  if ((i & 0x80) > 0 || (j & 0x80) > 0 || (k & 0x80) > 0 || (l & 0x80) > 0) {
781
782
  position$1 -= 12;
782
- return
783
+ return;
783
784
  }
784
785
  if (length < 14) {
785
786
  if (length === 12)
786
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l)
787
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l);
787
788
  else {
788
789
  let m = src[position$1++];
789
790
  if ((m & 0x80) > 0) {
790
791
  position$1 -= 13;
791
- return
792
+ return;
792
793
  }
793
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m)
794
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m);
794
795
  }
795
796
  } else {
796
797
  let m = src[position$1++];
797
798
  let n = src[position$1++];
798
799
  if ((m & 0x80) > 0 || (n & 0x80) > 0) {
799
800
  position$1 -= 14;
800
- return
801
+ return;
801
802
  }
802
803
  if (length < 15)
803
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
804
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n);
804
805
  let o = src[position$1++];
805
806
  if ((o & 0x80) > 0) {
806
807
  position$1 -= 15;
807
- return
808
+ return;
808
809
  }
809
- return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
810
+ return fromCharCode(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o);
810
811
  }
811
812
  }
812
813
  }
@@ -824,22 +825,22 @@
824
825
  case 0xd9:
825
826
  // str 8
826
827
  length = src[position$1++];
827
- break
828
+ break;
828
829
  case 0xda:
829
830
  // str 16
830
831
  length = dataView.getUint16(position$1);
831
832
  position$1 += 2;
832
- break
833
+ break;
833
834
  case 0xdb:
834
835
  // str 32
835
836
  length = dataView.getUint32(position$1);
836
837
  position$1 += 4;
837
- break
838
+ break;
838
839
  default:
839
- throw new Error('Expected string')
840
+ throw new Error('Expected string');
840
841
  }
841
842
  }
842
- return readStringJS(length)
843
+ return readStringJS(length);
843
844
  }
844
845
 
845
846
 
@@ -847,7 +848,7 @@
847
848
  return currentUnpackr.copyBuffers ?
848
849
  // specifically use the copying slice (not the node one)
849
850
  Uint8Array.prototype.slice.call(src, position$1, position$1 += length) :
850
- src.subarray(position$1, position$1 += length)
851
+ src.subarray(position$1, position$1 += length);
851
852
  }
852
853
  function readExt(length) {
853
854
  let type = src[position$1++];
@@ -860,10 +861,10 @@
860
861
  } finally {
861
862
  position$1 = end;
862
863
  }
863
- })
864
+ });
864
865
  }
865
866
  else
866
- throw new Error('Unknown extension type ' + type)
867
+ throw new Error('Unknown extension type ' + type);
867
868
  }
868
869
 
869
870
  var keyCache = new Array(4096);
@@ -873,12 +874,12 @@
873
874
  // fixstr, potentially use key cache
874
875
  length = length - 0xa0;
875
876
  if (srcStringEnd >= position$1) // if it has been extracted, must use it (and faster anyway)
876
- return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart)
877
+ return srcString.slice(position$1 - srcStringStart, (position$1 += length) - srcStringStart);
877
878
  else if (!(srcStringEnd == 0 && srcEnd < 180))
878
- return readFixedString(length)
879
+ return readFixedString(length);
879
880
  } else { // not cacheable, go back and do a standard read
880
881
  position$1--;
881
- return asSafeString(read())
882
+ return asSafeString(read());
882
883
  }
883
884
  let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position$1) : length > 0 ? src[position$1] : 0)) & 0xfff;
884
885
  let entry = keyCache[key];
@@ -891,7 +892,7 @@
891
892
  chunk = dataView.getUint32(checkPosition);
892
893
  if (chunk != entry[i++]) {
893
894
  checkPosition = 0x70000000;
894
- break
895
+ break;
895
896
  }
896
897
  checkPosition += 4;
897
898
  }
@@ -900,12 +901,12 @@
900
901
  chunk = src[checkPosition++];
901
902
  if (chunk != entry[i++]) {
902
903
  checkPosition = 0x70000000;
903
- break
904
+ break;
904
905
  }
905
906
  }
906
907
  if (checkPosition === end) {
907
908
  position$1 = checkPosition;
908
- return entry.string
909
+ return entry.string;
909
910
  }
910
911
  end -= 3;
911
912
  checkPosition = position$1;
@@ -926,8 +927,8 @@
926
927
  // for small blocks, avoiding the overhead of the extract call is helpful
927
928
  let string = length < 16 ? shortStringInJS(length) : longStringInJS(length);
928
929
  if (string != null)
929
- return entry.string = string
930
- return entry.string = readFixedString(length)
930
+ return entry.string = string;
931
+ return entry.string = readFixedString(length);
931
932
  }
932
933
 
933
934
  function asSafeString(property) {
@@ -958,7 +959,7 @@
958
959
  }
959
960
  currentStructures[id] = structure;
960
961
  structure.read = createStructureReader(structure, firstByte);
961
- return structure.read()
962
+ return structure.read();
962
963
  };
963
964
  currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
964
965
  currentExtensions[0].noBuffer = true;
@@ -980,17 +981,17 @@
980
981
  out <<= BigInt(64);
981
982
  out |= view.getBigUint64(i);
982
983
  }
983
- return out
984
+ return out;
984
985
  }
985
986
  // if (length === 8) return view.getBigUint64(start)
986
987
  let middle = start + (length >> 4 << 3);
987
988
  let left = decode(start, middle);
988
989
  let right = decode(middle, end);
989
- return (left << BigInt((end - middle) * 8)) | right
990
+ return (left << BigInt((end - middle) * 8)) | right;
990
991
  };
991
992
  head = (head << BigInt((view.byteLength - headLength) * 8)) | decode(headLength, view.byteLength);
992
993
  }
993
- return head
994
+ return head;
994
995
  };
995
996
 
996
997
  let errors = {
@@ -1001,14 +1002,14 @@
1001
1002
  if (!errors[data[0]]) {
1002
1003
  let error = Error(data[1], { cause: data[2] });
1003
1004
  error.name = data[0];
1004
- return error
1005
+ return error;
1005
1006
  }
1006
- return errors[data[0]](data[1], { cause: data[2] })
1007
+ return errors[data[0]](data[1], { cause: data[2] });
1007
1008
  };
1008
1009
 
1009
1010
  currentExtensions[0x69] = (data) => {
1010
1011
  // id extension (for structured clones)
1011
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1012
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled');
1012
1013
  let id = dataView.getUint32(position$1 - 4);
1013
1014
  if (!referenceMap)
1014
1015
  referenceMap = new Map();
@@ -1029,7 +1030,7 @@
1029
1030
  let targetProperties = read(); // read the next value as the target object to id
1030
1031
  if (!refEntry.used) {
1031
1032
  // no cycle, can just use the returned read object
1032
- return refEntry.target = targetProperties // replace the placeholder with the real one
1033
+ return refEntry.target = targetProperties; // replace the placeholder with the real one
1033
1034
  } else {
1034
1035
  // there is a cycle, so we have to assign properties to original target
1035
1036
  Object.assign(target, targetProperties);
@@ -1040,16 +1041,16 @@
1040
1041
  for (let [k, v] of targetProperties.entries()) target.set(k, v);
1041
1042
  if (target instanceof Set)
1042
1043
  for (let i of Array.from(targetProperties)) target.add(i);
1043
- return target
1044
+ return target;
1044
1045
  };
1045
1046
 
1046
1047
  currentExtensions[0x70] = (data) => {
1047
1048
  // pointer extension (for structured clones)
1048
- if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled')
1049
+ if (currentUnpackr.structuredClone === false) throw new Error('Structured clone extension is disabled');
1049
1050
  let id = dataView.getUint32(position$1 - 4);
1050
1051
  let refEntry = referenceMap.get(id);
1051
1052
  refEntry.used = true;
1052
- return refEntry.target
1053
+ return refEntry.target;
1053
1054
  };
1054
1055
 
1055
1056
  currentExtensions[0x73] = () => new Set(read());
@@ -1064,15 +1065,15 @@
1064
1065
 
1065
1066
  let typedArrayName = typedArrays[typeCode];
1066
1067
  if (!typedArrayName) {
1067
- if (typeCode === 16) return buffer
1068
- if (typeCode === 17) return new DataView(buffer)
1069
- throw new Error('Could not find typed array for code ' + typeCode)
1068
+ if (typeCode === 16) return buffer;
1069
+ if (typeCode === 17) return new DataView(buffer);
1070
+ throw new Error('Could not find typed array for code ' + typeCode);
1070
1071
  }
1071
- return new glbl[typedArrayName](buffer)
1072
+ return new glbl[typedArrayName](buffer);
1072
1073
  };
1073
1074
  currentExtensions[0x78] = () => {
1074
1075
  let data = read();
1075
- return new RegExp(data[0], data[1])
1076
+ return new RegExp(data[0], data[1]);
1076
1077
  };
1077
1078
  const TEMP_BUNDLE = [];
1078
1079
  currentExtensions[0x62] = (data) => {
@@ -1085,28 +1086,30 @@
1085
1086
  bundledStrings$1.position1 = 0;
1086
1087
  bundledStrings$1.postBundlePosition = position$1;
1087
1088
  position$1 = dataPosition;
1088
- return read()
1089
+ return read();
1089
1090
  };
1090
1091
 
1091
1092
  currentExtensions[0xff] = (data) => {
1092
1093
  // 32-bit date extension
1093
1094
  if (data.length == 4)
1094
- return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000)
1095
+ return new Date((data[0] * 0x1000000 + (data[1] << 16) + (data[2] << 8) + data[3]) * 1000);
1095
1096
  else if (data.length == 8)
1096
1097
  return new Date(
1097
1098
  ((data[0] << 22) + (data[1] << 14) + (data[2] << 6) + (data[3] >> 2)) / 1000000 +
1098
- ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000)
1099
+ ((data[3] & 0x3) * 0x100000000 + data[4] * 0x1000000 + (data[5] << 16) + (data[6] << 8) + data[7]) * 1000);
1099
1100
  else if (data.length == 12)
1100
1101
  return new Date(
1101
1102
  ((data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]) / 1000000 +
1102
- (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000)
1103
+ (((data[4] & 0x80) ? -0x1000000000000 : 0) + data[6] * 0x10000000000 + data[7] * 0x100000000 + data[8] * 0x1000000 + (data[9] << 16) + (data[10] << 8) + data[11]) * 1000);
1103
1104
  else
1104
- return new Date('invalid')
1105
+ return new Date('invalid');
1105
1106
  };
1106
1107
  // registration of bulk record definition?
1107
1108
  // currentExtensions[0x52] = () =>
1108
1109
 
1109
1110
  function saveState(callback) {
1111
+ if (currentUnpackr && currentUnpackr._onSaveState)
1112
+ currentUnpackr._onSaveState();
1110
1113
  let savedSrcEnd = srcEnd;
1111
1114
  let savedPosition = position$1;
1112
1115
  let savedSrcStringStart = srcStringStart;
@@ -1135,7 +1138,7 @@
1135
1138
  currentStructures.splice(0, currentStructures.length, ...savedStructuresContents);
1136
1139
  currentUnpackr = savedPackr;
1137
1140
  dataView = new DataView(src.buffer, src.byteOffset, src.byteLength);
1138
- return value
1141
+ return value;
1139
1142
  }
1140
1143
  function clearSource() {
1141
1144
  src = null;
@@ -1170,8 +1173,12 @@
1170
1173
  function roundFloat32(float32Number) {
1171
1174
  f32Array[0] = float32Number;
1172
1175
  let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
1173
- return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
1176
+ return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier;
1174
1177
  }
1178
+ // Marker for downstream libraries (e.g. structon) to detect per-instance
1179
+ // struct-decoding hooks (this._readStruct, this._onLoadedStructures,
1180
+ // this._onSaveState). See `checkedRead` for the dispatch.
1181
+ Unpackr.SUPPORTS_STRUCT_HOOKS = true;
1175
1182
 
1176
1183
  let textEncoder;
1177
1184
  try {
@@ -1180,7 +1187,7 @@
1180
1187
  let extensions, extensionClasses;
1181
1188
  const hasNodeBuffer = typeof Buffer !== 'undefined';
1182
1189
  const ByteArrayAllocate = hasNodeBuffer ?
1183
- function(length) { return Buffer.allocUnsafeSlow(length) } : Uint8Array;
1190
+ function(length) { return Buffer.allocUnsafeSlow(length); } : Uint8Array;
1184
1191
  const ByteArray = hasNodeBuffer ? Buffer : Uint8Array;
1185
1192
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000;
1186
1193
  let target, keysTarget;
@@ -1188,7 +1195,6 @@
1188
1195
  let position = 0;
1189
1196
  let safeEnd;
1190
1197
  let bundledStrings = null;
1191
- let writeStructSlots;
1192
1198
  const MAX_BUNDLE_SIZE = 0x5500; // maximum characters such that the encoded bytes fits in 16 bits.
1193
1199
  const hasNonLatin = /[\u0080-\uFFFF]/;
1194
1200
  const RECORD_SYMBOL = Symbol('record-id');
@@ -1201,10 +1207,10 @@
1201
1207
  let structures;
1202
1208
  let referenceMap;
1203
1209
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position) {
1204
- return target.utf8Write(string, position, target.byteLength - position)
1210
+ return target.utf8Write(string, position, target.byteLength - position);
1205
1211
  } : (textEncoder && textEncoder.encodeInto) ?
1206
1212
  function(string, position) {
1207
- return textEncoder.encodeInto(string, target.subarray(position)).written
1213
+ return textEncoder.encodeInto(string, target.subarray(position)).written;
1208
1214
  } : false;
1209
1215
 
1210
1216
  let packr = this;
@@ -1216,7 +1222,7 @@
1216
1222
  if (maxSharedStructures == null)
1217
1223
  maxSharedStructures = hasSharedStructures ? 32 : 0;
1218
1224
  if (maxSharedStructures > 8160)
1219
- throw new Error('Maximum maxSharedStructure is 8160')
1225
+ throw new Error('Maximum maxSharedStructure is 8160');
1220
1226
  if (options.structuredClone && options.moreTypes == undefined) {
1221
1227
  this.moreTypes = true;
1222
1228
  }
@@ -1230,7 +1236,7 @@
1230
1236
  let sharedLimitId = maxSharedStructures + 0x40;
1231
1237
  let maxStructureId = maxSharedStructures + maxOwnStructures + 0x40;
1232
1238
  if (maxStructureId > 8256) {
1233
- throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192')
1239
+ throw new Error('Maximum maxSharedStructure + maxOwnStructure is 8192');
1234
1240
  }
1235
1241
  let recordIdsToRemove = [];
1236
1242
  let transitionsCount = 0;
@@ -1266,7 +1272,7 @@
1266
1272
  let sharedLength = structures.sharedLength || 0;
1267
1273
  if (sharedLength > maxSharedStructures) {
1268
1274
  //if (maxSharedStructures <= 32 && structures.sharedLength > 32) // TODO: could support this, but would need to update the limit ids
1269
- throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength)
1275
+ throw new Error('Shared structures is larger than maximum shared structures, try increasing maxSharedStructures to ' + structures.sharedLength);
1270
1276
  }
1271
1277
  if (!structures.transitions) {
1272
1278
  // rebuild our structure transitions
@@ -1274,7 +1280,7 @@
1274
1280
  for (let i = 0; i < sharedLength; i++) {
1275
1281
  let keys = structures[i];
1276
1282
  if (!keys)
1277
- continue
1283
+ continue;
1278
1284
  let nextTransition, transition = structures.transitions;
1279
1285
  for (let j = 0, l = keys.length; j < l; j++) {
1280
1286
  let key = keys[j];
@@ -1296,7 +1302,7 @@
1296
1302
  hasSharedUpdate = false;
1297
1303
  let encodingError;
1298
1304
  try {
1299
- if (packr.randomAccessStructure && value && typeof value === 'object') {
1305
+ if (packr._writeStruct && value && typeof value === 'object') {
1300
1306
  if (value.constructor === Object) writeStruct(value); // simple object
1301
1307
  else if (value.constructor !== Map && !Array.isArray(value) && !extensionClasses.some(extClass => value instanceof extClass)) {
1302
1308
  // allow user classes, if they don't need special handling (but do use toJSON if available)
@@ -1340,15 +1346,15 @@
1340
1346
  packr.offset = position;
1341
1347
  let serialized = insertIds(target.subarray(start, position), idsToInsert);
1342
1348
  referenceMap = null;
1343
- return serialized
1349
+ return serialized;
1344
1350
  }
1345
1351
  packr.offset = position; // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
1346
1352
  if (encodeOptions & REUSE_BUFFER_MODE) {
1347
1353
  target.start = start;
1348
1354
  target.end = position;
1349
- return target
1355
+ return target;
1350
1356
  }
1351
- return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
1357
+ return target.subarray(start, position); // position can change if we call pack again in saveStructures, so we get the buffer now
1352
1358
  } catch(error) {
1353
1359
  encodingError = error;
1354
1360
  throw error;
@@ -1359,16 +1365,16 @@
1359
1365
  let sharedLength = structures.sharedLength || 0;
1360
1366
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1361
1367
  let returnBuffer = target.subarray(start, position);
1362
- let newSharedData = prepareStructures(structures, packr);
1368
+ let newSharedData = (packr._prepareStructures || prepareStructures)(structures, packr);
1363
1369
  if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time
1364
1370
  if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1365
1371
  // get updated structures and try again if the update failed
1366
- return packr.pack(value, encodeOptions)
1372
+ return packr.pack(value, encodeOptions);
1367
1373
  }
1368
1374
  packr.lastNamedStructuresLength = sharedLength;
1369
1375
  // don't keep large buffers around
1370
1376
  if (target.length > 0x40000000) target = null;
1371
- return returnBuffer
1377
+ return returnBuffer;
1372
1378
  }
1373
1379
  }
1374
1380
  }
@@ -1454,7 +1460,7 @@
1454
1460
  bundledStrings[twoByte ? 0 : 1] += value;
1455
1461
  target[position++] = 0xc1;
1456
1462
  pack(twoByte ? -strLength : strLength);
1457
- return
1463
+ return;
1458
1464
  }
1459
1465
  let headerSize;
1460
1466
  // first we estimate the header size, so we can write to the correct location
@@ -1528,7 +1534,7 @@
1528
1534
  } else if (type === 'number') {
1529
1535
  if (value >>> 0 === value) {// positive integer, 32-bit or less
1530
1536
  // positive uint
1531
- if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this.randomAccessStructure)) {
1537
+ if (value < 0x20 || (value < 0x80 && this.useRecords === false) || (value < 0x40 && !this._writeStruct)) {
1532
1538
  target[position++] = value;
1533
1539
  } else if (value < 0x100) {
1534
1540
  target[position++] = 0xcc;
@@ -1567,7 +1573,7 @@
1567
1573
  // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
1568
1574
  ((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
1569
1575
  position += 4;
1570
- return
1576
+ return;
1571
1577
  } else
1572
1578
  position--; // move back into position for writing a double
1573
1579
  }
@@ -1590,7 +1596,7 @@
1590
1596
  target[position++] = 0x70; // "p" for pointer
1591
1597
  targetView.setUint32(position, referee.id);
1592
1598
  position += 4;
1593
- return
1599
+ return;
1594
1600
  } else
1595
1601
  referenceMap.set(value, { offset: position - start });
1596
1602
  }
@@ -1640,7 +1646,7 @@
1640
1646
  } else {
1641
1647
  pack(writeResult);
1642
1648
  }
1643
- return
1649
+ return;
1644
1650
  }
1645
1651
  let currentTarget = target;
1646
1652
  let currentTargetView = targetView;
@@ -1657,7 +1663,7 @@
1657
1663
  makeRoom(position);
1658
1664
  return {
1659
1665
  target, targetView, position: position - size
1660
- }
1666
+ };
1661
1667
  }, pack);
1662
1668
  } finally {
1663
1669
  // restore current target information (unless already restored)
@@ -1673,7 +1679,7 @@
1673
1679
  makeRoom(result.length + position);
1674
1680
  position = writeExtensionData(result, target, position, extension.type);
1675
1681
  }
1676
- return
1682
+ return;
1677
1683
  }
1678
1684
  }
1679
1685
  // check isArray after extensions, because extensions can extend Array
@@ -1685,7 +1691,7 @@
1685
1691
  const json = value.toJSON();
1686
1692
  // if for some reason value.toJSON returns itself it'll loop forever
1687
1693
  if (json !== value)
1688
- return pack(json)
1694
+ return pack(json);
1689
1695
  }
1690
1696
 
1691
1697
  // if there is a writeFunction, use it, otherwise just encode as undefined
@@ -1724,7 +1730,7 @@
1724
1730
  let chunks = [];
1725
1731
  while (true) {
1726
1732
  chunks.push(value & mask);
1727
- if ((value >> BigInt(63)) === empty) break
1733
+ if ((value >> BigInt(63)) === empty) break;
1728
1734
  value >>= BigInt(64);
1729
1735
  }
1730
1736
 
@@ -1756,11 +1762,11 @@
1756
1762
  if (array.length + position > safeEnd)
1757
1763
  makeRoom(array.length + position);
1758
1764
  position = writeExtensionData(array, target, position, 0x42);
1759
- return
1765
+ return;
1760
1766
  } else {
1761
1767
  throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
1762
1768
  ' useBigIntExtension, or set largeBigIntToFloat to convert to float-64, or set' +
1763
- ' largeBigIntToString to convert to string')
1769
+ ' largeBigIntToString to convert to string');
1764
1770
  }
1765
1771
  }
1766
1772
  position += 8;
@@ -1773,7 +1779,7 @@
1773
1779
  target[position++] = 0;
1774
1780
  }
1775
1781
  } else {
1776
- throw new Error('Unknown type: ' + type)
1782
+ throw new Error('Unknown type: ' + type);
1777
1783
  }
1778
1784
  };
1779
1785
 
@@ -1919,12 +1925,30 @@
1919
1925
  checkUseRecords(object) ? writeRecord(object) : writePlainObject(object);
1920
1926
  } : writeRecord;
1921
1927
 
1928
+ const writeStruct = (object) => {
1929
+ let newPosition = packr._writeStruct(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1930
+ if (notifySharedUpdate)
1931
+ return hasSharedUpdate = true;
1932
+ position = newPosition;
1933
+ let startTarget = target;
1934
+ pack(value);
1935
+ resetStructures();
1936
+ if (startTarget !== target) {
1937
+ return { position, targetView, target }; // indicate the buffer was re-allocated
1938
+ }
1939
+ return position;
1940
+ });
1941
+ if (newPosition === 0) // bail and go to a msgpack object
1942
+ return writeObject(object);
1943
+ position = newPosition;
1944
+ };
1945
+
1922
1946
  const makeRoom = (end) => {
1923
1947
  let newSize;
1924
1948
  if (end > 0x1000000) {
1925
1949
  // special handling for really large buffers
1926
1950
  if ((end - start) > MAX_BUFFER_SIZE)
1927
- throw new Error('Packed buffer would be larger than maximum buffer size')
1951
+ throw new Error('Packed buffer would be larger than maximum buffer size');
1928
1952
  newSize = Math.min(MAX_BUFFER_SIZE,
1929
1953
  Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000);
1930
1954
  } else // faster handling for smaller buffers
@@ -1939,7 +1963,7 @@
1939
1963
  position -= start;
1940
1964
  start = 0;
1941
1965
  safeEnd = newBuffer.length - 10;
1942
- return target = newBuffer
1966
+ return target = newBuffer;
1943
1967
  };
1944
1968
  const newRecord = (transition, keys, newTransitions) => {
1945
1969
  let recordId = structures.nextId;
@@ -2021,23 +2045,6 @@
2021
2045
  target[insertionOffset + start] = keysTarget[0];
2022
2046
  }
2023
2047
  };
2024
- const writeStruct = (object) => {
2025
- let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
2026
- if (notifySharedUpdate)
2027
- return hasSharedUpdate = true;
2028
- position = newPosition;
2029
- let startTarget = target;
2030
- pack(value);
2031
- resetStructures();
2032
- if (startTarget !== target) {
2033
- return { position, targetView, target }; // indicate the buffer was re-allocated
2034
- }
2035
- return position;
2036
- }, this);
2037
- if (newPosition === 0) // bail and go to a msgpack object
2038
- return writeObject(object);
2039
- position = newPosition;
2040
- };
2041
2048
  }
2042
2049
  useBuffer(buffer) {
2043
2050
  // this means we are finished using our own buffer and we can write over it safely
@@ -2080,7 +2087,7 @@
2080
2087
  } else if (isNaN(seconds)) {
2081
2088
  if (this.onInvalidDate) {
2082
2089
  allocateForWrite(0);
2083
- return pack(this.onInvalidDate())
2090
+ return pack(this.onInvalidDate());
2084
2091
  }
2085
2092
  // Intentionally invalid timestamp
2086
2093
  let { target, targetView, position} = allocateForWrite(3);
@@ -2101,7 +2108,7 @@
2101
2108
  pack(set, allocateForWrite, pack) {
2102
2109
  if (this.setAsEmptyObject) {
2103
2110
  allocateForWrite(0);
2104
- return pack({})
2111
+ return pack({});
2105
2112
  }
2106
2113
  let array = Array.from(set);
2107
2114
  let { target, position} = allocateForWrite(this.moreTypes ? 3 : 0);
@@ -2209,19 +2216,19 @@
2209
2216
  switch (length) {
2210
2217
  case 1:
2211
2218
  target[position++] = 0xd4;
2212
- break
2219
+ break;
2213
2220
  case 2:
2214
2221
  target[position++] = 0xd5;
2215
- break
2222
+ break;
2216
2223
  case 4:
2217
2224
  target[position++] = 0xd6;
2218
- break
2225
+ break;
2219
2226
  case 8:
2220
2227
  target[position++] = 0xd7;
2221
- break
2228
+ break;
2222
2229
  case 16:
2223
2230
  target[position++] = 0xd8;
2224
- break
2231
+ break;
2225
2232
  default:
2226
2233
  if (length < 0x100) {
2227
2234
  target[position++] = 0xc7;
@@ -2241,7 +2248,7 @@
2241
2248
  target[position++] = type;
2242
2249
  target.set(result, position);
2243
2250
  position += length;
2244
- return position
2251
+ return position;
2245
2252
  }
2246
2253
 
2247
2254
  function insertIds(serialized, idsToInsert) {
@@ -2263,7 +2270,7 @@
2263
2270
  serialized[position++] = id & 0xff;
2264
2271
  lastEnd = offset;
2265
2272
  }
2266
- return serialized
2273
+ return serialized;
2267
2274
  }
2268
2275
 
2269
2276
  function writeBundles(start, pack, incrementPosition) {
@@ -2280,9 +2287,9 @@
2280
2287
  function addExtension(extension) {
2281
2288
  if (extension.Class) {
2282
2289
  if (!extension.pack && !extension.write)
2283
- throw new Error('Extension has no pack or write function')
2290
+ throw new Error('Extension has no pack or write function');
2284
2291
  if (extension.pack && !extension.type)
2285
- throw new Error('Extension has no type (numeric code to identify the extension)')
2292
+ throw new Error('Extension has no type (numeric code to identify the extension)');
2286
2293
  extensionClasses.unshift(extension.Class);
2287
2294
  extensions.unshift(extension);
2288
2295
  }
@@ -2295,9 +2302,14 @@
2295
2302
  packr._mergeStructures(existingStructures);
2296
2303
  return compatible;
2297
2304
  };
2298
- return structures
2305
+ return structures;
2299
2306
  }
2300
2307
 
2308
+ // Marker for downstream libraries (e.g. structon) to detect that this Packr
2309
+ // supports per-instance struct-encoding hooks (this._writeStruct,
2310
+ // this._prepareStructures). See `pack` for the dispatch.
2311
+ Packr.SUPPORTS_STRUCT_HOOKS = true;
2312
+
2301
2313
  let defaultPackr = new Packr({ useRecords: false });
2302
2314
  const pack = defaultPackr.pack;
2303
2315
  const encode = defaultPackr.pack;
@@ -2316,13 +2328,13 @@
2316
2328
  */
2317
2329
  function packIter (objectIterator, options = {}) {
2318
2330
  if (!objectIterator || typeof objectIterator !== 'object') {
2319
- throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
2331
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable');
2320
2332
  } else if (typeof objectIterator[Symbol.iterator] === 'function') {
2321
- return packIterSync(objectIterator, options)
2333
+ return packIterSync(objectIterator, options);
2322
2334
  } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
2323
- return packIterAsync(objectIterator, options)
2335
+ return packIterAsync(objectIterator, options);
2324
2336
  } else {
2325
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
2337
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise');
2326
2338
  }
2327
2339
  }
2328
2340
 
@@ -2349,7 +2361,7 @@
2349
2361
  */
2350
2362
  function unpackIter (bufferIterator, options = {}) {
2351
2363
  if (!bufferIterator || typeof bufferIterator !== 'object') {
2352
- throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
2364
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise');
2353
2365
  }
2354
2366
 
2355
2367
  const unpackr = new Unpackr(options);
@@ -2369,10 +2381,10 @@
2369
2381
  incomplete = chunk.slice(err.lastPosition);
2370
2382
  yields = err.values;
2371
2383
  } else {
2372
- throw err
2384
+ throw err;
2373
2385
  }
2374
2386
  }
2375
- return yields
2387
+ return yields;
2376
2388
  };
2377
2389
 
2378
2390
  if (typeof bufferIterator[Symbol.iterator] === 'function') {
@@ -2380,13 +2392,13 @@
2380
2392
  for (const value of bufferIterator) {
2381
2393
  yield * parser(value);
2382
2394
  }
2383
- })()
2395
+ })();
2384
2396
  } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
2385
2397
  return (async function * iter () {
2386
2398
  for await (const value of bufferIterator) {
2387
2399
  yield * parser(value);
2388
2400
  }
2389
- })()
2401
+ })();
2390
2402
  }
2391
2403
  }
2392
2404
  const decodeIter = unpackIter;