@hocuspocus/common 2.0.1 → 2.0.3

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.
@@ -31,20 +31,47 @@ const fromCamelCaseRegex = /([A-Z])/g;
31
31
  */
32
32
  const fromCamelCase = (s, separator) => trimLeft(s.replace(fromCamelCaseRegex, match => `${separator}${toLowerCase(match)}`));
33
33
 
34
- /* istanbul ignore next */
35
- /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
34
+ /**
35
+ * @param {string} str
36
+ * @return {Uint8Array}
37
+ */
38
+ const _encodeUtf8Polyfill = str => {
39
+ const encodedString = unescape(encodeURIComponent(str));
40
+ const len = encodedString.length;
41
+ const buf = new Uint8Array(len);
42
+ for (let i = 0; i < len; i++) {
43
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
44
+ }
45
+ return buf
46
+ };
36
47
 
37
- /* istanbul ignore next */
48
+ /* c8 ignore next */
49
+ const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
50
+
51
+ /**
52
+ * @param {string} str
53
+ * @return {Uint8Array}
54
+ */
55
+ const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
56
+
57
+ /**
58
+ * @param {string} str
59
+ * @return {Uint8Array}
60
+ */
61
+ /* c8 ignore next */
62
+ const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
63
+
64
+ /* c8 ignore next */
38
65
  let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
39
66
 
40
- /* istanbul ignore next */
67
+ /* c8 ignore start */
41
68
  if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
42
69
  // Safari doesn't handle BOM correctly.
43
70
  // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
44
71
  // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
45
72
  // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
46
73
  // Another issue is that from then on no BOM chars are recognized anymore
47
- /* istanbul ignore next */
74
+ /* c8 ignore next */
48
75
  utf8TextDecoder = null;
49
76
  }
50
77
 
@@ -62,7 +89,7 @@ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
62
89
  *
63
90
  * @function
64
91
  */
65
- const create = () => new Map();
92
+ const create$1 = () => new Map();
66
93
 
67
94
  /**
68
95
  * Often used conditions.
@@ -75,10 +102,10 @@ const create = () => new Map();
75
102
  * @param {T|null|undefined} v
76
103
  * @return {T|null}
77
104
  */
78
- /* istanbul ignore next */
105
+ /* c8 ignore next */
79
106
  const undefinedToNull = v => v === undefined ? null : v;
80
107
 
81
- /* global localStorage, addEventListener */
108
+ /* eslint-env browser */
82
109
 
83
110
  /**
84
111
  * Isomorphic variable storage.
@@ -88,7 +115,7 @@ const undefinedToNull = v => v === undefined ? null : v;
88
115
  * @module storage
89
116
  */
90
117
 
