msgpackr 1.7.1 → 1.8.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
@@ -20,7 +20,9 @@ export interface Options {
20
20
  encodeUndefinedAsNil?: boolean
21
21
  maxSharedStructures?: number
22
22
  maxOwnStructures?: number
23
+ /** @deprecated use int64AsType: 'number' */
23
24
  int64AsNumber?: boolean
25
+ int64AsType?: 'bigint' | 'number' | 'string'
24
26
  shouldShareStructure?: (keys: string[]) => boolean
25
27
  getStructures?(): {}[]
26
28
  saveStructures?(structures: {}[]): boolean | void
package/pack.js CHANGED
@@ -66,14 +66,14 @@ export class Packr extends Unpackr {
66
66
  this.pack = this.encode = function(value, encodeOptions) {
67
67
  if (!target) {
68
68
  target = new ByteArrayAllocate(8192)
69
- targetView = target.dataView = new DataView(target.buffer, 0, 8192)
69
+ targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, 8192))
70
70
  position = 0
71
71
  }
72
72
  safeEnd = target.length - 10
73
73
  if (safeEnd - position < 0x800) {
74
74
  // don't start too close to the end,
75
75
  target = new ByteArrayAllocate(target.length)
76
- targetView = target.dataView = new DataView(target.buffer, 0, target.length)
76
+ targetView = target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))
77
77
  safeEnd = target.length - 10
78
78
  position = 0
79
79
  } else
@@ -125,20 +125,44 @@ export class Packr extends Unpackr {
125
125
  writeStruct(value);
126
126
  else
127
127
  pack(value)
128
+ let lastBundle = bundledStrings;
129
+ if (bundledStrings)
130
+ writeBundles(start, pack, 0)
128
131
  if (referenceMap && referenceMap.idsToInsert) {
129
- let incrementPosition = referenceMap.idsToInsert.length * 6;
130
- if (bundledStrings)
131
- writeBundles(start, pack, incrementPosition)
132
- position += incrementPosition
132
+ let idsToInsert = referenceMap.idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1);
133
+ let i = idsToInsert.length;
134
+ let incrementPosition = -1;
135
+ while (lastBundle && i > 0) {
136
+ let insertionPoint = idsToInsert[--i].offset + start;
137
+ if (insertionPoint < (lastBundle.stringsPosition + start) && incrementPosition === -1)
138
+ incrementPosition = 0;
139
+ if (insertionPoint > (lastBundle.position + start)) {
140
+ if (incrementPosition >= 0)
141
+ incrementPosition += 6;
142
+ } else {
143
+ if (incrementPosition >= 0) {
144
+ // update the bundle reference now
145
+ targetView.setUint32(lastBundle.position + start,
146
+ targetView.getUint32(lastBundle.position + start) + incrementPosition)
147
+ incrementPosition = -1; // reset
148
+ }
149
+ lastBundle = lastBundle.previous;
150
+ i++;
151
+ }
152
+ }
153
+ if (incrementPosition >= 0 && lastBundle) {
154
+ // update the bundle reference now
155
+ targetView.setUint32(lastBundle.position + start,
156
+ targetView.getUint32(lastBundle.position + start) + incrementPosition)
157
+ }
158
+ position += idsToInsert.length * 6;
133
159
  if (position > safeEnd)
134
160
  makeRoom(position)
135
161
  packr.offset = position
136
- let serialized = insertIds(target.subarray(start, position), referenceMap.idsToInsert)
162
+ let serialized = insertIds(target.subarray(start, position), idsToInsert)
137
163
  referenceMap = null
138
164
  return serialized
139
165
  }
140
- if (bundledStrings)
141
- writeBundles(start, pack, 0)
142
166
  packr.offset = position // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
