@hocuspocus/provider 2.0.1 → 2.0.2

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.
@@ -16,7 +16,7 @@ import { retry } from '@lifeomic/attempt';
16
16
  *
17
17
  * @function
18
18
  */
19
- const create$1 = () => new Map();
19
+ const create$2 = () => new Map();
20
20
 
21
21
  /**
22
22
  * Get map property. Create T if property is undefined and set T on map.
@@ -27,11 +27,12 @@ const create$1 = () => new Map();
27
27
  * ```
28
28
  *
29
29
  * @function
30
- * @template T,K
31
- * @param {Map<K, T>} map
30
+ * @template V,K
31
+ * @template {Map<K,V>} MAP
32
+ * @param {MAP} map
32
33
  * @param {K} key
33
- * @param {function():T} createT
34
- * @return {T}
34
+ * @param {function():V} createT
35
+ * @return {V}
35
36
  */
36
37
  const setIfUndefined = (map, key, createT) => {
37
38
  let set = map.get(key);
@@ -41,6 +42,14 @@ const setIfUndefined = (map, key, createT) => {
41
42
  return set
42
43
  };
43
44
 
45
+ /**
46
+ * Utility module to work with sets.
47
+ *
48
+ * @module set
49
+ */
50
+
51
+ const create$1 = () => new Set();
52
+
44
53
  /**
45
54
  * Utility module to work with strings.
46
55
  *
@@ -72,20 +81,47 @@ const fromCamelCaseRegex = /([A-Z])/g;
72
81
  */
73
82
  const fromCamelCase = (s, separator) => trimLeft(s.replace(fromCamelCaseRegex, match => `${separator}${toLowerCase(match)}`));
74
83
 
75
- /* istanbul ignore next */
76
- /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
84
+ /**
85
+ * @param {string} str
86
+ * @return {Uint8Array}
87
+ */
88
+ const _encodeUtf8Polyfill = str => {
89
+ const encodedString = unescape(encodeURIComponent(str));
90
+ const len = encodedString.length;
91
+ const buf = new Uint8Array(len);
92
+ for (let i = 0; i < len; i++) {
93
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
94
+ }
95
+ return buf
96
+ };
97
+
98
+ /* c8 ignore next */
99
+ const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
77
100
 
78
- /* istanbul ignore next */
101
+ /**
102
+ * @param {string} str
103
+ * @return {Uint8Array}
104
+ */
105
+ const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
106
+
107
+ /**
108
+ * @param {string} str
109
+ * @return {Uint8Array}
110
+ */
111
+ /* c8 ignore next */
112
+ const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
113
+
114
+ /* c8 ignore next */
79
115
  let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
80
116
 
81
- /* istanbul ignore next */
117
+ /* c8 ignore start */
82
118
  if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
83
119
  // Safari doesn't handle BOM correctly.
84
120
  // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
85
121
  // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
86
122
  // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
87
123
  // Another issue is that from then on no BOM chars are recognized anymore
88
- /* istanbul ignore next */
124
+ /* c8 ignore next */
89
125
  utf8TextDecoder = null;
90
126
  }
91
127
 
@@ -100,10 +136,10 @@ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
100
136
  * @param {T|null|undefined} v
101
137
  * @return {T|null}
102
138
  */
103
- /* istanbul ignore next */
139
+ /* c8 ignore next */
104
140
  const undefinedToNull = v => v === undefined ? null : v;
105
141
 
106
- /* global localStorage, addEventListener */
142
+ /* eslint-env browser */
107
143
 
108
144
  /**
109
145
  * Isomorphic variable storage.
@@ -113,7 +149,7 @@ const undefinedToNull = v => v === undefined ? null : v;
113
149
  * @module storage
114
150
  */
115
151
 