91
- /* istanbul ignore next */
118
+ /* c8 ignore start */
92
119
  class VarStoragePolyfill {
93
120
  constructor () {
94
121
  this.map = new Map();
@@ -109,54 +136,74 @@ class VarStoragePolyfill {
109
136
  return this.map.get(key)
110
137
  }
111
138
  }
139
+ /* c8 ignore stop */
112
140
 
113
- /* istanbul ignore next */
114
141
  /**
115
142
  * @type {any}
116
143
  */
117
144
  let _localStorage = new VarStoragePolyfill();
118
145
  let usePolyfill = true;
119
146
 
147
+ /* c8 ignore start */
120
148
  try {
121
149
  // if the same-origin rule is violated, accessing localStorage might thrown an error
122
- /* istanbul ignore next */
123
150
  if (typeof localStorage !== 'undefined') {
124
151
  _localStorage = localStorage;
125
152
  usePolyfill = false;
126
153
  }
127
154
  } catch (e) { }
155
+ /* c8 ignore stop */
128
156
 
129
- /* istanbul ignore next */
130
157
  /**
131
158
  * This is basically localStorage in browser, or a polyfill in nodejs
132
159
  */
160
+ /* c8 ignore next */
133
161
  const varStorage = _localStorage;
134
162
 
163
+ /**
164
+ * Common functions and function call helpers.
165
+ *
166
+ * @module function
167
+ */
168
+
169
+ /**
170
+ * @template V
171
+ * @template {V} OPTS
172
+ *
173
+ * @param {V} value
174
+ * @param {Array<OPTS>} options
175
+ */
176
+ // @ts-ignore
177
+ const isOneOf = (value, options) => options.includes(value);
178
+ /* c8 ignore stop */
179
+
135
180
  /**
136
181
  * Isomorphic module to work access the environment (query params, env variables).
137
182
  *
138
183
  * @module map
139
184
  */
140
185
 
141
- /* istanbul ignore next */
186
+ /* c8 ignore next */
142
187
  // @ts-ignore
143
- const isNode = typeof process !== 'undefined' && process.release && /node|io\.js/.test(process.release.name);
144
- /* istanbul ignore next */
145
- typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
188
+ const isNode = typeof process !== 'undefined' && process.release &&
189
+ /node|io\.js/.test(process.release.name);
190
+ /* c8 ignore next 3 */
191
+ typeof navigator !== 'undefined'
192
+ ? /Mac/.test(navigator.platform)
193
+ : false;
146
194
 
147
195
  /**
148
196
  * @type {Map<string,string>}
149
197
  */
150
198
  let params;
151
199
 
152
- /* istanbul ignore next */
200
+ /* c8 ignore start */
153
201
  const computeParams = () => {
154
202
  if (params === undefined) {
155
203
  if (isNode) {
156
- params = create();
204
+ params = create$1();
157
205
  const pargs = process.argv;
158
206
  let currParamName = null;
159
- /* istanbul ignore next */
160
207
  for (let i = 0; i < pargs.length; i++) {
161
208
  const parg = pargs[i];
162
209
  if (parg[0] === '-') {
@@ -174,11 +221,10 @@ const computeParams = () => {
174
221
  if (currParamName !== null) {
175
222
  params.set(currParamName, '');
176
223
  }
177
- // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
224
+ // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
178
225
  } else if (typeof location === 'object') {
179
- params = create()
180
- // eslint-disable-next-line no-undef
181
- ;(location.search || '?').slice(1).split('&').forEach(kv => {
226
+ params = create$1(); // eslint-disable-next-line no-undef
227
+ (location.search || '?').slice(1).split('&').forEach((kv) => {
182
228
  if (kv.length !== 0) {
183
229
  const [key, value] = kv.split('=');
184
230
  params.set(`--${fromCamelCase(key, '-')}`, value);
@@ -186,41 +232,103 @@ const computeParams = () => {
186
232
  }
187
233
  });
188
234
  } else {
189
- params = create();
235
+ params = create$1();
190
236
  }
191
237
  }
192
238
  return params
193
239
  };
240
+ /* c8 ignore stop */
194
241
 
195
242
  /**
196
243
  * @param {string} name
197
244
  * @return {boolean}
198
245
  */
199
- /* istanbul ignore next */
200
- const hasParam = name => computeParams().has(name);
201
- // export const getArgs = name => computeParams() && args
246
+ /* c8 ignore next */
247
+ const hasParam = (name) => computeParams().has(name);
202
248
 
203
249
  /**
204
250
  * @param {string} name
205
251
  * @return {string|null}
206
252
  */
207
- /* istanbul ignore next */
208
- const getVariable = name => isNode ? undefinedToNull(process.env[name.toUpperCase()]) : undefinedToNull(varStorage.getItem(name));
253
+ /* c8 ignore next 4 */
254
+ const getVariable = (name) =>
255
+ isNode
256
+ ? undefinedToNull(process.env[name.toUpperCase()])
257
+ : undefinedToNull(varStorage.getItem(name));
209
258
 
210
259
  /**
211
260
  * @param {string} name
212
261
  * @return {boolean}
213
262
  */
214
- /* istanbul ignore next */
215
- const hasConf = name => hasParam('--' + name) || getVariable(name) !== null;
263
+ /* c8 ignore next 2 */
264
+ const hasConf = (name) =>
265
+ hasParam('--' + name) || getVariable(name) !== null;
216
266
 
217
- /* istanbul ignore next */
267
+ /* c8 ignore next */
218
268
  hasConf('production');
219
269
 
270
+ /* c8 ignore next 2 */
271
+ const forceColor = isNode &&
272
+ isOneOf(process.env.FORCE_COLOR, ['true', '1', '2']);
273
+
274
+ /* c8 ignore start */
275
+ !hasParam('no-colors') &&
276
+ (!isNode || process.stdout.isTTY || forceColor) && (
277
+ !isNode || hasParam('color') || forceColor ||
278
+ getVariable('COLORTERM') !== null ||
279
+ (getVariable('TERM') || '').includes('color')
280
+ );
281
+ /* c8 ignore stop */
282
+
220
283
  /* eslint-env browser */
221
284
  const BIT8 = 128;
222
285
  const BITS7 = 127;
223
286
 
287
+ /**
288
+ * Common Math expressions.
289
+ *
290
+ * @module math
291
+ */
292
+
293
+ const floor = Math.floor;
294
+
295
+ /**
296
+ * @function
297
+ * @param {number} a
298
+ * @param {number} b
299
+ * @return {number} The smaller element of a and b
300
+ */
301
+ const min = (a, b) => a < b ? a : b;
302
+
303
+ /**
304
+ * @function
305
+ * @param {number} a
306
+ * @param {number} b
307
+ * @return {number} The bigger element of a and b
308
+ */
309
+ const max = (a, b) => a > b ? a : b;
310
+
311
+ /**
312
+ * Utility helpers for working with numbers.
313
+ *
314
+ * @module number
315
+ */
316
+
317
+ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
318
+
319
+ /**
320
+ * Error helpers.
321
+ *
322
+ * @module error
323
+ */
324
+
325
+ /**
326
+ * @param {string} s
327
+ * @return {Error}
328
+ */
329
+ /* c8 ignore next */
330
+ const create = s => new Error(s);
331
+
224
332
  /**
225
333
  * Efficient schema-less binary decoding with support for variable length encoding.
226
334
  *
@@ -232,7 +340,7 @@ const BITS7 = 127;
232
340
  *
233
341
  * ```js
234
342
  * // encoding step
235
- * const encoder = new encoding.createEncoder()
343
+ * const encoder = encoding.createEncoder()
236
344
  * encoding.writeVarUint(encoder, 256)
237
345
  * encoding.writeVarString(encoder, 'Hello world!')
238
346
  * const buf = encoding.toUint8Array(encoder)
@@ -240,7 +348,7 @@ const BITS7 = 127;
240
348
  *
241
349
  * ```js
242
350
  * // decoding step
243
- * const decoder = new decoding.createDecoder(buf)
351
+ * const decoder = decoding.createDecoder(buf)
244
352
  * decoding.readVarUint(decoder) // => 256
245
353
  * decoding.readVarString(decoder) // => 'Hello world!'
246
354
  * decoding.hasContent(decoder) // => false - all data is read
@@ -249,6 +357,38 @@ const BITS7 = 127;
249
357
  * @module decoding
250
358
  */
251
359
 
360
+ const errorUnexpectedEndOfArray = create('Unexpected end of array');
361
+ const errorIntegerOutOfRange = create('Integer out of Range');
362
+
363
+ /**
364
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
365
+ *
366
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
367
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
368
+ *
369
+ * @function
370
+ * @param {Decoder} decoder The decoder instance
371
+ * @param {number} len The length of bytes to read
372
+ * @return {Uint8Array}
373
+ */
374
+ const readUint8Array = (decoder, len) => {
375
+ const view = createUint8ArrayViewFromArrayBuffer(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
376
+ decoder.pos += len;
377
+ return view
378
+ };
379
+
380
+ /**
381
+ * Read variable length Uint8Array.
382
+ *
383
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
384
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
385
+ *
386
+ * @function
387
+ * @param {Decoder} decoder
388
+ * @return {Uint8Array}
389
+ */
390
+ const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder));
391
+
252
392
  /**
253
393
  * Read one byte as unsigned integer.
254
394
  * @function
@@ -269,24 +409,28 @@ const readUint8 = decoder => decoder.arr[decoder.pos++];
269
409
  */
270
410
  const readVarUint = decoder => {
271
411
  let num = 0;
272
- let len = 0;
273
- while (true) {
412
+ let mult = 1;
413
+ const len = decoder.arr.length;
414
+ while (decoder.pos < len) {
274
415
  const r = decoder.arr[decoder.pos++];
275
- num = num | ((r & BITS7) << len);
276
- len += 7;
416
+ // num = num | ((r & binary.BITS7) << len)
417
+ num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
418
+ mult *= 128; // next iteration, shift 7 "more" to the left
277
419
  if (r < BIT8) {
278
- return num >>> 0 // return unsigned number!
420
+ return num
279
421
  }
280
- /* istanbul ignore if */
281
- if (len > 35) {
282
- throw new Error('Integer out of range!')
422
+ /* c8 ignore start */
423
+ if (num > MAX_SAFE_INTEGER) {
424
+ throw errorIntegerOutOfRange
283
425
  }
426
+ /* c8 ignore stop */
284
427
  }
428
+ throw errorUnexpectedEndOfArray
285
429
  };
286
430
 
287
431
  /**
288
- * Read string of variable length
289
- * * varUint is used to store the length of the string
432
+ * We don't test this function anymore as we use native decoding/encoding by default now.
433
+ * Better not modify this anymore..
290
434
  *
291
435
  * Transforming utf8 to a string is pretty expensive. The code performs 10x better
292
436
  * when String.fromCodePoint is fed with all characters as arguments.
@@ -297,7 +441,8 @@ const readVarUint = decoder => {
297
441
  * @param {Decoder} decoder
298
442
  * @return {String} The read String.
299
443
  */
300
- const readVarString = decoder => {
444
+ /* c8 ignore start */
445
+ const _readVarStringPolyfill = decoder => {
301
446
  let remainingLen = readVarUint(decoder);
302
447
  if (remainingLen === 0) {
303
448
  return ''
@@ -321,6 +466,42 @@ const readVarString = decoder => {
321
466
  return decodeURIComponent(escape(encodedString))
322
467
  }
323
468
  };
469
+ /* c8 ignore stop */
470
+
471
+ /**
472
+ * @function
473
+ * @param {Decoder} decoder
474
+ * @return {String} The read String
475
+ */
476
+ const _readVarStringNative = decoder =>
477
+ /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
478
+
479
+ /**
480
+ * Read string of variable length
481
+ * * varUint is used to store the length of the string
482
+ *
483
+ * @function
484
+ * @param {Decoder} decoder
485
+ * @return {String} The read String
486
+ *
487
+ */
488
+ /* c8 ignore next */
489
+ const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
490
+
491
+ /**
492
+ * Utility functions to work with buffers (Uint8Array).
493
+ *
494
+ * @module buffer
495
+ */
496
+
497
+ /**
498
+ * Create Uint8Array with initial content from buffer
499
+ *
500
+ * @param {ArrayBuffer} buffer
501
+ * @param {number} byteOffset
502
+ * @param {number} length
503
+ */
504
+ const createUint8ArrayViewFromArrayBuffer = (buffer, byteOffset, length) => new Uint8Array(buffer, byteOffset, length);
324
505
 
325
506
  /**
326
507
  * Efficient schema-less binary encoding with support for variable length encoding.
@@ -333,7 +514,7 @@ const readVarString = decoder => {
333
514
  *
334
515
  * ```js
335
516
  * // encoding step
336
- * const encoder = new encoding.createEncoder()
517
+ * const encoder = encoding.createEncoder()
337
518
  * encoding.writeVarUint(encoder, 256)
338
519
  * encoding.writeVarString(encoder, 'Hello world!')
339
520
  * const buf = encoding.toUint8Array(encoder)
@@ -341,7 +522,7 @@ const readVarString = decoder => {
341
522
  *
342
523
  * ```js
343
524
  * // decoding step
344
- * const decoder = new decoding.createDecoder(buf)
525
+ * const decoder = decoding.createDecoder(buf)
345
526
  * decoding.readVarUint(decoder) // => 256
346
527
  * decoding.readVarString(decoder) // => 'Hello world!'
347
528
  * decoding.hasContent(decoder) // => false - all data is read
@@ -368,9 +549,7 @@ const write = (encoder, num) => {
368
549
  };
369
550
 
370
551
  /**
371
- * Write a variable length unsigned integer.
372
- *
373
- * Encodes integers in the range from [0, 4294967295] / [0, 0xffffffff]. (max 32 bit unsigned integer)
552
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
374
553
  *
375
554
  * @function
376
555
  * @param {Encoder} encoder
@@ -379,11 +558,38 @@ const write = (encoder, num) => {
379
558
  const writeVarUint = (encoder, num) => {
380
559
  while (num > BITS7) {
381
560
  write(encoder, BIT8 | (BITS7 & num));
382
- num >>>= 7;
561
+ num = floor(num / 128); // shift >>> 7
383
562
  }
384
563
  write(encoder, BITS7 & num);
385
564
  };
386
565
 
566
+ /**
567
+ * A cache to store strings temporarily
568
+ */
569
+ const _strBuffer = new Uint8Array(30000);
570
+ const _maxStrBSize = _strBuffer.length / 3;
571
+
572
+ /**
573
+ * Write a variable length string.
574
+ *
575
+ * @function
576
+ * @param {Encoder} encoder
577
+ * @param {String} str The string that is to be encoded.
578
+ */
579
+ const _writeVarStringNative = (encoder, str) => {
580
+ if (str.length < _maxStrBSize) {
581
+ // We can encode the string into the existing buffer
582
+ /* c8 ignore next */
583
+ const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
584
+ writeVarUint(encoder, written);
585
+ for (let i = 0; i < written; i++) {
586
+ write(encoder, _strBuffer[i]);
587
+ }
588
+ } else {
589
+ writeVarUint8Array(encoder, encodeUtf8(str));
590
+ }
591
+ };
592
+
387
593
  /**
388
594
  * Write a variable length string.
389
595
  *
@@ -391,7 +597,7 @@ const writeVarUint = (encoder, num) => {
391
597
  * @param {Encoder} encoder
392
598
  * @param {String} str The string that is to be encoded.
393
599
  */
394
- const writeVarString = (encoder, str) => {
600
+ const _writeVarStringPolyfill = (encoder, str) => {
395
601
  const encodedString = unescape(encodeURIComponent(str));
396
602
  const len = encodedString.length;
397
603
  writeVarUint(encoder, len);
@@ -400,6 +606,54 @@ const writeVarString = (encoder, str) => {
400
606
  }
401
607
  };
402
608
 
609
+ /**
610
+ * Write a variable length string.
611
+ *
612
+ * @function
613
+ * @param {Encoder} encoder
614
+ * @param {String} str The string that is to be encoded.
615
+ */
616
+ /* c8 ignore next */
617
+ const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
618
+
619
+ /**
620
+ * Append fixed-length Uint8Array to the encoder.
621
+ *
622
+ * @function
623
+ * @param {Encoder} encoder
624
+ * @param {Uint8Array} uint8Array
625
+ */
626
+ const writeUint8Array = (encoder, uint8Array) => {
627
+ const bufferLen = encoder.cbuf.length;
628
+ const cpos = encoder.cpos;
629
+ const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
630
+ const rightCopyLen = uint8Array.length - leftCopyLen;
631
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
632
+ encoder.cpos += leftCopyLen;
633
+ if (rightCopyLen > 0) {
634
+ // Still something to write, write right half..
635
+ // Append new buffer
636
+ encoder.bufs.push(encoder.cbuf);
637
+ // must have at least size of remaining buffer
638
+ encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
639
+ // copy array
640
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
641
+ encoder.cpos = rightCopyLen;
642
+ }
643
+ };
644
+
645
+ /**
646
+ * Append an Uint8Array to Encoder.
647
+ *
648
+ * @function
649
+ * @param {Encoder} encoder
650
+ * @param {Uint8Array} uint8Array
651
+ */
652
+ const writeVarUint8Array = (encoder, uint8Array) => {
653
+ writeVarUint(encoder, uint8Array.byteLength);
654
+ writeUint8Array(encoder, uint8Array);
655
+ };
656
+
403
657
  var AuthMessageType;
404
658
  (function (AuthMessageType) {
405
659
  AuthMessageType[AuthMessageType["Token"] = 0] = "Token";