msgpackr 1.9.8 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/test.js CHANGED
@@ -984,6 +984,17 @@
984
984
  currentExtensions[0] = () => {}; // notepack defines extension 0 to mean undefined, so use that as the default here
985
985
  currentExtensions[0].noBuffer = true;
986
986
 
987
+ currentExtensions[0x42] = (data) => {
988
+ // decode bigint
989
+ let length = data.length;
990
+ let value = BigInt(data[0] & 0x80 ? data[0] - 0x100 : data[0]);
991
+ for (let i = 1; i < length; i++) {
992
+ value <<= 8n;
993
+ value += BigInt(data[i]);
994
+ }
995
+ return value;
996
+ };
997
+
987
998
  let errors = { Error, TypeError, ReferenceError };
988
999
  currentExtensions[0x65] = () => {
989
1000
  let data = read();
@@ -1268,6 +1279,7 @@
1268
1279
  }
1269
1280
  if (hasSharedUpdate)
1270
1281
  hasSharedUpdate = false;
1282
+ let encodingError;
1271
1283
  try {
1272
1284
  if (packr.randomAccessStructure && value && value.constructor && value.constructor === Object)
1273
1285
  writeStruct(value);
@@ -1318,6 +1330,9 @@
1318
1330
  return target
1319
1331
  }
1320
1332
  return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
1333
+ } catch(error) {
1334
+ encodingError = error;
1335
+ throw error;
1321
1336
  } finally {
1322
1337
  if (structures) {
1323
1338
  resetStructures();
@@ -1326,12 +1341,14 @@
1326
1341
  // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
1327
1342
  let returnBuffer = target.subarray(start, position);
1328
1343
  let newSharedData = prepareStructures$1(structures, packr);
1329
- if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1330
- // get updated structures and try again if the update failed
1331
- return packr.pack(value)
1344
+ if (!encodingError) { // TODO: If there is an encoding error, should make the structures as uninitialized so they get rebuilt next time
1345
+ if (packr.saveStructures(newSharedData, newSharedData.isCompatible) === false) {
1346
+ // get updated structures and try again if the update failed
1347
+ return packr.pack(value, encodeOptions)
1348
+ }
1349
+ packr.lastNamedStructuresLength = sharedLength;
1350
+ return returnBuffer
1332
1351
  }
1333
- packr.lastNamedStructuresLength = sharedLength;
1334
- return returnBuffer
1335
1352
  }
1336
1353
  }
1337
1354
  if (encodeOptions & RESET_BUFFER_MODE)
@@ -1673,8 +1690,26 @@
1673
1690
  if (this.largeBigIntToFloat) {
1674
1691
  target[position++] = 0xcb;
1675
1692
  targetView.setFloat64(position, Number(value));
1693
+ } else if (this.useBigIntExtension && value < 2n**(1023n) && value > -(2n**(1023n))) {
1694
+ target[position++] = 0xc7;
1695
+ position++;
1696
+ target[position++] = 0x42; // "B" for BigInt
1697
+ let bytes = [];
1698
+ let alignedSign;
1699
+ do {
1700
+ let byte = value & 0xffn;
1701
+ alignedSign = (byte & 0x80n) === (value < 0n ? 0x80n : 0n);
1702
+ bytes.push(byte);
1703
+ value >>= 8n;
1704
+ } while (!((value === 0n || value === -1n) && alignedSign));
1705
+ target[position-2] = bytes.length;
1706
+ for (let i = bytes.length; i > 0;) {
1707
+ target[position++] = Number(bytes[--i]);
1708
+ }
1709
+ return
1676
1710
  } else {
1677
- throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, set largeBigIntToFloat to convert to float-64')
1711
+ throw new RangeError(value + ' was too large to fit in MessagePack 64-bit integer format, use' +
1712
+ ' useBigIntExtension or set largeBigIntToFloat to convert to float-64')
1678
1713
  }
1679
1714
  }
1680
1715
  position += 8;
@@ -1922,7 +1957,7 @@
1922
1957
  }
1923
1958
  };
