msgpackr 1.7.0-alpha7 → 1.7.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/index.d.ts CHANGED
@@ -1,17 +1,65 @@
1
- export {
2
- Unpackr,
3
- Decoder,
4
- unpack,
5
- unpackMultiple,
6
- decode,
7
- addExtension,
8
- FLOAT32_OPTIONS,
9
- clearSource,
10
- roundFloat32,
11
- isNativeAccelerationEnabled,
12
- } from './unpack'
13
- import { Options } from './unpack'
14
- export { Packr, Encoder, pack, encode } from './pack'
1
+ export enum FLOAT32_OPTIONS {
2
+ NEVER = 0,
3
+ ALWAYS = 1,
4
+ DECIMAL_ROUND = 3,
5
+ DECIMAL_FIT = 4
6
+ }
7
+
8
+ export interface Options {
9
+ useFloat32?: FLOAT32_OPTIONS
10
+ useRecords?: boolean
11
+ structures?: {}[]
12
+ moreTypes?: boolean
13
+ structuredClone?: boolean
14
+ mapsAsObjects?: boolean
15
+ variableMapSize?: boolean
16
+ copyBuffers?: boolean
17
+ bundleStrings?: boolean
18
+ useTimestamp32?: boolean
19
+ largeBigIntToFloat?: boolean
20
+ encodeUndefinedAsNil?: boolean
21
+ maxSharedStructures?: number
22
+ maxOwnStructures?: number
23
+ int64AsNumber?: boolean
24
+ shouldShareStructure?: (keys: string[]) => boolean
25
+ getStructures?(): {}[]
26
+ saveStructures?(structures: {}[]): boolean | void
27
+ onInvalidDate?: () => any
28
+ }
29
+ interface Extension {
30
+ Class: Function
31
+ type: number
32
+ pack?(value: any): Buffer | Uint8Array
33
+ unpack?(messagePack: Buffer | Uint8Array): any
34
+ read?(datum: any): any
35
+ write?(instance: any): any
36
+ }
37
+ export class Unpackr {
38
+ constructor(options?: Options)
39
+ unpack(messagePack: Buffer | Uint8Array): any
40
+ decode(messagePack: Buffer | Uint8Array): any
41
+ unpackMultiple(messagePack: Buffer | Uint8Array): any[]
42
+ unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
43
+ }
44
+ export class Decoder extends Unpackr {}
45
+ export function unpack(messagePack: Buffer | Uint8Array): any
46
+ export function unpackMultiple(messagePack: Buffer | Uint8Array): any[]
47
+ export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
48
+ export function decode(messagePack: Buffer | Uint8Array): any
49
+ export function addExtension(extension: Extension): void
50
+ export function clearSource(): void
51
+ export function roundFloat32(float32Number: number): number
52
+ export const C1: {}
53
+ export let isNativeAccelerationEnabled: boolean
54
+
55
+ export class Packr extends Unpackr {
56
+ pack(value: any): Buffer
57
+ encode(value: any): Buffer
58
+ }
59
+ export class Encoder extends Packr {}
60
+ export function pack(value: any): Buffer
61
+ export function encode(value: any): Buffer
62
+
15
63
  import { Transform, Readable } from 'stream'
16
64
 
17
65
  export as namespace msgpackr;
package/pack.d.ts CHANGED
@@ -1,9 +1 @@
1
- import { Unpackr } from './unpack'
2
- export { addExtension, FLOAT32_OPTIONS } from './unpack'
3
- export class Packr extends Unpackr {
4
- pack(value: any): Buffer
5
- encode(value: any): Buffer
6
- }
7
- export class Encoder extends Packr {}
8
- export function pack(value: any): Buffer
9
- export function encode(value: any): Buffer
1
+ export { Unpackr, Decoder, Packr, Encoder, pack, encode, unpack, decode, addExtension, FLOAT32_OPTIONS } from '.'
package/pack.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict"
2
1
  import { Unpackr, mult10, C1Type, typedArrays, addExtension as unpackAddExtension } from './unpack.js'
3
2
  let textEncoder