116
- /* istanbul ignore next */
152
+ /* c8 ignore start */
117
153
  class VarStoragePolyfill {
118
154
  constructor () {
119
155
  this.map = new Map();
@@ -134,65 +170,242 @@ class VarStoragePolyfill {
134
170
  return this.map.get(key)
135
171
  }
136
172
  }
173
+ /* c8 ignore stop */
137
174
 
138
- /* istanbul ignore next */
139
175
  /**
140
176
  * @type {any}
141
177
  */
142
178
  let _localStorage = new VarStoragePolyfill();
143
179
  let usePolyfill = true;
144
180
 
181
+ /* c8 ignore start */
145
182
  try {
146
183
  // if the same-origin rule is violated, accessing localStorage might thrown an error
147
- /* istanbul ignore next */
148
184
  if (typeof localStorage !== 'undefined') {
149
185
  _localStorage = localStorage;
150
186
  usePolyfill = false;
151
187
  }
152
188
  } catch (e) { }
189
+ /* c8 ignore stop */
153
190
 
154
- /* istanbul ignore next */
155
191
  /**
156
192
  * This is basically localStorage in browser, or a polyfill in nodejs
157
193
  */
194
+ /* c8 ignore next */
158
195
  const varStorage = _localStorage;
159
196
 
160
- /* istanbul ignore next */
161
197
  /**
162
198
  * A polyfill for `addEventListener('storage', event => {..})` that does nothing if the polyfill is being used.
163
199
  *
164
200
  * @param {function({ key: string, newValue: string, oldValue: string }): void} eventHandler
165
201
  * @function
166
202
  */
203
+ /* c8 ignore next */
167
204
  const onChange = eventHandler => usePolyfill || addEventListener('storage', /** @type {any} */ (eventHandler));
168
205
 
206
+ /**
207
+ * A polyfill for `removeEventListener('storage', event => {..})` that does nothing if the polyfill is being used.
208
+ *
209
+ * @param {function({ key: string, newValue: string, oldValue: string }): void} eventHandler
210
+ * @function
211
+ */
212
+ /* c8 ignore next */
213
+ const offChange = eventHandler => usePolyfill || removeEventListener('storage', /** @type {any} */ (eventHandler));
214
+
215
+ /**
216
+ * Utility module to work with Arrays.
217
+ *
218
+ * @module array
219
+ */
220
+
221
+ /**
222
+ * Transforms something array-like to an actual Array.
223
+ *
224
+ * @function
225
+ * @template T
226
+ * @param {ArrayLike<T>|Iterable<T>} arraylike
227
+ * @return {T}
228
+ */
229
+ const from = Array.from;
230
+
231
+ /**
232
+ * Utility functions for working with EcmaScript objects.
233
+ *
234
+ * @module object
235
+ */
236
+
237
+ /**
238
+ * @param {Object<string,any>} obj
239
+ */
240
+ const keys = Object.keys;
241
+
242
+ /**
243
+ * @todo implement mapToArray & map
244
+ *
245
+ * @template R
246
+ * @param {Object<string,any>} obj
247
+ * @param {function(any,string):R} f
248
+ * @return {Array<R>}
249
+ */
250
+ const map = (obj, f) => {
251
+ const results = [];
252
+ for (const key in obj) {
253
+ results.push(f(obj[key], key));
254
+ }
255
+ return results
256
+ };
257
+
258
+ /**
259
+ * @param {Object<string,any>} obj
260
+ * @return {number}
261
+ */
262
+ const length$1 = obj => keys(obj).length;
263
+
264
+ /**
265
+ * Calls `Object.prototype.hasOwnProperty`.
266
+ *
267
+ * @param {any} obj
268
+ * @param {string|symbol} key
269
+ * @return {boolean}
270
+ */
271
+ const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
272
+
273
+ /**
274
+ * Common functions and function call helpers.
275
+ *
276
+ * @module function
277
+ */
278
+
279
+ /**
280
+ * @template T
281
+ *
282
+ * @param {T} a
283
+ * @param {T} b
284
+ * @return {boolean}
285
+ */
286
+ const equalityStrict = (a, b) => a === b;
287
+
288
+ /* c8 ignore start */
289
+
290
+ /**
291
+ * @param {any} a
292
+ * @param {any} b
293
+ * @return {boolean}
294
+ */
295
+ const equalityDeep = (a, b) => {
296
+ if (a == null || b == null) {
297
+ return equalityStrict(a, b)
298
+ }
299
+ if (a.constructor !== b.constructor) {
300
+ return false
301
+ }
302
+ if (a === b) {
303
+ return true
304
+ }
305
+ switch (a.constructor) {
306
+ case ArrayBuffer:
307
+ a = new Uint8Array(a);
308
+ b = new Uint8Array(b);
309
+ // eslint-disable-next-line no-fallthrough
310
+ case Uint8Array: {
311
+ if (a.byteLength !== b.byteLength) {
312
+ return false
313
+ }
314
+ for (let i = 0; i < a.length; i++) {
315
+ if (a[i] !== b[i]) {
316
+ return false
317
+ }
318
+ }
319
+ break
320
+ }
321
+ case Set: {
322
+ if (a.size !== b.size) {
323
+ return false
324
+ }
325
+ for (const value of a) {
326
+ if (!b.has(value)) {
327
+ return false
328
+ }
329
+ }
330
+ break
331
+ }
332
+ case Map: {
333
+ if (a.size !== b.size) {
334
+ return false
335
+ }
336
+ for (const key of a.keys()) {
337
+ if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
338
+ return false
339
+ }
340
+ }
341
+ break
342
+ }
343
+ case Object:
344
+ if (length$1(a) !== length$1(b)) {
345
+ return false
346
+ }
347
+ for (const key in a) {
348
+ if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
349
+ return false
350
+ }
351
+ }
352
+ break
353
+ case Array:
354
+ if (a.length !== b.length) {
355
+ return false
356
+ }
357
+ for (let i = 0; i < a.length; i++) {
358
+ if (!equalityDeep(a[i], b[i])) {
359
+ return false
360
+ }
361
+ }
362
+ break
363
+ default:
364
+ return false
365
+ }
366
+ return true
367
+ };
368
+
369
+ /**
370
+ * @template V
371
+ * @template {V} OPTS
372
+ *
373
+ * @param {V} value
374
+ * @param {Array<OPTS>} options
375
+ */
376
+ // @ts-ignore
377
+ const isOneOf = (value, options) => options.includes(value);
378
+ /* c8 ignore stop */
379
+
169
380
  /**
170
381
  * Isomorphic module to work access the environment (query params, env variables).
171
382
  *
172
383
  * @module map
173
384
  */