143
167
  if (encodeOptions & REUSE_BUFFER_MODE) {
144
168
  target.start = start
@@ -196,13 +220,15 @@ export class Packr extends Unpackr {
196
220
  let maxBytes = (bundledStrings[0] ? bundledStrings[0].length * 3 + bundledStrings[1].length : 0) + 10
197
221
  if (position + maxBytes > safeEnd)
198
222
  target = makeRoom(position + maxBytes)
199
- if (bundledStrings.position) { // here we use the 0x62 extension to write the last bundle and reserve sapce for the reference pointer to the next/current bundle
223
+ let lastBundle
224
+ if (bundledStrings.position) { // here we use the 0x62 extension to write the last bundle and reserve space for the reference pointer to the next/current bundle
225
+ lastBundle = bundledStrings
200
226
  target[position] = 0xc8 // ext 16
201
227
  position += 3 // reserve for the writing bundle size
202
228
  target[position++] = 0x62 // 'b'
203
229
  extStart = position - start
204
230
  position += 4 // reserve for writing bundle reference
205
- writeBundles(start, pack) // write the last bundles
231
+ writeBundles(start, pack, 0) // write the last bundles
206
232
  targetView.setUint16(extStart + start - 3, position - start - extStart)
207
233
  } 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)
208
234
  target[position++] = 0xd6 // fixext 4
@@ -211,6 +237,7 @@ export class Packr extends Unpackr {
211
237
  position += 4 // reserve for writing bundle reference
212
238
  }
213
239
  bundledStrings = ['', ''] // create new ones
240
+ bundledStrings.previous = lastBundle;
214
241
  bundledStrings.size = 0
215
242
  bundledStrings.position = extStart
216
243
  }
@@ -361,7 +388,7 @@ export class Packr extends Unpackr {
361
388
  let constructor = value.constructor
362
389
  if (constructor === Object) {
363
390
  writeObject(value, true)
364
- } else if (constructor === Array) {
391
+ } else if (constructor === Array || Array.isArray(value)) {
365
392
  length = value.length
366
393
  if (length < 0x10) {
367
394
  target[position++] = 0x90 | length
@@ -600,7 +627,7 @@ export class Packr extends Unpackr {
600
627
  } else // faster handling for smaller buffers
601
628
  newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12
602
629
  let newBuffer = new ByteArrayAllocate(newSize)
603
- targetView = newBuffer.dataView = new DataView(newBuffer.buffer, 0, newSize)
630
+ targetView = newBuffer.dataView || (newBuffer.dataView = new DataView(newBuffer.buffer, 0, newSize))
604
631
  end = Math.min(end, target.length)
605
632
  if (target.copy)
606
633
  target.copy(newBuffer, 0, start, end)
@@ -906,7 +933,6 @@ function insertIds(serialized, idsToInsert) {
906
933
  let nextId
907
934
  let distanceToMove = idsToInsert.length * 6
908
935
  let lastEnd = serialized.length - distanceToMove
909
- idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1)
910
936
  while (nextId = idsToInsert.pop()) {
911
937
  let offset = nextId.offset
912
938
  let id = nextId.id
@@ -927,6 +953,7 @@ function insertIds(serialized, idsToInsert) {
927
953
  function writeBundles(start, pack, incrementPosition) {
928
954
  if (bundledStrings.length > 0) {
929
955
  targetView.setUint32(bundledStrings.position + start, position + incrementPosition - bundledStrings.position - start)
956
+ bundledStrings.stringsPosition = position - start;
930
957
  let writeStrings = bundledStrings
931
958
  bundledStrings = null
932
959
  pack(writeStrings[0])
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "msgpackr",
3
3
  "author": "Kris Zyp",
4
- "version": "1.7.1",
4
+ "version": "1.8.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",
@@ -72,17 +72,18 @@
72
72
  "/*.ts"
73
73
  ],
74
74
  "optionalDependencies": {
75
- "msgpackr-extract": "^2.1.2"
75
+ "msgpackr-extract": "^2.2.0"
76
76
  },
77
77
  "devDependencies": {
78
- "@rollup/plugin-json": "^4.1.0",
78
+ "@rollup/plugin-json": "^5.0.1",
79
+ "@rollup/plugin-replace": "^5.0.1",
79
80
  "@types/node": "latest",
80
81
  "async": "^3",
81
82
  "chai": "^4.3.4",
82
83
  "cpy-cli": "^4.1.0",
83
84
  "esm": "^3.2.25",
84
- "mocha": "^8.1.3",
85
- "rollup": "^1.20.3",
86
- "rollup-plugin-babel-minify": "^9.0.0"
85
+ "mocha": "^10.1.0",
86
+ "rollup": "^3.2.5",
87
+ "@rollup/plugin-terser": "^0.1.0"
87
88
  }
88
89
  }
package/rollup.config.js CHANGED
@@ -1,5 +1,6 @@
1
- import minify from "rollup-plugin-babel-minify";
2
- import json from "@rollup/plugin-json";
1
+ import terser from '@rollup/plugin-terser';
2
+ import json from "@rollup/plugin-json";
3
+ import replace from "@rollup/plugin-replace";
3
4
 
4
5
  export default [
5
6
  {
@@ -20,11 +21,24 @@ export default [
20
21
  name: "msgpackr",
21
22
  sourcemap: true
22
23
  }
23
- },
24
+ },
25
+ {
26
+ input: "index.js",
27
+ plugins: [
28
+ replace({ Function: 'BlockedFunction '})
29
+ ],
30
+ output: {
31
+ file: "dist/index-no-eval.js",
32
+ format: "umd",
33
+ name: "msgpackr",
34
+ sourcemap: true
35
+ },
36
+ },
24
37
  {
25
38
  input: "index.js",
26
- plugins: [minify({
27
- })],
39
+ plugins: [
40
+ terser({})
41
+ ],
28
42
  output: {
29
43
  file: "dist/index.min.js",
30
44
  format: "umd",
@@ -32,6 +46,19 @@ export default [
32
46
  sourcemap: true
33
47
  }
34
48
  },
49
+ {
50
+ input: "index.js",
51
+ plugins: [
52
+ replace({ Function: 'BlockedFunction '}),
53
+ terser({})
54
+ ],
55
+ output: {
56
+ file: "dist/index-no-eval.min.js",
57
+ format: "umd",
58
+ name: "msgpackr",
59
+ sourcemap: true
60
+ }
61
+ },
35
62
  {
36
63
  input: "tests/test.js",
37
64
  plugins: [json()],
package/struct.js CHANGED
@@ -161,9 +161,9 @@ function writeStruct(object, target, position, structures, makeRoom, pack, packr
161
161
  case 'string':
162
162
  let strLength = value.length;
163
163
  refOffset = refPosition - refsStartPosition;
164
- if ((strLength << 2) + position > safeEnd) {
164
+ if ((strLength << 2) + refPosition > safeEnd) {
165
165
  let lastStart = start;
166
- target = makeRoom(refPosition);
166
+ target = makeRoom((strLength << 2) + refPosition);
167
167
  targetView = target.dataView;
168
168
  position -= lastStart;
169
169
  refsStartPosition -= lastStart;
@@ -776,7 +776,7 @@ function prepareStructures(structures, packr) {
776
776
  let typed = existing.get('typed') || [];
777
777
  if (typed.length !== lastTypedStructuresLength)
778
778
  compatible = false;
779
- } else if (existing instanceof Array) {
779
+ } else if (existing instanceof Array || Array.isArray(existing)) {
780
780
  if (existing.length !== (packr.lastNamedStructuresLength || 0))
781
781
  compatible = false;
782
782
  }
package/unpack.js CHANGED
@@ -28,6 +28,8 @@ C1.name = 'MessagePack 0xC1'
28
28
  var sequentialMode = false
29
29
  var inlineObjectReadThreshold = 2
30
30
  var readStruct, onLoadedStructures, onSaveState
31
+ var BlockedFunction // we use search and replace to change the next call to BlockedFunction to avoid CSP issues for
32
+ // no-eval build
31
33
  try {
32
34
  new Function('')
33
35
  } catch(error) {
@@ -54,6 +56,9 @@ export class Unpackr {
54
56
  (options.structures = []).uninitialized = true // this is what we use to denote an uninitialized structures
55
57
  options.structures.sharedLength = 0
56
58
  }
59
+ if (options.int64AsNumber) {
60
+ options.int64AsType = 'number'
61
+ }
57
62
  }
58
63
  Object.assign(this, options)
59
64
  }
@@ -188,8 +193,10 @@ export function checkedRead(options) {
188
193
  position = srcEnd
189
194
  } else
190
195
  result = read()
191
- if (bundledStrings) // bundled strings to skip past
196
+ if (bundledStrings) { // bundled strings to skip past
192
197
  position = bundledStrings.postBundlePosition
198
+ bundledStrings = null
199
+ }
193
200
 
194
201
  if (position == srcEnd) {
195
202
  // finished reading this source, cleanup references
@@ -354,9 +361,11 @@ export function read() {
354
361
  position += 4
355
362
  return value
356
363
  case 0xcf:
357
- if (currentUnpackr.int64AsNumber) {
364
+ if (currentUnpackr.int64AsType === 'number') {
358
365
  value = dataView.getUint32(position) * 0x100000000
359
366
  value += dataView.getUint32(position + 4)
367
+ } else if (currentUnpackr.int64AsType === 'string') {
368
+ value = dataView.getBigUint64(position).toString()
360
369
  } else
361
370
  value = dataView.getBigUint64(position)
362
371
  position += 8
@@ -374,9 +383,11 @@ export function read() {
374
383
  position += 4
375
384
  return value
376
385
  case 0xd3:
377
- if (currentUnpackr.int64AsNumber) {
386
+ if (currentUnpackr.int64AsType === 'number') {
378
387
  value = dataView.getInt32(position) * 0x100000000
379
388
  value += dataView.getUint32(position + 4)
389
+ } else if (currentUnpackr.int64AsType === 'string') {
390
+ value = dataView.getBigInt64(position).toString()
380
391
  } else
381
392
  value = dataView.getBigInt64(position)
382
393
  position += 8
@@ -884,7 +895,7 @@ function readKey() {
884
895
  return readFixedString(length)
885
896
  } else { // not cacheable, go back and do a standard read
886
897
  position--
887
- return read()
898
+ return read().toString()
888
899
  }
889
900
  let key = ((length << 5) ^ (length > 1 ? dataView.getUint16(position) : length > 0 ? src[position] : 0)) & 0xfff
890
901
  let entry = keyCache[key]
@@ -938,16 +949,7 @@ function readKey() {
938
949
 
939
950
  // the registration of the record definition extension (as "r")
940
951
  const recordDefinition = (id, highByte) => {
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()
952
+ let structure = read().map(property => property.toString()) // ensure that all keys are strings and that the array is mutable
951
953
  let firstByte = id
952
954
  if (highByte !== undefined) {
953
955
  id = id < 32 ? -((highByte << 5) + id) : ((highByte << 5) + id)