4
3
  try {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "msgpackr",
3
3
  "author": "Kris Zyp",
4
- "version": "1.7.0-alpha7",
4
+ "version": "1.7.0",
5
5
  "description": "Ultra-fast MessagePack implementation with extensions for records and structured cloning",
6
6
  "license": "MIT",
7
7
  "types": "./index.d.ts",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "scripts": {
22
22
  "benchmark": "node ./tests/benchmark.cjs",
23
- "build": "rollup -c",
23
+ "build": "rollup -c && cpy index.d.ts . --rename=index.d.cts",
24
24
  "dry-run": "npm publish --dry-run",
25
25
  "prepare": "npm run build",
26
26
  "test": "mocha tests/test**.*js -u tdd --experimental-json-modules"
@@ -36,6 +36,10 @@
36
36
  "require": "./dist/node.cjs",
37
37
  "import": "./node-index.js"
38
38
  },
39
+ "types": {
40
+ "require": "./index.d.cts",
41
+ "import": "./index.d.ts"
42
+ },
39
43
  "default": "./index.js"
40
44
  },
41
45
  "./pack": {
@@ -68,13 +72,14 @@
68
72
  "/*.ts"
69
73
  ],
70
74
  "optionalDependencies": {
71
- "msgpackr-extract": "^2.1.1"
75
+ "msgpackr-extract": "^2.1.2"
72
76
  },