1924
1959
  const writeStruct = (object, safePrototype) => {
1925
- let newPosition = writeStructSlots(object, target, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1960
+ let newPosition = writeStructSlots(object, target, start, position, structures, makeRoom, (value, newPosition, notifySharedUpdate) => {
1926
1961
  if (notifySharedUpdate)
1927
1962
  return hasSharedUpdate = true;
1928
1963
  position = newPosition;
@@ -2223,7 +2258,7 @@
2223
2258
  return textEncoder.encodeInto(string, target.subarray(position)).written
2224
2259
  } : false;
2225
2260
  setWriteStructSlots(writeStruct, prepareStructures);
2226
- function writeStruct(object, target, position, structures, makeRoom, pack, packr) {
2261
+ function writeStruct(object, target, encodingStart, position, structures, makeRoom, pack, packr) {
2227
2262
  let typedStructs = packr.typedStructs || (packr.typedStructs = []);
2228
2263
  // note that we rely on pack.js to load stored structures before we get to this point
2229
2264
  let targetView = target.dataView;
@@ -2231,12 +2266,12 @@
2231
2266
  let safeEnd = target.length - 10;
2232
2267
  let start = position;
2233
2268
  if (position > safeEnd) {
2234
- let lastStart = start;
2235
2269
  target = makeRoom(position);
2236
2270
  targetView = target.dataView;
2237
- position -= lastStart;
2238
- refsStartPosition -= lastStart;
2239
- start = 0;
2271
+ position -= encodingStart;
2272
+ start -= encodingStart;
2273
+ refsStartPosition -= encodingStart;
2274
+ encodingStart = 0;
2240
2275
  safeEnd = target.length - 10;
2241
2276
  }
2242
2277
 
@@ -2274,13 +2309,13 @@
2274
2309
  };
2275
2310
  }
2276
2311
  if (position > safeEnd) {
2277
- let lastStart = start;
2278
2312
  target = makeRoom(position);
2279
2313
  targetView = target.dataView;
2280
- position -= lastStart;
2281
- refsStartPosition -= lastStart;
2282
- refPosition -= lastStart;
2283
- start = 0;
2314
+ position -= encodingStart;
2315
+ start -= encodingStart;
2316
+ refsStartPosition -= encodingStart;
2317
+ refPosition -= encodingStart;
2318
+ encodingStart = 0;
2284
2319
  safeEnd = target.length - 10;
2285
2320
  }
2286
2321
  switch (typeof value) {
@@ -2319,13 +2354,13 @@
2319
2354
  let strLength = value.length;
2320
2355
  refOffset = refPosition - refsStartPosition;
2321
2356
  if ((strLength << 2) + refPosition > safeEnd) {
2322
- let lastStart = start;
2323
2357
  target = makeRoom((strLength << 2) + refPosition);
2324
2358
  targetView = target.dataView;
2325
- position -= lastStart;
2326
- refsStartPosition -= lastStart;
2327
- refPosition -= lastStart;
2328
- start = 0;
2359
+ position -= encodingStart;
2360
+ start -= encodingStart;
2361
+ refsStartPosition -= encodingStart;
2362
+ refPosition -= encodingStart;
2363
+ encodingStart = 0;
2329
2364
  safeEnd = target.length - 10;
2330
2365
  }
2331
2366
  if (strLength > ((0xff00 + refOffset) >> 2)) {
@@ -2427,6 +2462,8 @@
2427
2462
  position = updatedPosition;
2428
2463
  } else queuedReferences.push(key, value, keyIndex);
2429
2464
  break;
2465
+ default:
2466
+ queuedReferences.push(key, value, keyIndex);
2430
2467
  }
2431
2468
  keyIndex++;
2432
2469
  }
@@ -2484,9 +2521,10 @@
2484
2521
  refPosition = newPosition.position;
2485
2522
  targetView = newPosition.targetView;
2486
2523
  target = newPosition.target;
2487
- refsStartPosition -= start;
2488
- position -= start;
2489
- start = 0;
2524
+ refsStartPosition -= encodingStart;
2525
+ position -= encodingStart;
2526
+ start -= encodingStart;
2527
+ encodingStart = 0;
2490
2528
  } else
2491
2529
  refPosition = newPosition;
2492
2530
  if (size === 2) {
@@ -2560,7 +2598,7 @@
2560
2598
  if (refsStartPosition === refPosition)
2561
2599
  return position; // no refs
2562
2600
  typedStructs.lastStringStart = position - start;
2563
- return writeStruct(object, target, start, structures, makeRoom, pack, packr);
2601
+ return writeStruct(object, target, encodingStart, start, structures, makeRoom, pack, packr);
2564
2602
  }
2565
2603
  return refPosition;
2566
2604
  }
@@ -3340,6 +3378,22 @@
3340
3378
  assert.equal(pack(123).length, 1);
3341
3379
  });
3342
3380
 
3381
+ test('BigInt', function() {
3382
+ let packr = new Packr({useBigIntExtension: true});
3383
+ let data = {
3384
+ a: 3333333333333333333333333333n,
3385
+ b: 1234567890123456789012345678901234567890n,
3386
+ c: -3333333333333333333333333333n,
3387
+ d: -352523523642364364364264264264264264262642642n,
3388
+ e: 0xffffffffffffffffffffffffffn,
3389
+ f: -0xffffffffffffffffffffffffffn,
3390
+ };
3391
+ let serialized = packr.pack(data);
3392
+ let deserialized = packr.unpack(serialized);
3393
+ assert.deepEqual(data, deserialized);
3394
+ });
3395
+
3396
+
3343
3397
  test('extended class pack/unpack', function(){
3344
3398
  function Extended() {
3345
3399
 
@@ -3609,6 +3663,19 @@
3609
3663
  var deserialized = unpack(serialized);
3610
3664
  assert.equal(deserialized.aDate, data.aDate.toString());
3611
3665
  });
3666
+ test('standard pack fails on circular reference with shared structures', function () {
3667
+ var data = {};
3668
+ data.self = data;
3669
+ let structures = [];
3670
+ let packr = new Packr({
3671
+ structures,
3672
+ saveStructures(structures) {
3673
+ }
3674
+ });
3675
+ assert.throws(function () {
3676
+ packr.pack(data);
3677
+ });
3678
+ });
3612
3679
 
3613
3680
  test('proto handling', function() {
3614
3681
  var objectWithProto = JSON.parse('{"__proto__":{"foo":3}}');