174
385
 
175
- /* istanbul ignore next */
386
+ /* c8 ignore next */
176
387
  // @ts-ignore
177
- const isNode = typeof process !== 'undefined' && process.release && /node|io\.js/.test(process.release.name);
178
- /* istanbul ignore next */
179
- const isBrowser = typeof window !== 'undefined' && !isNode;
180
- /* istanbul ignore next */
181
- typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
388
+ const isNode = typeof process !== 'undefined' && process.release &&
389
+ /node|io\.js/.test(process.release.name);
390
+ /* c8 ignore next */
391
+ const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && !isNode;
392
+ /* c8 ignore next 3 */
393
+ typeof navigator !== 'undefined'
394
+ ? /Mac/.test(navigator.platform)
395
+ : false;
182
396
 
183
397
  /**
184
398
  * @type {Map<string,string>}
185
399
  */
186
400
  let params;
187
401
 
188
- /* istanbul ignore next */
402
+ /* c8 ignore start */
189
403
  const computeParams = () => {
190
404
  if (params === undefined) {
191
405
  if (isNode) {
192
- params = create$1();
406
+ params = create$2();
193
407
  const pargs = process.argv;
194
408
  let currParamName = null;
195
- /* istanbul ignore next */
196
409
  for (let i = 0; i < pargs.length; i++) {
197
410
  const parg = pargs[i];
198
411
  if (parg[0] === '-') {
@@ -210,11 +423,10 @@ const computeParams = () => {
210
423
  if (currParamName !== null) {
211
424
  params.set(currParamName, '');
212
425
  }
213
- // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
426
+ // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
214
427
  } else if (typeof location === 'object') {
215
- params = create$1()
216
- // eslint-disable-next-line no-undef
217
- ;(location.search || '?').slice(1).split('&').forEach(kv => {
428
+ params = create$2(); // eslint-disable-next-line no-undef
429
+ (location.search || '?').slice(1).split('&').forEach((kv) => {
218
430
  if (kv.length !== 0) {
219
431
  const [key, value] = kv.split('=');
220
432
  params.set(`--${fromCamelCase(key, '-')}`, value);
@@ -222,37 +434,54 @@ const computeParams = () => {
222
434
  }
223
435
  });
224
436
  } else {
225
- params = create$1();
437
+ params = create$2();
226
438
  }
227
439
  }
228
440
  return params
229
441
  };
442
+ /* c8 ignore stop */
230
443
 
231
444
  /**
232
445
  * @param {string} name
233
446
  * @return {boolean}
234
447
  */
235
- /* istanbul ignore next */
236
- const hasParam = name => computeParams().has(name);
237
- // export const getArgs = name => computeParams() && args
448
+ /* c8 ignore next */
449
+ const hasParam = (name) => computeParams().has(name);
238
450
 
239
451
  /**
240
452
  * @param {string} name
241
453
  * @return {string|null}
242
454
  */
243
- /* istanbul ignore next */
244
- const getVariable = name => isNode ? undefinedToNull(process.env[name.toUpperCase()]) : undefinedToNull(varStorage.getItem(name));
455
+ /* c8 ignore next 4 */
456
+ const getVariable = (name) =>
457
+ isNode
458
+ ? undefinedToNull(process.env[name.toUpperCase()])
459
+ : undefinedToNull(varStorage.getItem(name));
245
460
 
246
461
  /**
247
462
  * @param {string} name
248
463
  * @return {boolean}
249
464
  */
250
- /* istanbul ignore next */
251
- const hasConf = name => hasParam('--' + name) || getVariable(name) !== null;
465
+ /* c8 ignore next 2 */
466
+ const hasConf = (name) =>
467
+ hasParam('--' + name) || getVariable(name) !== null;
252
468
 
253
- /* istanbul ignore next */
469
+ /* c8 ignore next */
254
470
  hasConf('production');
255
471
 
472
+ /* c8 ignore next 2 */
473
+ const forceColor = isNode &&
474
+ isOneOf(process.env.FORCE_COLOR, ['true', '1', '2']);
475
+
476
+ /* c8 ignore start */
477
+ !hasParam('no-colors') &&
478
+ (!isNode || process.stdout.isTTY || forceColor) && (
479
+ !isNode || hasParam('color') || forceColor ||
480
+ getVariable('COLORTERM') !== null ||
481
+ (getVariable('TERM') || '').includes('color')
482
+ );
483
+ /* c8 ignore stop */
484
+
256
485
  /**
257
486
  * Common Math expressions.
258
487
  *
@@ -281,6 +510,14 @@ const max = (a, b) => a > b ? a : b;
281
510
  const BIT8 = 128;
282
511
  const BITS7 = 127;
283
512
 
513
+ /**
514
+ * Utility helpers for working with numbers.
515
+ *
516
+ * @module number
517
+ */
518
+
519
+ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
520
+
284
521
  /**
285
522
  * Efficient schema-less binary encoding with support for variable length encoding.
286
523
  *
@@ -292,7 +529,7 @@ const BITS7 = 127;
292
529
  *
293
530
  * ```js
294
531
  * // encoding step
295
- * const encoder = new encoding.createEncoder()
532
+ * const encoder = encoding.createEncoder()
296
533
  * encoding.writeVarUint(encoder, 256)
297
534
  * encoding.writeVarString(encoder, 'Hello world!')
298
535
  * const buf = encoding.toUint8Array(encoder)
@@ -300,7 +537,7 @@ const BITS7 = 127;
300
537
  *
301
538
  * ```js
302
539
  * // decoding step
303
- * const decoder = new decoding.createDecoder(buf)
540
+ * const decoder = decoding.createDecoder(buf)
304
541
  * decoding.readVarUint(decoder) // => 256
305
542
  * decoding.readVarString(decoder) // => 'Hello world!'
306
543
  * decoding.hasContent(decoder) // => false - all data is read
@@ -336,7 +573,7 @@ const createEncoder = () => new Encoder();
336
573
  * @param {Encoder} encoder
337
574
  * @return {number}
338
575
  */
339
- const length$1 = encoder => {
576
+ const length = encoder => {
340
577
  let len = encoder.cpos;
341
578
  for (let i = 0; i < encoder.bufs.length; i++) {
342
579
  len += encoder.bufs[i].length;
@@ -352,7 +589,7 @@ const length$1 = encoder => {
352
589
  * @return {Uint8Array} The created ArrayBuffer.
353
590
  */
354
591
  const toUint8Array = encoder => {
355
- const uint8arr = new Uint8Array(length$1(encoder));
592
+ const uint8arr = new Uint8Array(length(encoder));
356
593
  let curPos = 0;
357
594
  for (let i = 0; i < encoder.bufs.length; i++) {
358
595
  const d = encoder.bufs[i];
@@ -381,9 +618,7 @@ const write = (encoder, num) => {
381
618
  };
382
619
 
383
620
  /**
384
- * Write a variable length unsigned integer.
385
- *
386
- * Encodes integers in the range from [0, 4294967295] / [0, 0xffffffff]. (max 32 bit unsigned integer)
621
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
387
622
  *
388
623
  * @function
389
624
  * @param {Encoder} encoder
@@ -392,11 +627,17 @@ const write = (encoder, num) => {
392
627
  const writeVarUint = (encoder, num) => {
393
628
  while (num > BITS7) {
394
629
  write(encoder, BIT8 | (BITS7 & num));
395
- num >>>= 7;
630
+ num = floor(num / 128); // shift >>> 7
396
631
  }
397
632
  write(encoder, BITS7 & num);
398
633
  };
399
634
 
635
+ /**
636
+ * A cache to store strings temporarily
637
+ */
638
+ const _strBuffer = new Uint8Array(30000);
639
+ const _maxStrBSize = _strBuffer.length / 3;
640
+
400
641
  /**
401
642
  * Write a variable length string.
402
643
  *
@@ -404,7 +645,28 @@ const writeVarUint = (encoder, num) => {
404
645
  * @param {Encoder} encoder
405
646
  * @param {String} str The string that is to be encoded.
406
647
  */
407
- const writeVarString = (encoder, str) => {
648
+ const _writeVarStringNative = (encoder, str) => {
649
+ if (str.length < _maxStrBSize) {
650
+ // We can encode the string into the existing buffer
651
+ /* c8 ignore next */
652
+ const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
653
+ writeVarUint(encoder, written);
654
+ for (let i = 0; i < written; i++) {
655
+ write(encoder, _strBuffer[i]);
656
+ }
657
+ } else {
658
+ writeVarUint8Array(encoder, encodeUtf8(str));
659
+ }
660
+ };
661
+
662
+ /**
663
+ * Write a variable length string.
664
+ *
665
+ * @function
666
+ * @param {Encoder} encoder
667
+ * @param {String} str The string that is to be encoded.
668
+ */
669
+ const _writeVarStringPolyfill = (encoder, str) => {
408
670
  const encodedString = unescape(encodeURIComponent(str));
409
671
  const len = encodedString.length;
410
672
  writeVarUint(encoder, len);
@@ -413,6 +675,16 @@ const writeVarString = (encoder, str) => {
413
675
  }
414
676
  };
415
677
 
678
+ /**
679
+ * Write a variable length string.
680
+ *
681
+ * @function
682
+ * @param {Encoder} encoder
683
+ * @param {String} str The string that is to be encoded.
684
+ */
685
+ /* c8 ignore next */
686
+ const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
687
+
416
688
  /**
417
689
  * Append fixed-length Uint8Array to the encoder.
418
690
  *
@@ -451,6 +723,19 @@ const writeVarUint8Array = (encoder, uint8Array) => {
451
723
  writeUint8Array(encoder, uint8Array);
452
724
  };
453
725
 
726
+ /**
727
+ * Error helpers.
728
+ *
729
+ * @module error
730
+ */
731
+
732
+ /**
733
+ * @param {string} s
734
+ * @return {Error}
735
+ */
736
+ /* c8 ignore next */
737
+ const create = s => new Error(s);
738
+
454
739
  /**
455
740
  * Efficient schema-less binary decoding with support for variable length encoding.
456
741
  *
@@ -462,7 +747,7 @@ const writeVarUint8Array = (encoder, uint8Array) => {
462
747
  *
463
748
  * ```js
464
749
  * // encoding step
465
- * const encoder = new encoding.createEncoder()
750
+ * const encoder = encoding.createEncoder()
466
751
  * encoding.writeVarUint(encoder, 256)
467
752
  * encoding.writeVarString(encoder, 'Hello world!')
468
753
  * const buf = encoding.toUint8Array(encoder)
@@ -470,7 +755,7 @@ const writeVarUint8Array = (encoder, uint8Array) => {
470
755
  *
471
756
  * ```js
472
757
  * // decoding step
473
- * const decoder = new decoding.createDecoder(buf)
758
+ * const decoder = decoding.createDecoder(buf)
474
759
  * decoding.readVarUint(decoder) // => 256
475
760
  * decoding.readVarString(decoder) // => 'Hello world!'
476
761
  * decoding.hasContent(decoder) // => false - all data is read
@@ -479,6 +764,9 @@ const writeVarUint8Array = (encoder, uint8Array) => {
479
764
  * @module decoding
480
765
  */
481
766
 
767
+ const errorUnexpectedEndOfArray = create('Unexpected end of array');
768
+ const errorIntegerOutOfRange = create('Integer out of Range');
769
+
482
770
  /**
483
771
  * A Decoder handles the decoding of an Uint8Array.
484
772
  */
@@ -558,24 +846,28 @@ const readUint8 = decoder => decoder.arr[decoder.pos++];
558
846
  */
559
847
  const readVarUint = decoder => {
560
848
  let num = 0;
561
- let len = 0;
562
- while (true) {
849
+ let mult = 1;
850
+ const len = decoder.arr.length;
851
+ while (decoder.pos < len) {
563
852
  const r = decoder.arr[decoder.pos++];
564
- num = num | ((r & BITS7) << len);
565
- len += 7;
853
+ // num = num | ((r & binary.BITS7) << len)
854
+ num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
855
+ mult *= 128; // next iteration, shift 7 "more" to the left
566
856
  if (r < BIT8) {
567
- return num >>> 0 // return unsigned number!
857
+ return num
568
858
  }
569
- /* istanbul ignore if */
570
- if (len > 35) {
571
- throw new Error('Integer out of range!')
859
+ /* c8 ignore start */
860
+ if (num > MAX_SAFE_INTEGER) {
861
+ throw errorIntegerOutOfRange
572
862
  }
863
+ /* c8 ignore stop */
573
864
  }
865
+ throw errorUnexpectedEndOfArray
574
866
  };
575
867
 
576
868
  /**
577
- * Read string of variable length
578
- * * varUint is used to store the length of the string
869
+ * We don't test this function anymore as we use native decoding/encoding by default now.
870
+ * Better not modify this anymore..
579
871
  *
580
872
  * Transforming utf8 to a string is pretty expensive. The code performs 10x better
581
873
  * when String.fromCodePoint is fed with all characters as arguments.
@@ -586,7 +878,8 @@ const readVarUint = decoder => {
586
878
  * @param {Decoder} decoder
587
879
  * @return {String} The read String.
588
880
  */
589
- const readVarString = decoder => {
881
+ /* c8 ignore start */
882
+ const _readVarStringPolyfill = decoder => {
590
883
  let remainingLen = readVarUint(decoder);
591
884
  if (remainingLen === 0) {
592
885
  return ''
@@ -610,6 +903,27 @@ const readVarString = decoder => {
610
903
  return decodeURIComponent(escape(encodedString))
611
904
  }
612
905
  };
906
+ /* c8 ignore stop */
907
+
908
+ /**
909
+ * @function
910
+ * @param {Decoder} decoder
911
+ * @return {String} The read String
912
+ */
913
+ const _readVarStringNative = decoder =>
914
+ /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
915
+
916
+ /**
917
+ * Read string of variable length
918
+ * * varUint is used to store the length of the string
919
+ *
920
+ * @function
921
+ * @param {Decoder} decoder
922
+ * @return {String} The read String
923
+ *
924
+ */
925
+ /* c8 ignore next */
926
+ const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
613
927
 
614
928
  /**
615
929
  * Utility functions to work with buffers (Uint8Array).
@@ -638,7 +952,7 @@ const createUint8ArrayViewFromArrayBuffer = (buffer, byteOffset, length) => new
638
952
  */
639
953
  const createUint8ArrayFromArrayBuffer = buffer => new Uint8Array(buffer);
640
954
 
641
- /* istanbul ignore next */
955
+ /* c8 ignore start */
642
956
  /**
643
957
  * @param {Uint8Array} bytes
644
958
  * @return {string}
@@ -651,6 +965,7 @@ const toBase64Browser = bytes => {
651
965
  // eslint-disable-next-line no-undef
652
966
  return btoa(s)
653
967
  };
968
+ /* c8 ignore stop */
654
969
 
655
970
  /**
656
971
  * @param {Uint8Array} bytes
@@ -658,7 +973,7 @@ const toBase64Browser = bytes => {
658
973
  */
659
974
  const toBase64Node = bytes => Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString('base64');
660
975
 
661
- /* istanbul ignore next */
976
+ /* c8 ignore start */
662
977
  /**
663
978
  * @param {string} s
664
979
  * @return {Uint8Array}
@@ -672,6 +987,7 @@ const fromBase64Browser = s => {
672
987
  }
673
988
  return bytes
674
989
  };
990
+ /* c8 ignore stop */
675
991
 
676
992
  /**
677
993
  * @param {string} s
@@ -681,17 +997,17 @@ const fromBase64Node = s => {
681
997
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)
682
998
  };
683
999
 
684
- /* istanbul ignore next */
1000
+ /* c8 ignore next */
685
1001
  const toBase64 = isBrowser ? toBase64Browser : toBase64Node;
686
1002
 
687
- /* istanbul ignore next */
1003
+ /* c8 ignore next */
688
1004
  const fromBase64 = isBrowser ? fromBase64Browser : fromBase64Node;
689
1005
 
690
1006
  /* eslint-env browser */
691
1007
 
692
1008
  /**
693
1009
  * @typedef {Object} Channel
694
- * @property {Set<Function>} Channel.subs
1010
+ * @property {Set<function(any, any):any>} Channel.subs
695
1011
  * @property {any} Channel.bc
696
1012
  */
697
1013
 
@@ -700,6 +1016,7 @@ const fromBase64 = isBrowser ? fromBase64Browser : fromBase64Node;
700
1016
  */
701
1017
  const channels = new Map();
702
1018
 
1019
+ /* c8 ignore start */
703
1020
  class LocalStoragePolyfill {
704
1021
  /**
705
1022
  * @param {string} room
@@ -710,7 +1027,11 @@ class LocalStoragePolyfill {
710
1027
  * @type {null|function({data:ArrayBuffer}):void}
711
1028
  */
712
1029
  this.onmessage = null;
713
- onChange(e => e.key === room && this.onmessage !== null && this.onmessage({ data: fromBase64(e.newValue || '') }));
1030
+ /**
1031
+ * @param {any} e
1032
+ */
1033
+ this._onChange = e => e.key === room && this.onmessage !== null && this.onmessage({ data: fromBase64(e.newValue || '') });
1034
+ onChange(this._onChange);
714
1035
  }
715
1036
 
716
1037
  /**
@@ -719,9 +1040,15 @@ class LocalStoragePolyfill {
719
1040
  postMessage (buf) {
720
1041
  varStorage.setItem(this.room, toBase64(createUint8ArrayFromArrayBuffer(buf)));
721
1042
  }
1043
+
1044
+ close () {
1045
+ offChange(this._onChange);
1046
+ }
722
1047
  }
1048
+ /* c8 ignore stop */
723
1049
 
724
1050
  // Use BroadcastChannel or Polyfill
1051
+ /* c8 ignore next */
725
1052
  const BC = typeof BroadcastChannel === 'undefined' ? LocalStoragePolyfill : BroadcastChannel;
726
1053
 
727
1054
  /**
@@ -730,12 +1057,13 @@ const BC = typeof BroadcastChannel === 'undefined' ? LocalStoragePolyfill : Broa
730
1057
  */
731
1058
  const getChannel = room =>
732
1059
  setIfUndefined(channels, room, () => {
733
- const subs = new Set();
1060
+ const subs = create$1();
734
1061
  const bc = new BC(room);
735
1062
  /**
736
1063
  * @param {{data:ArrayBuffer}} e
737
1064
  */
738
- bc.onmessage = e => subs.forEach(sub => sub(e.data));
1065
+ /* c8 ignore next */
1066
+ bc.onmessage = e => subs.forEach(sub => sub(e.data, 'broadcastchannel'));
739
1067
  return {
740
1068
  bc, subs
741
1069
  }
@@ -746,18 +1074,29 @@ const getChannel = room =>
746
1074
  *
747
1075
  * @function
748
1076
  * @param {string} room
749
- * @param {function(any):any} f
1077
+ * @param {function(any, any):any} f
750
1078
  */
751
- const subscribe = (room, f) => getChannel(room).subs.add(f);
1079
+ const subscribe = (room, f) => {
1080
+ getChannel(room).subs.add(f);
1081
+ return f
1082
+ };
752
1083
 
753
1084
  /**
754
1085
  * Unsubscribe from `publish` global events.
755
1086
  *
756
1087
  * @function
757
1088
  * @param {string} room
758
- * @param {function(any):any} f
759
- */
760
- const unsubscribe = (room, f) => getChannel(room).subs.delete(f);
1089
+ * @param {function(any, any):any} f
1090
+ */
1091
+ const unsubscribe = (room, f) => {
1092
+ const channel = getChannel(room);
1093
+ const unsubscribed = channel.subs.delete(f);
1094
+ if (unsubscribed && channel.subs.size === 0) {
1095
+ channel.bc.close();
1096
+ channels.delete(room);
1097
+ }
1098
+ return unsubscribed
1099
+ };
761
1100
 
762
1101
  /**
763
1102
  * Publish data to all subscribers (including subscribers on this tab)
@@ -765,11 +1104,12 @@ const unsubscribe = (room, f) => getChannel(room).subs.delete(f);
765
1104
  * @function
766
1105
  * @param {string} room
767
1106
  * @param {any} data
1107
+ * @param {any} [origin]
768
1108
  */
769
- const publish = (room, data) => {
1109
+ const publish = (room, data, origin = null) => {
770
1110
  const c = getChannel(room);
771
1111
  c.bc.postMessage(data);
772
- c.subs.forEach(sub => sub(data));
1112
+ c.subs.forEach(sub => sub(data, origin));
773
1113
  };
774
1114
 
775
1115
  /**
@@ -785,30 +1125,6 @@ const publish = (room, data) => {
785
1125
  */
786
1126
  const getUnixTime = Date.now;
787
1127
 
788
- /**
789
- * Utility module to work with sets.
790
- *
791
- * @module set
792
- */
793
-
794
- const create = () => new Set();
795
-
796
- /**
797
- * Utility module to work with Arrays.
798
- *
799
- * @module array
800
- */
801
-
802
- /**
803
- * Transforms something array-like to an actual Array.
804
- *
805
- * @function
806
- * @template T
807
- * @param {ArrayLike<T>|Iterable<T>} arraylike
808
- * @return {T}
809
- */
810
- const from = Array.from;
811
-
812
1128
  /**
813
1129
  * Observable class prototype.
814
1130
  *
@@ -826,7 +1142,7 @@ class Observable {
826
1142
  * Some desc.
827
1143
  * @type {Map<N, any>}
828
1144
  */
829
- this._observers = create$1();
1145
+ this._observers = create$2();
830
1146
  }
831
1147
 
832
1148
  /**
@@ -834,7 +1150,7 @@ class Observable {
834
1150
  * @param {function} f
835
1151
  */
836
1152
  on (name, f) {
837
- setIfUndefined(this._observers, name, create).add(f);
1153
+ setIfUndefined(this._observers, name, create$1).add(f);
838
1154
  }
839
1155
 
840
1156
  /**
@@ -877,148 +1193,14 @@ class Observable {
877
1193
  */
878
1194
  emit (name, args) {
879
1195
  // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
880
- return from((this._observers.get(name) || create$1()).values()).forEach(f => f(...args))
1196
+ return from((this._observers.get(name) || create$2()).values()).forEach(f => f(...args))
881
1197
  }
882
1198
 
883
1199
  destroy () {
884
- this._observers = create$1();
1200
+ this._observers = create$2();
885
1201
  }
886
1202
  }
887
1203
 
888
- /**
889
- * Utility functions for working with EcmaScript objects.
890
- *
891
- * @module object
892
- */
893
-
894
- /**
895
- * @param {Object<string,any>} obj
896
- */
897
- const keys = Object.keys;
898
-
899
- /**
900
- * @template R
901
- * @param {Object<string,any>} obj
902
- * @param {function(any,string):R} f
903
- * @return {Array<R>}
904
- */
905
- const map = (obj, f) => {
906
- const results = [];
907
- for (const key in obj) {
908
- results.push(f(obj[key], key));
909
- }
910
- return results
911
- };
912
-
913
- /**
914
- * @param {Object<string,any>} obj
915
- * @return {number}
916
- */
917
- const length = obj => keys(obj).length;
918
-
919
- /**
920
- * Calls `Object.prototype.hasOwnProperty`.
921
- *
922
- * @param {any} obj
923
- * @param {string|symbol} key
924
- * @return {boolean}
925
- */
926
- const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
927
-
928
- /**
929
- * Common functions and function call helpers.
930
- *
931
- * @module function
932
- */
933
-
934
- /**
935
- * @template T
936
- *
937
- * @param {T} a
938
- * @param {T} b
939
- * @return {boolean}
940
- */
941
- const equalityStrict = (a, b) => a === b;
942
-
943
- /**
944
- * @param {any} a
945
- * @param {any} b
946
- * @return {boolean}
947
- */
948
- const equalityDeep = (a, b) => {
949
- if (a == null || b == null) {
950
- return equalityStrict(a, b)
951
- }
952
- if (a.constructor !== b.constructor) {
953
- return false
954
- }
955
- if (a === b) {
956
- return true
957
- }
958
- switch (a.constructor) {
959
- case ArrayBuffer:
960
- a = new Uint8Array(a);
961
- b = new Uint8Array(b);
962
- // eslint-disable-next-line no-fallthrough
963
- case Uint8Array: {
964
- if (a.byteLength !== b.byteLength) {
965
- return false
966
- }
967
- for (let i = 0; i < a.length; i++) {
968
- if (a[i] !== b[i]) {
969
- return false
970
- }
971
- }
972
- break
973
- }
974
- case Set: {
975
- if (a.size !== b.size) {
976
- return false
977
- }
978
- for (const value of a) {
979
- if (!b.has(value)) {
980
- return false
981
- }
982
- }
983
- break
984
- }
985
- case Map: {
986
- if (a.size !== b.size) {
987
- return false
988
- }
989
- for (const key of a.keys()) {
990
- if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
991
- return false
992
- }
993
- }
994
- break
995
- }
996
- case Object:
997
- if (length(a) !== length(b)) {
998
- return false
999
- }
1000
- for (const key in a) {
1001
- if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
1002
- return false
1003
- }
1004
- }
1005
- break
1006
- case Array:
1007
- if (a.length !== b.length) {
1008
- return false
1009
- }
1010
- for (let i = 0; i < a.length; i++) {
1011
- if (!equalityDeep(a[i], b[i])) {
1012
- return false
1013
- }
1014
- }
1015
- break
1016
- default:
1017
- return false
1018
- }
1019
- return true
1020
- };
1021
-
1022
1204
  /**
1023
1205
  * @module awareness-protocol
1024
1206
  */
@@ -1384,7 +1566,7 @@ class IncomingMessage {
1384
1566
  return writeVarUint8Array(this.encoder, data);
1385
1567
  }
1386
1568
  length() {
1387
- return length$1(this.encoder);
1569
+ return length(this.encoder);
1388
1570
  }
1389
1571
  }
1390
1572
 
@@ -2180,7 +2362,11 @@ class HocuspocusProvider extends EventEmitter {
2180
2362
  }
2181
2363
  setConfiguration(configuration = {}) {
2182
2364
  if (!configuration.websocketProvider && configuration.url) {
2183
- this.configuration.websocketProvider = new HocuspocusProviderWebsocket({ url: configuration.url });
2365
+ const websocketProviderConfig = configuration;
2366
+ this.configuration.websocketProvider = new HocuspocusProviderWebsocket({
2367
+ url: websocketProviderConfig.url,
2368
+ parameters: websocketProviderConfig.parameters,
2369
+ });
2184
2370
  }
2185
2371
  this.configuration = { ...this.configuration, ...configuration };
2186
2372
  }