73
77
  "devDependencies": {
74
78
  "@rollup/plugin-json": "^4.1.0",
75
79
  "@types/node": "latest",
76
80
  "async": "^3",
77
81
  "chai": "^4.3.4",
82
+ "cpy-cli": "^4.1.0",
78
83
  "esm": "^3.2.25",
79
84
  "mocha": "^8.1.3",
80
85
  "rollup": "^1.20.3",
package/struct.js CHANGED
@@ -45,6 +45,14 @@ const DATE = 16;
45
45
  const TYPE_NAMES = ['num', 'object', 'string', 'ascii'];
46
46
  TYPE_NAMES[DATE] = 'date';
47
47
  const float32Headers = [false, true, true, false, false, true, true, false];
48
+ let evalSupported;
49
+ try {
50
+ new Function('');
51
+ evalSupported = true;
52
+ } catch(error) {
53
+ // if eval variants are not supported, do not create inline object readers ever
54
+ }
55
+
48
56
  let updatedPosition;
49
57
  const hasNodeBuffer = typeof Buffer !== 'undefined'
50
58
  let textEncoder, currentSource;
@@ -472,9 +480,8 @@ function onLoadedStructures(sharedData) {
472
480
  this.lastTypedStructuresLength = typed.length;
473
481
  return named;
474
482
  }
475
- var sourceSymbol = Symbol('source')
483
+ var sourceSymbol = Symbol.for('source')
476
484
  function readStruct(src, position, srcEnd, unpackr) {
477
- // var stringLength = (src[position++] << 8) | src[position++];
478
485
  let recordId = src[position++] - 0x20;
479
486
  if (recordId >= 24) {
480
487
  switch(recordId) {
@@ -505,23 +512,13 @@ function readStruct(src, position, srcEnd, unpackr) {
505
512
  }
506
513
  var prototype = construct.prototype;
507
514
  let properties = [];
508
- Object.defineProperty(prototype, 'toJSON', {
509
- value() {
510
- // return an enumerable object with own properties to JSON stringify
511
- let resolved = {};
512
- for (let i = 0, l = properties.length; i < l; i++) {
513
- let key = properties[i].key;
514
- resolved[key] = this[key];
515
- }
516
- return resolved;
517
- },
518
- // not enumerable or anything
519
- });
520
515
  let currentOffset = 0;
521
516
  let lastRefProperty;
522
517
  for (let i = 0, l = structure.length; i < l; i++) {
523
518
  let definition = structure[i];
524
519
  let [ type, size, key, enumerationOffset ] = definition;
520
+ if (key === '__proto__')
521
+ key = '__proto_';
525
522
  let property = {
526
523
  key,
527
524
  offset: currentOffset,
@@ -535,13 +532,13 @@ function readStruct(src, position, srcEnd, unpackr) {
535
532
  case 0: getRef = () => 0; break;
536
533
  case 1:
537
534
  getRef = (source, position) => {
538
- let ref = source.src[position + property.offset];
535
+ let ref = source.bytes[position + property.offset];
539
536
  return ref >= 0xf6 ? toConstant(ref) : ref;
540
537
  };
541
538
  break;
542
539
  case 2:
543
540
  getRef = (source, position) => {
544
- let src = source.src;
541
+ let src = source.bytes;
545
542
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
546
543
  let ref = dataView.getUint16(position + property.offset, true);
547
544
  return ref >= 0xff00 ? toConstant(ref & 0xff) : ref;
@@ -549,7 +546,7 @@ function readStruct(src, position, srcEnd, unpackr) {
549
546
  break;
550
547
  case 4:
551
548
  getRef = (source, position) => {
552
- let src = source.src;
549
+ let src = source.bytes;
553
550
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
554
551
  let ref = dataView.getUint32(position + property.offset, true);
555
552
  return ref >= 0xffffff00 ? toConstant(ref & 0xff) : ref;
@@ -565,9 +562,8 @@ function readStruct(src, position, srcEnd, unpackr) {
565
562
  lastRefProperty.next = property;
566
563
  lastRefProperty = property;
567
564
  property.multiGetCount = 0;
568
- get = function() {
569
- let source = this[sourceSymbol];
570
- let src = source.src;
565
+ get = function(source) {
566
+ let src = source.bytes;
571
567
  let position = source.position;
572
568
  let refStart = currentOffset + position;
573
569
  let ref = getRef(source, position);
@@ -583,7 +579,7 @@ function readStruct(src, position, srcEnd, unpackr) {
583
579
  next = next.next;
584
580
  }
585
581
  if (end == null)
586
- end = source.srcEnd - refStart;
582
+ end = source.bytesEnd - refStart;
587
583
  if (source.srcString) {
588
584
  return source.srcString.slice(ref, end);
589
585
  }
@@ -599,7 +595,7 @@ function readStruct(src, position, srcEnd, unpackr) {
599
595
  asciiEnd = null;
600
596
  } while((next = next.next));
601
597
  if (asciiEnd == null)
602
- asciiEnd = source.srcEnd - refStart
598
+ asciiEnd = source.bytesEnd - refStart
603
599
  source.srcString = src.toString('latin1', refStart, refStart + asciiEnd);
604
600
  return source.srcString.slice(ref, end);
605
601
  }
@@ -617,13 +613,12 @@ function readStruct(src, position, srcEnd, unpackr) {
617
613
  if (lastRefProperty && !lastRefProperty.next)
618
614
  lastRefProperty.next = property;
619
615
  lastRefProperty = property;
620
- get = function() {
621
- let source = this[sourceSymbol];
616
+ get = function(source) {
622
617
  let position = source.position;
623
618
  let refStart = currentOffset + position;
624
619
  let ref = getRef(source, position);
625
620
  if (typeof ref !== 'number') return ref;
626
- let src = source.src;
621
+ let src = source.bytes;
627
622
  let end, next = property.next;
628
623
  while(next) {
629
624
  end = next.getRef(source, position);
@@ -634,7 +629,7 @@ function readStruct(src, position, srcEnd, unpackr) {
634
629
  next = next.next;
635
630
  }
636
631
  if (end == null)
637
- end = source.srcEnd - refStart;
632
+ end = source.bytesEnd - refStart;
638
633
  if (type === UTF8) {
639
634
  return src.toString('utf8', ref + refStart, end + refStart);
640
635
  } else {
@@ -650,9 +645,8 @@ function readStruct(src, position, srcEnd, unpackr) {
650
645
  case NUMBER:
651
646
  switch(size) {
652
647
  case 4:
653
- get = function () {
654
- let source = this[sourceSymbol];
655
- let src = source.src;
648
+ get = function (source) {
649
+ let src = source.bytes;
656
650
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
657
651
  let position = source.position + property.offset;
658
652
  let value = dataView.getInt32(position, true)
@@ -669,9 +663,8 @@ function readStruct(src, position, srcEnd, unpackr) {
669
663
  };
670
664
  break;
671
665
  case 8:
672
- get = function () {
673
- let source = this[sourceSymbol];
674
- let src = source.src;
666
+ get = function (source) {
667
+ let src = source.bytes;
675
668
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
676
669
  let value = dataView.getFloat64(source.position + property.offset, true);
677
670
  if (isNaN(value)) {
@@ -683,9 +676,8 @@ function readStruct(src, position, srcEnd, unpackr) {
683
676
  };
684
677
  break;
685
678
  case 1:
686
- get = function () {
687
- let source = this[sourceSymbol];
688
- let src = source.src;
679
+ get = function (source) {
680
+ let src = source.bytes;
689
681
  let value = src[source.position + property.offset];
690
682
  return value < 0xf6 ? value : toConstant(value);
691
683
  };
@@ -693,9 +685,8 @@ function readStruct(src, position, srcEnd, unpackr) {
693
685
  }
694
686
  break;
695
687
  case DATE:
696
- get = function () {
697
- let source = this[sourceSymbol];
698
- let src = source.src;
688
+ get = function (source) {
689
+ let src = source.bytes;
699
690
  let dataView = src.dataView || (src.dataView = new DataView(src.buffer, src.byteOffset, src.byteLength));
700
691
  return new Date(dataView.getFloat64(source.position + property.offset, true));
701
692
  };
@@ -704,15 +695,45 @@ function readStruct(src, position, srcEnd, unpackr) {
704
695
  }
705
696
  property.get = get;
706
697
  }
707
- for (let property of properties) // assign in enumeration order
708
- Object.defineProperty(prototype, property.key, { get: property.get, enumerable: true });
698
+ // TODO: load the srcString for faster string decoding on toJSON
699
+ if (evalSupported) {
700
+ let objectLiteralProperties = [];
701
+ let args = [];
702
+ let i = 0;
703
+ for (let property of properties) { // assign in enumeration order
704
+ Object.defineProperty(prototype, property.key, { get: withSource(property.get), enumerable: true });
705
+ let valueFunction = 'v' + i++;
706
+ args.push(valueFunction);
707
+ objectLiteralProperties.push('[' + JSON.stringify(property.key) + ']:' + valueFunction + '(s)');
708
+ }
709
+ let toObject = (new Function(...args, 'return function(s){return{' + objectLiteralProperties.join(',') + '}}')).apply(null, properties.map(prop => prop.get));
710
+ Object.defineProperty(prototype, 'toJSON', {
711
+ value() {
712
+ return toObject(this[sourceSymbol]);
713
+ }
714
+ });
715
+ } else {
716
+ Object.defineProperty(prototype, 'toJSON', {
717
+ value() {
718
+ // return an enumerable object with own properties to JSON stringify
719
+ let resolved = {};
720
+ for (let i = 0, l = properties.length; i < l; i++) {
721
+ let key = properties[i].key;
722
+
723
+ resolved[key] = this[key];
724
+ }
725
+ return resolved;
726
+ },
727
+ // not enumerable or anything
728
+ });
729
+ }
709
730
  }
710
731
  var instance = new construct();
711
732
  instance[sourceSymbol] = {
712
- src,
733
+ bytes: src,
713
734
  position,
714
735
  srcString: '',
715
- srcEnd
736
+ bytesEnd: srcEnd
716
737
  }
717
738
  return instance;
718
739
  }
@@ -725,12 +746,17 @@ function toConstant(code) {
725
746
  }
726
747
  throw new Error('Unknown constant');
727
748
  }
749
+ function withSource(get) {
750
+ return function() {
751
+ return get(this[sourceSymbol]);
752
+ }
753
+ }
728
754
 
729
755
  function saveState() {
730
756
  if (currentSource) {
731
- currentSource.src = Uint8Array.prototype.slice.call(currentSource.src, currentSource.position, currentSource.srcEnd);
757
+ currentSource.bytes = Uint8Array.prototype.slice.call(currentSource.bytes, currentSource.position, currentSource.bytesEnd);
732
758
  currentSource.position = 0;
733
- currentSource.srcEnd = currentSource.src.length;
759
+ currentSource.bytesEnd = currentSource.bytes.length;
734
760
  }
735
761
  }
736
762
  function prepareStructures(structures, packr) {
package/unpack.d.ts CHANGED
@@ -1,53 +1,2 @@
1
- export enum FLOAT32_OPTIONS {
2
- NEVER = 0,
3
- ALWAYS = 1,
4
- DECIMAL_ROUND = 3,
5
- DECIMAL_FIT = 4
6
- }
7
-
8
- export interface Options {
9
- useFloat32?: FLOAT32_OPTIONS
10
- useRecords?: boolean
11
- structures?: {}[]
12
- moreTypes?: boolean
13
- structuredClone?: boolean
14
- mapsAsObjects?: boolean
15
- variableMapSize?: boolean
16
- copyBuffers?: boolean
17
- bundleStrings?: boolean
18
- useTimestamp32?: boolean
19
- largeBigIntToFloat?: boolean
20
- encodeUndefinedAsNil?: boolean
21
- maxSharedStructures?: number
22
- maxOwnStructures?: number
23
- int64AsNumber?: boolean
24
- shouldShareStructure?: (keys: string[]) => boolean
25
- getStructures?(): {}[]
26
- saveStructures?(structures: {}[]): boolean | void
27
- onInvalidDate?: () => any
28
- }
29
- interface Extension {
30
- Class: Function
31
- type: number
32
- pack?(value: any): Buffer | Uint8Array
33
- unpack?(messagePack: Buffer | Uint8Array): any
34
- read?(datum: any): any
35
- write?(instance: any): any
36
- }
37
- export class Unpackr {
38
- constructor(options?: Options)
39
- unpack(messagePack: Buffer | Uint8Array): any
40
- decode(messagePack: Buffer | Uint8Array): any
41
- unpackMultiple(messagePack: Buffer | Uint8Array): any[]
42
- unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
43
- }
44
- export class Decoder extends Unpackr {}
45
- export function unpack(messagePack: Buffer | Uint8Array): any
46
- export function unpackMultiple(messagePack: Buffer | Uint8Array): any[]
47
- export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach: (value: any) => any): void
48
- export function decode(messagePack: Buffer | Uint8Array): any
49
- export function addExtension(extension: Extension): void
50
- export function clearSource(): void
51
- export function roundFloat32(float32Number: number): number
52
- export const C1: {}
53
- export let isNativeAccelerationEnabled: boolean
1
+ export { Unpackr, Decoder, unpack, unpackMultiple, decode,
2
+ addExtension, FLOAT32_OPTIONS, Options, Extension, clearSource, roundFloat32 } from '.'
package/unpack.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict"
2
1
  var decoder
3
2
  try {
4
3
  decoder = new TextDecoder()
@@ -183,6 +182,7 @@ export function checkedRead(options) {
183
182
  let result
184
183
  if (currentUnpackr.randomAccessStructure && src[position] < 0x40 && src[position] >= 0x20 && readStruct) {
185
184
  result = readStruct(src, position, srcEnd, currentUnpackr)
185
+ src = null // dispose of this so that recursive unpack calls don't save state
186
186
  if (!(options && options.lazy) && result)
187
187
  result = result.toJSON()
188
188
  position = srcEnd
@@ -193,7 +193,7 @@ export function checkedRead(options) {
193
193
 
194
194
  if (position == srcEnd) {
195
195
  // finished reading this source, cleanup references
196
- if (currentStructures.restoreStructures)
196
+ if (currentStructures?.restoreStructures)
197
197
  restoreStructures()
198
198
  currentStructures = null
199
199
  src = null
@@ -248,7 +248,10 @@ export function read() {
248
248
  if (currentUnpackr.mapsAsObjects) {
249
249
  let object = {}
250
250
  for (let i = 0; i < token; i++) {
251
- object[readKey()] = read()
251
+ let key = readKey()
252
+ if (key === '__proto__')
253
+ key = '__proto_'
254
+ object[key] = read()
252
255
  }
253
256
  return object
254
257
  } else {
@@ -477,7 +480,7 @@ function createStructureReader(structure, firstId) {
477
480
  // This initial function is quick to instantiate, but runs slower. After several iterations pay the cost to build the faster function
478
481
  if (readObject.count++ > inlineObjectReadThreshold) {
479
482
  let readObject = structure.read = (new Function('r', 'return function(){return ' + (currentUnpackr.freezeData ? 'Object.freeze' : '') +
480
- '({' + structure.map(key => validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
483
+ '({' + structure.map(key => key === '__proto__' ? '__proto_:r()' : validName.test(key) ? key + ':r()' : ('[' + JSON.stringify(key) + ']:r()')).join(',') + '})}'))(read)
481
484
  if (structure.highByte === 0)
482
485
  structure.read = createSecondByteReader(firstId, structure.read)
483
486
  return readObject() // second byte is already read, if there is one so immediately read object
@@ -485,6 +488,8 @@ function createStructureReader(structure, firstId) {
485
488
  let object = {}
486
489
  for (let i = 0, l = structure.length; i < l; i++) {
487
490
  let key = structure[i]
491
+ if (key === '__proto__')
492
+ key = '__proto_'
488
493
  object[key] = read()
489
494
  }
490
495
  if (currentUnpackr.freezeData)
@@ -645,7 +650,10 @@ function readMap(length) {
645
650
  if (currentUnpackr.mapsAsObjects) {
646
651
  let object = {}
647
652
  for (let i = 0; i < length; i++) {
648
- object[readKey()] = read()
653
+ let key = readKey()
654
+ if (key === '__proto__')
655
+ key = '__proto_';
656
+ object[key] = read()
649
657
  }
650
658
  return object
651
659
  } else {
@@ -930,7 +938,16 @@ function readKey() {
930
938
 
931
939
  // the registration of the record definition extension (as "r")
932
940
  const recordDefinition = (id, highByte) => {
933
- var structure = read()
941
+ let structure
942
+ if (currentUnpackr.freezeData) {
943
+ currentUnpackr.freezeData = false;
944
+ try {
945
+ structure = read()
946
+ } finally {
947
+ currentUnpackr.freezeData = true;
948
+ }
949
+ } else
950
+ structure = read()
934
951
  let firstByte = id
935
952
  if (highByte !== undefined) {
936
953
  id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id)