lib0 0.2.43 → 0.2.44

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.
Files changed (104) hide show
  1. package/README.md +49 -0
  2. package/cache.d.ts +50 -0
  3. package/cache.d.ts.map +1 -0
  4. package/cache.js +178 -0
  5. package/cache.test.d.ts +3 -0
  6. package/cache.test.d.ts.map +1 -0
  7. package/diff.d.ts +5 -0
  8. package/diff.d.ts.map +1 -1
  9. package/diff.js +47 -10
  10. package/diff.test.d.ts +1 -0
  11. package/diff.test.d.ts.map +1 -1
  12. package/dist/{broadcastchannel-044f32d2.cjs → broadcastchannel-7da37795.cjs} +2 -2
  13. package/dist/{broadcastchannel-044f32d2.cjs.map → broadcastchannel-7da37795.cjs.map} +1 -1
  14. package/dist/broadcastchannel.cjs +4 -4
  15. package/dist/{buffer-49880125.cjs → buffer-b0dea3b0.cjs} +3 -3
  16. package/dist/{buffer-49880125.cjs.map → buffer-b0dea3b0.cjs.map} +1 -1
  17. package/dist/buffer.cjs +3 -3
  18. package/dist/cache.cjs +185 -0
  19. package/dist/cache.cjs.map +1 -0
  20. package/dist/cache.d.ts +50 -0
  21. package/dist/cache.d.ts.map +1 -0
  22. package/dist/cache.test.d.ts +3 -0
  23. package/dist/cache.test.d.ts.map +1 -0
  24. package/dist/component.cjs +2 -2
  25. package/dist/decoding.cjs +3 -3
  26. package/dist/{diff-75787d87.cjs → diff-233747fa.cjs} +51 -12
  27. package/dist/diff-233747fa.cjs.map +1 -0
  28. package/dist/diff.cjs +2 -1
  29. package/dist/diff.cjs.map +1 -1
  30. package/dist/diff.d.ts +5 -0
  31. package/dist/diff.d.ts.map +1 -1
  32. package/dist/diff.test.d.ts +1 -0
  33. package/dist/diff.test.d.ts.map +1 -1
  34. package/dist/dom.d.ts.map +1 -1
  35. package/dist/encoding.cjs +3 -3
  36. package/dist/{environment-7e2ffaea.cjs → environment-60b83194.cjs} +2 -2
  37. package/dist/{environment-7e2ffaea.cjs.map → environment-60b83194.cjs.map} +1 -1
  38. package/dist/environment.cjs +2 -2
  39. package/dist/index.cjs +9 -9
  40. package/dist/list.cjs +172 -0
  41. package/dist/list.cjs.map +1 -0
  42. package/dist/list.d.ts +33 -0
  43. package/dist/list.d.ts.map +1 -0
  44. package/dist/list.test.d.ts +4 -0
  45. package/dist/list.test.d.ts.map +1 -0
  46. package/dist/{logging-7cc36806.cjs → logging-f6d41f58.cjs} +2 -2
  47. package/dist/{logging-7cc36806.cjs.map → logging-f6d41f58.cjs.map} +1 -1
  48. package/dist/logging.cjs +3 -3
  49. package/dist/observable.cjs +1 -1
  50. package/dist/{prng-97174619.cjs → prng-25602bac.cjs} +3 -3
  51. package/dist/{prng-97174619.cjs.map → prng-25602bac.cjs.map} +1 -1
  52. package/dist/prng.cjs +4 -4
  53. package/dist/queue.cjs +3 -0
  54. package/dist/queue.cjs.map +1 -1
  55. package/dist/queue.d.ts.map +1 -1
  56. package/dist/queue.test.d.ts.map +1 -1
  57. package/dist/set-b596ef38.cjs +49 -0
  58. package/dist/set-b596ef38.cjs.map +1 -0
  59. package/dist/set.cjs +3 -1
  60. package/dist/set.cjs.map +1 -1
  61. package/dist/set.d.ts +2 -0
  62. package/dist/set.d.ts.map +1 -1
  63. package/dist/set.test.d.ts +2 -0
  64. package/dist/set.test.d.ts.map +1 -1
  65. package/dist/{string-f3c3d805.cjs → string-ad04f734.cjs} +12 -2
  66. package/dist/{string-f3c3d805.cjs.map → string-ad04f734.cjs.map} +1 -1
  67. package/dist/string.cjs +2 -1
  68. package/dist/string.cjs.map +1 -1
  69. package/dist/string.d.ts +1 -0
  70. package/dist/string.d.ts.map +1 -1
  71. package/dist/string.test.d.ts +1 -0
  72. package/dist/string.test.d.ts.map +1 -1
  73. package/dist/test.cjs +721 -101
  74. package/dist/test.cjs.map +1 -1
  75. package/dist/test.js +721 -101
  76. package/dist/test.js.map +1 -1
  77. package/dist/testing.cjs +6 -6
  78. package/dist/{websocket-bfe7f545.cjs → websocket-08bd4c7b.cjs} +1 -1
  79. package/dist/{websocket-bfe7f545.cjs.map → websocket-08bd4c7b.cjs.map} +1 -1
  80. package/dist/websocket.cjs +2 -2
  81. package/dom.d.ts.map +1 -1
  82. package/list.d.ts +33 -0
  83. package/list.d.ts.map +1 -0
  84. package/list.js +155 -0
  85. package/list.test.d.ts +4 -0
  86. package/list.test.d.ts.map +1 -0
  87. package/package.json +13 -1
  88. package/queue.d.ts.map +1 -1
  89. package/queue.js +3 -0
  90. package/queue.test.d.ts.map +1 -1
  91. package/set.d.ts +2 -0
  92. package/set.d.ts.map +1 -1
  93. package/set.js +18 -0
  94. package/set.test.d.ts +2 -0
  95. package/set.test.d.ts.map +1 -1
  96. package/string.d.ts +1 -0
  97. package/string.d.ts.map +1 -1
  98. package/string.js +8 -0
  99. package/string.test.d.ts +1 -0
  100. package/string.test.d.ts.map +1 -1
  101. package/test.js +7 -1
  102. package/dist/diff-75787d87.cjs.map +0 -1
  103. package/dist/set-7ae96d21.cjs +0 -27
  104. package/dist/set-7ae96d21.cjs.map +0 -1
package/dist/test.js CHANGED
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * @function
17
17
  */
18
- const create$7 = () => new Map();
18
+ const create$a = () => new Map();
19
19
 
20
20
  /**
21
21
  * Copy a Map object into a fresh Map object.
@@ -26,7 +26,7 @@
26
26
  * @return {Map<X,Y>}
27
27
  */
28
28
  const copy = m => {
29
- const r = create$7();
29
+ const r = create$a();
30
30
  m.forEach((v, k) => { r.set(k, v); });
31
31
  return r
32
32
  };
@@ -46,7 +46,7 @@
46
46
  * @param {function():T} createT
47
47
  * @return {T}
48
48
  */
49
- const setIfUndefined = (map, key, createT) => {
49
+ const setIfUndefined$1 = (map, key, createT) => {
50
50
  let set = map.get(key);
51
51
  if (set === undefined) {
52
52
  map.set(key, set = createT());
@@ -65,7 +65,7 @@
65
65
  * @param {function(V,K):R} f
66
66
  * @return {Array<R>}
67
67
  */
68
- const map$3 = (m, f) => {
68
+ const map$4 = (m, f) => {
69
69
  const res = [];
70
70
  for (const [key, value] of m) {
71
71
  res.push(f(value, key));
@@ -188,6 +188,14 @@
188
188
  /* istanbul ignore next */
189
189
  const decodeUtf8 = utf8TextDecoder ? _decodeUtf8Native : _decodeUtf8Polyfill;
190
190
 
191
+ /**
192
+ * @param {string} str The initial string
193
+ * @param {number} index Starting position
194
+ * @param {number} remove Number of characters to remove
195
+ * @param {string} insert New content to insert
196
+ */
197
+ const splice = (str, index, remove, insert = '') => str.slice(0, index) + insert + str.slice(index + remove);
198
+
191
199
  /**
192
200
  * Often used conditions.
193
201
  *
@@ -288,7 +296,7 @@
288
296
  const computeParams = () => {
289
297
  if (params === undefined) {
290
298
  if (isNode) {
291
- params = create$7();
299
+ params = create$a();
292
300
  const pargs = process.argv;
293
301
  let currParamName = null;
294
302
  /* istanbul ignore next */
@@ -311,7 +319,7 @@
311
319
  }
312
320
  // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
313
321
  } else if (typeof location === 'object') {
314
- params = create$7()
322
+ params = create$a()
315
323
  // eslint-disable-next-line no-undef
316
324
  ;(location.search || '?').slice(1).split('&').forEach(kv => {
317
325
  if (kv.length !== 0) {
@@ -321,7 +329,7 @@
321
329
  }
322
330
  });
323
331
  } else {
324
- params = create$7();
332
+ params = create$a();
325
333
  }
326
334
  }
327
335
  return params
@@ -371,7 +379,7 @@
371
379
  *
372
380
  * @return {Symbol}
373
381
  */
374
- const create$6 = Symbol;
382
+ const create$9 = Symbol;
375
383
 
376
384
  /**
377
385
  * Working with value pairs.
@@ -399,7 +407,7 @@
399
407
  * @param {R} right
400
408
  * @return {Pair<L,R>}
401
409
  */
402
- const create$5 = (left, right) => new Pair(left, right);
410
+ const create$8 = (left, right) => new Pair(left, right);
403
411
 
404
412
  /**
405
413
  * @template L,R
@@ -422,7 +430,7 @@
422
430
  * @param {function(L, R):X} f
423
431
  * @return {Array<X>}
424
432
  */
425
- const map$2 = (arr, f) => arr.map(p => f(p.left, p.right));
433
+ const map$3 = (arr, f) => arr.map(p => f(p.left, p.right));
426
434
 
427
435
  /* eslint-env browser */
428
436
 
@@ -541,7 +549,7 @@
541
549
  * @return {string}
542
550
  */
543
551
  /* istanbul ignore next */
544
- const mapToStyleString = m => map$3(m, (value, key) => `${key}:${value};`).join('');
552
+ const mapToStyleString = m => map$4(m, (value, key) => `${key}:${value};`).join('');
545
553
 
546
554
  /**
547
555
  * @param {Node} parent
@@ -863,7 +871,7 @@
863
871
  /**
864
872
  * @return {Object<string,any>} obj
865
873
  */
866
- const create$4 = () => Object.create(null);
874
+ const create$7 = () => Object.create(null);
867
875
 
868
876
  /**
869
877
  * Object.assign
@@ -891,7 +899,7 @@
891
899
  * @param {function(any,string):R} f
892
900
  * @return {Array<R>}
893
901
  */
894
- const map$1 = (obj, f) => {
902
+ const map$2 = (obj, f) => {
895
903
  const results = [];
896
904
  for (const key in obj) {
897
905
  results.push(f(obj[key], key));
@@ -1058,29 +1066,29 @@
1058
1066
  * @module logging
1059
1067
  */
1060
1068
 
1061
- const BOLD = create$6();
1062
- const UNBOLD = create$6();
1063
- const BLUE = create$6();
1064
- const GREY = create$6();
1065
- const GREEN = create$6();
1066
- const RED = create$6();
1067
- const PURPLE = create$6();
1068
- const ORANGE = create$6();
1069
- const UNCOLOR = create$6();
1069
+ const BOLD = create$9();
1070
+ const UNBOLD = create$9();
1071
+ const BLUE = create$9();
1072
+ const GREY = create$9();
1073
+ const GREEN = create$9();
1074
+ const RED = create$9();
1075
+ const PURPLE = create$9();
1076
+ const ORANGE = create$9();
1077
+ const UNCOLOR = create$9();
1070
1078
 
1071
1079
  /**
1072
1080
  * @type {Object<Symbol,pair.Pair<string,string>>}
1073
1081
  */
1074
1082
  const _browserStyleMap = {
1075
- [BOLD]: create$5('font-weight', 'bold'),
1076
- [UNBOLD]: create$5('font-weight', 'normal'),
1077
- [BLUE]: create$5('color', 'blue'),
1078
- [GREEN]: create$5('color', 'green'),
1079
- [GREY]: create$5('color', 'grey'),
1080
- [RED]: create$5('color', 'red'),
1081
- [PURPLE]: create$5('color', 'purple'),
1082
- [ORANGE]: create$5('color', 'orange'), // not well supported in chrome when debugging node with inspector - TODO: deprecate
1083
- [UNCOLOR]: create$5('color', 'black')
1083
+ [BOLD]: create$8('font-weight', 'bold'),
1084
+ [UNBOLD]: create$8('font-weight', 'normal'),
1085
+ [BLUE]: create$8('color', 'blue'),
1086
+ [GREEN]: create$8('color', 'green'),
1087
+ [GREY]: create$8('color', 'grey'),
1088
+ [RED]: create$8('color', 'red'),
1089
+ [PURPLE]: create$8('color', 'purple'),
1090
+ [ORANGE]: create$8('color', 'orange'), // not well supported in chrome when debugging node with inspector - TODO: deprecate
1091
+ [UNCOLOR]: create$8('color', 'black')
1084
1092
  };
1085
1093
 
1086
1094
  const _nodeStyleMap = {
@@ -1103,7 +1111,7 @@
1103
1111
  const computeBrowserLoggingArgs = args => {
1104
1112
  const strBuilder = [];
1105
1113
  const styles = [];
1106
- const currentStyle = create$7();
1114
+ const currentStyle = create$a();
1107
1115
  /**
1108
1116
  * @type {Array<string|Object|number>}
1109
1117
  */
@@ -1281,7 +1289,7 @@
1281
1289
  } else {
1282
1290
  if (arg.constructor === String || arg.constructor === Number) {
1283
1291
  // @ts-ignore
1284
- const span = element('span', [create$5('style', mapToStyleString(currentStyle))], [text(arg)]);
1292
+ const span = element('span', [create$8('style', mapToStyleString(currentStyle))], [text(arg)]);
1285
1293
  if (span.innerHTML === '') {
1286
1294
  span.innerHTML = '&nbsp;';
1287
1295
  }
@@ -1327,10 +1335,10 @@
1327
1335
  */
1328
1336
  group (args, collapsed = false) {
1329
1337
  enqueue$1(() => {
1330
- const triangleDown = element('span', [create$5('hidden', collapsed), create$5('style', 'color:grey;font-size:120%;')], [text('▼')]);
1331
- const triangleRight = element('span', [create$5('hidden', !collapsed), create$5('style', 'color:grey;font-size:125%;')], [text('▶')]);
1332
- const content = element('div', [create$5('style', `${lineStyle};padding-left:${this.depth * 10}px`)], [triangleDown, triangleRight, text(' ')].concat(_computeLineSpans(args)));
1333
- const nextContainer = element('div', [create$5('hidden', collapsed)]);
1338
+ const triangleDown = element('span', [create$8('hidden', collapsed), create$8('style', 'color:grey;font-size:120%;')], [text('▼')]);
1339
+ const triangleRight = element('span', [create$8('hidden', !collapsed), create$8('style', 'color:grey;font-size:125%;')], [text('▶')]);
1340
+ const content = element('div', [create$8('style', `${lineStyle};padding-left:${this.depth * 10}px`)], [triangleDown, triangleRight, text(' ')].concat(_computeLineSpans(args)));
1341
+ const nextContainer = element('div', [create$8('hidden', collapsed)]);
1334
1342
  const nextLine = element('div', [], [content, nextContainer]);
1335
1343
  append(this.ccontainer, [nextLine]);
1336
1344
  this.ccontainer = nextContainer;
@@ -1366,7 +1374,7 @@
1366
1374
  */
1367
1375
  print (args) {
1368
1376
  enqueue$1(() => {
1369
- append(this.ccontainer, [element('div', [create$5('style', `${lineStyle};padding-left:${this.depth * 10}px`)], _computeLineSpans(args))]);
1377
+ append(this.ccontainer, [element('div', [create$8('style', `${lineStyle};padding-left:${this.depth * 10}px`)], _computeLineSpans(args))]);
1370
1378
  });
1371
1379
  }
1372
1380
 
@@ -1383,7 +1391,7 @@
1383
1391
  */
1384
1392
  printImg (url, height) {
1385
1393
  enqueue$1(() => {
1386
- append(this.ccontainer, [element('img', [create$5('src', url), create$5('height', `${round(height * 1.5)}px`)])]);
1394
+ append(this.ccontainer, [element('img', [create$8('src', url), create$8('height', `${round(height * 1.5)}px`)])]);
1387
1395
  });
1388
1396
  }
1389
1397
 
@@ -1453,11 +1461,8 @@
1453
1461
  while (left < a.length && left < b.length && a[left] === b[left]) {
1454
1462
  left++;
1455
1463
  }
1456
- if (left !== a.length || left !== b.length) {
1457
- // Only check right if a !== b
1458
- while (right + left < a.length && right + left < b.length && a[a.length - right - 1] === b[b.length - right - 1]) {
1459
- right++;
1460
- }
1464
+ while (right + left < a.length && right + left < b.length && a[a.length - right - 1] === b[b.length - right - 1]) {
1465
+ right++;
1461
1466
  }
1462
1467
  return {
1463
1468
  index: left,
@@ -1487,11 +1492,51 @@
1487
1492
  while (left < a.length && left < b.length && compare(a[left], b[left])) {
1488
1493
  left++;
1489
1494
  }
1490
- if (left !== a.length || left !== b.length) {
1491
- // Only check right if a !== b
1492
- while (right + left < a.length && right + left < b.length && compare(a[a.length - right - 1], b[b.length - right - 1])) {
1493
- right++;
1494
- }
1495
+ while (right + left < a.length && right + left < b.length && compare(a[a.length - right - 1], b[b.length - right - 1])) {
1496
+ right++;
1497
+ }
1498
+ return {
1499
+ index: left,
1500
+ remove: a.length - left - right,
1501
+ insert: b.slice(left, b.length - right)
1502
+ }
1503
+ };
1504
+
1505
+ /**
1506
+ * Diff text and try to diff at the current cursor position.
1507
+ *
1508
+ * @param {string} a
1509
+ * @param {string} b
1510
+ * @param {number} cursor This should refer to the current left cursor-range position
1511
+ */
1512
+ const simpleDiffStringWithCursor = (a, b, cursor) => {
1513
+ let left = 0; // number of same characters counting from left
1514
+ let right = 0; // number of same characters counting from right
1515
+ // Iterate left to the right until we find a changed character
1516
+ // First iteration considers the current cursor position
1517
+ while (
1518
+ left < a.length &&
1519
+ left < b.length &&
1520
+ a[left] === b[left] &&
1521
+ left < cursor
1522
+ ) {
1523
+ left++;
1524
+ }
1525
+ // Iterate right to the left until we find a changed character
1526
+ while (
1527
+ right + left < a.length &&
1528
+ right + left < b.length &&
1529
+ a[a.length - right - 1] === b[b.length - right - 1]
1530
+ ) {
1531
+ right++;
1532
+ }
1533
+ // Try to iterate left further to the right without caring about the current cursor position
1534
+ while (
1535
+ right + left < a.length &&
1536
+ right + left < b.length &&
1537
+ a[left] === b[left]
1538
+ ) {
1539
+ left++;
1495
1540
  }
1496
1541
  return {
1497
1542
  index: left,
@@ -1985,7 +2030,7 @@
1985
2030
  * @param {number} pos Position to which to write data
1986
2031
  * @param {number} num Unsigned 8-bit integer
1987
2032
  */
1988
- const set = (encoder, pos, num) => {
2033
+ const set$2 = (encoder, pos, num) => {
1989
2034
  let buffer = null;
1990
2035
  // iterate all buffers and adjust position
1991
2036
  for (let i = 0; i < encoder.bufs.length && buffer === null; i++) {
@@ -2020,7 +2065,7 @@
2020
2065
  * @param {number} pos The location where the data will be written.
2021
2066
  * @param {number} num The number that is to be encoded.
2022
2067
  */
2023
- const setUint8 = set;
2068
+ const setUint8 = set$2;
2024
2069
 
2025
2070
  /**
2026
2071
  * Write two bytes as an unsigned integer.
@@ -2042,8 +2087,8 @@
2042
2087
  * @param {number} num The number that is to be encoded.
2043
2088
  */
2044
2089
  const setUint16 = (encoder, pos, num) => {
2045
- set(encoder, pos, num & BITS8);
2046
- set(encoder, pos + 1, (num >>> 8) & BITS8);
2090
+ set$2(encoder, pos, num & BITS8);
2091
+ set$2(encoder, pos + 1, (num >>> 8) & BITS8);
2047
2092
  };
2048
2093
 
2049
2094
  /**
@@ -2084,7 +2129,7 @@
2084
2129
  */
2085
2130
  const setUint32 = (encoder, pos, num) => {
2086
2131
  for (let i = 0; i < 4; i++) {
2087
- set(encoder, pos + i, num & BITS8);
2132
+ set$2(encoder, pos + i, num & BITS8);
2088
2133
  num >>>= 8;
2089
2134
  }
2090
2135
  };
@@ -3387,7 +3432,7 @@
3387
3432
  * @param {number} seed A positive 32bit integer. Do not use negative numbers.
3388
3433
  * @return {PRNG}
3389
3434
  */
3390
- const create$3 = seed => new DefaultPRNG(seed);
3435
+ const create$6 = seed => new DefaultPRNG(seed);
3391
3436
 
3392
3437
  /**
3393
3438
  * Generates a single random bool.
@@ -3577,7 +3622,7 @@
3577
3622
  * @param {function(PromiseResolve<T>,function(Error):void):any} f
3578
3623
  * @return {Promise<T>}
3579
3624
  */
3580
- const create$2 = f => /** @type {Promise<T>} */ (new Promise(f));
3625
+ const create$5 = f => /** @type {Promise<T>} */ (new Promise(f));
3581
3626
 
3582
3627
  /**
3583
3628
  * @param {function(function():void,function(Error):void):void} f
@@ -3606,6 +3651,13 @@
3606
3651
  */
3607
3652
  const resolve = res => Promise.resolve(res);
3608
3653
 
3654
+ /**
3655
+ * @template T
3656
+ * @param {T} res
3657
+ * @return {Promise<T>}
3658
+ */
3659
+ const resolveWith = res => Promise.resolve(res);
3660
+
3609
3661
  /**
3610
3662
  * @todo Next version, reorder parameters: check, [timeout, [intervalResolution]]
3611
3663
  *
@@ -3614,7 +3666,7 @@
3614
3666
  * @param {number} [intervalResolution]
3615
3667
  * @return {Promise<void>}
3616
3668
  */
3617
- const until = (timeout, check, intervalResolution = 10) => create$2((resolve, reject) => {
3669
+ const until = (timeout, check, intervalResolution = 10) => create$5((resolve, reject) => {
3618
3670
  const startTime = getUnixTime();
3619
3671
  const hasTimeout = timeout > 0;
3620
3672
  const untilInterval = () => {
@@ -3636,7 +3688,7 @@
3636
3688
  * @param {number} timeout
3637
3689
  * @return {Promise<undefined>}
3638
3690
  */
3639
- const wait = timeout => create$2((resolve, reject) => setTimeout(resolve, timeout));
3691
+ const wait = timeout => create$5((resolve, reject) => setTimeout(resolve, timeout));
3640
3692
 
3641
3693
  /**
3642
3694
  * Checks if an object is a promise using ducktyping.
@@ -3743,7 +3795,7 @@
3743
3795
  get prng () {
3744
3796
  /* istanbul ignore else */
3745
3797
  if (this._prng === null) {
3746
- this._prng = create$3(this.seed);
3798
+ this._prng = create$6(this.seed);
3747
3799
  }
3748
3800
  return this._prng
3749
3801
  }
@@ -4170,7 +4222,7 @@
4170
4222
  * @param {Object<string, Object<string, function(TestCase):void|Promise<any>>>} tests
4171
4223
  */
4172
4224
  const runTests = async tests => {
4173
- const numberOfTests = map$1(tests, mod => map$1(mod, f => /* istanbul ignore next */ f ? 1 : 0).reduce(add$1, 0)).reduce(add$1, 0);
4225
+ const numberOfTests = map$2(tests, mod => map$2(mod, f => /* istanbul ignore next */ f ? 1 : 0).reduce(add$1, 0)).reduce(add$1, 0);
4174
4226
  let successfulTests = 0;
4175
4227
  let testnumber = 0;
4176
4228
  const start = performance.now();
@@ -4336,12 +4388,22 @@
4336
4388
  }
4337
4389
  };
4338
4390
 
4391
+ /**
4392
+ * @param {t.TestCase} tc
4393
+ */
4394
+ const testSplice = tc => {
4395
+ const initial = 'xyz';
4396
+ compareStrings(splice(initial, 0, 2), 'z');
4397
+ compareStrings(splice(initial, 0, 2, 'u'), 'uz');
4398
+ };
4399
+
4339
4400
  var string = /*#__PURE__*/Object.freeze({
4340
4401
  __proto__: null,
4341
4402
  testLowercaseTransformation: testLowercaseTransformation,
4342
4403
  testRepeatStringUtf8Encoding: testRepeatStringUtf8Encoding,
4343
4404
  testRepeatStringUtf8Decoding: testRepeatStringUtf8Decoding,
4344
- testBomEncodingDecoding: testBomEncodingDecoding
4405
+ testBomEncodingDecoding: testBomEncodingDecoding,
4406
+ testSplice: testSplice
4345
4407
  });
4346
4408
 
4347
4409
  /* global BigInt */
@@ -5051,6 +5113,7 @@
5051
5113
  function runDiffTest (a, b, expected) {
5052
5114
  const result = simpleDiffString(a, b);
5053
5115
  compare(result, expected);
5116
+ compare(result, simpleDiffStringWithCursor(a, b, a.length)); // check that the withCursor approach returns the same result
5054
5117
  const arrResult = simpleDiffArray(a.split(''), b.split(''));
5055
5118
  compare(arrResult, assign({}, result, { insert: result.insert.split('') }));
5056
5119
  }
@@ -5076,10 +5139,43 @@
5076
5139
  const a = word(tc.prng);
5077
5140
  const b = word(tc.prng);
5078
5141
  const change = simpleDiffString(a, b);
5079
- const recomposed = `${a.slice(0, change.index)}${change.insert}${a.slice(change.index + change.remove)}`;
5142
+ const recomposed = splice(a, change.index, change.remove, change.insert);
5080
5143
  compareStrings(recomposed, b);
5081
5144
  };
5082
5145
 
5146
+ /**
5147
+ * @param {t.TestCase} tc
5148
+ */
5149
+ const testSimpleDiffWithCursor = tc => {
5150
+ const initial = 'Hello WorldHello World';
5151
+ const expected = 'Hello World';
5152
+ {
5153
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 0); // should delete the first hello world
5154
+ compare(change, { insert: '', remove: 11, index: 0 });
5155
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5156
+ compareStrings(expected, recomposed);
5157
+ }
5158
+ {
5159
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 11); // should delete the second hello world
5160
+ compare(change, { insert: '', remove: 11, index: 11 });
5161
+ const recomposedSecond = splice(initial, change.index, change.remove, change.insert);
5162
+ compareStrings(recomposedSecond, expected);
5163
+ }
5164
+ {
5165
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 5); // should delete in the midst of Hello World
5166
+ compare(change, { insert: '', remove: 11, index: 5 });
5167
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5168
+ compareStrings(expected, recomposed);
5169
+ }
5170
+ {
5171
+ const initial = 'Hello my World';
5172
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 0); // Should delete after the current cursor position
5173
+ compare(change, { insert: '', remove: 3, index: 5 });
5174
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5175
+ compareStrings(expected, recomposed);
5176
+ }
5177
+ };
5178
+
5083
5179
  /**
5084
5180
  * @param {t.TestCase} tc
5085
5181
  */
@@ -5095,6 +5191,7 @@
5095
5191
  __proto__: null,
5096
5192
  testDiffing: testDiffing,
5097
5193
  testRepeatDiffing: testRepeatDiffing,
5194
+ testSimpleDiffWithCursor: testSimpleDiffWithCursor,
5098
5195
  testArrayDiffing: testArrayDiffing
5099
5196
  });
5100
5197
 
@@ -5107,7 +5204,7 @@
5107
5204
  compare([1, 2], [1, 2], 'simple compare (array)');
5108
5205
  compare({ a: [1, 2] }, { a: [1, 2] }, 'simple compare nested');
5109
5206
  compare(new Set(['3', 1234]), new Set(['3', 1234]), 'compare Sets');
5110
- const map1 = create$7();
5207
+ const map1 = create$a();
5111
5208
  map1.set(1, 2);
5112
5209
  map1.set('x', {});
5113
5210
  map1.set(98, 'tst');
@@ -5211,7 +5308,7 @@
5211
5308
  };
5212
5309
 
5213
5310
  const testAsync = async () => {
5214
- await measureTimeAsync('time', () => create$2(r => setTimeout(r)));
5311
+ await measureTimeAsync('time', () => create$5(r => setTimeout(r)));
5215
5312
  await groupAsync('some description', () => wait(1));
5216
5313
  };
5217
5314
 
@@ -5244,7 +5341,16 @@
5244
5341
  * @param {string} s
5245
5342
  * @return {Error}
5246
5343
  */
5247
- const create$1 = s => new Error(s);
5344
+ const create$4 = s => new Error(s);
5345
+
5346
+ /* istanbul ignore next */
5347
+ /**
5348
+ * @throws {Error}
5349
+ * @return {never}
5350
+ */
5351
+ const unexpectedCase = () => {
5352
+ throw create$4('Unexpected case')
5353
+ };
5248
5354
 
5249
5355
  /* eslint-env browser */
5250
5356
 
@@ -5255,7 +5361,7 @@
5255
5361
  * @param {IDBRequest} request
5256
5362
  * @return {Promise<any>}
5257
5363
  */
5258
- const rtop = request => create$2((resolve, reject) => {
5364
+ const rtop = request => create$5((resolve, reject) => {
5259
5365
  /* istanbul ignore next */
5260
5366
  // @ts-ignore
5261
5367
  request.onerror = event => reject(new Error(event.target.error));
@@ -5272,7 +5378,7 @@
5272
5378
  * @param {function(IDBDatabase):any} initDB Called when the database is first created
5273
5379
  * @return {Promise<IDBDatabase>}
5274
5380
  */
5275
- const openDB = (name, initDB) => create$2((resolve, reject) => {
5381
+ const openDB = (name, initDB) => create$5((resolve, reject) => {
5276
5382
  const request = indexedDB.open(name);
5277
5383
  /**
5278
5384
  * @param {any} event
@@ -5282,7 +5388,7 @@
5282
5388
  /**
5283
5389
  * @param {any} event
5284
5390
  */
5285
- request.onerror = event => reject(create$1(event.target.error));
5391
+ request.onerror = event => reject(create$4(event.target.error));
5286
5392
  /* istanbul ignore next */
5287
5393
  request.onblocked = () => location.reload();
5288
5394
  /**
@@ -5325,7 +5431,7 @@
5325
5431
  * @param {String | number | ArrayBuffer | Date | Array<any> } key
5326
5432
  * @return {Promise<String | number | ArrayBuffer | Date | Array<any>>}
5327
5433
  */
5328
- const get = (store, key) =>
5434
+ const get$1 = (store, key) =>
5329
5435
  rtop(store.get(key));
5330
5436
 
5331
5437
  /* istanbul ignore next */
@@ -5405,7 +5511,7 @@
5405
5511
  * @param {function(IDBCursorWithValue):void|boolean} f
5406
5512
  * @return {Promise<void>}
5407
5513
  */
5408
- const iterateOnRequest = (request, f) => create$2((resolve, reject) => {
5514
+ const iterateOnRequest = (request, f) => create$5((resolve, reject) => {
5409
5515
  /* istanbul ignore next */
5410
5516
  request.onerror = reject;
5411
5517
  /**
@@ -5536,19 +5642,19 @@
5536
5642
  await iterateTests('range!=null', range);
5537
5643
 
5538
5644
  describe('idb.get');
5539
- const getV = await get(store, ['t', 1]);
5645
+ const getV = await get$1(store, ['t', 1]);
5540
5646
  assert(getV === 0);
5541
5647
  describe('idb.del');
5542
5648
  await del(store, ['t', 0]);
5543
- const getVDel = await get(store, ['t', 0]);
5649
+ const getVDel = await get$1(store, ['t', 0]);
5544
5650
  assert(getVDel === undefined);
5545
5651
  describe('idb.add');
5546
5652
  await add(store, 99, 42);
5547
- const idbVAdd = await get(store, 42);
5653
+ const idbVAdd = await get$1(store, 42);
5548
5654
  assert(idbVAdd === 99);
5549
5655
  describe('idb.addAutoKey');
5550
5656
  const key = await addAutoKey(store, 1234);
5551
- const retrieved = await get(store, key);
5657
+ const retrieved = await get$1(store, key);
5552
5658
  assert(retrieved === 1234);
5553
5659
  };
5554
5660
 
@@ -5998,7 +6104,7 @@
5998
6104
  * @param {Promise<T>} p
5999
6105
  * @return {Promise<T>}
6000
6106
  */
6001
- const failsP = p => create$2((resolve, reject) => p.then(() => reject(create$1('Promise should fail')), resolve));
6107
+ const failsP = p => create$5((resolve, reject) => p.then(() => reject(create$4('Promise should fail')), resolve));
6002
6108
 
6003
6109
  /**
6004
6110
  * @param {t.TestCase} tc
@@ -6024,7 +6130,7 @@
6024
6130
  */
6025
6131
  const testispromise = tc => {
6026
6132
  assert(isPromise(new Promise(() => {})));
6027
- assert(isPromise(create$2(() => {})));
6133
+ assert(isPromise(create$5(() => {})));
6028
6134
  const rej = reject();
6029
6135
  assert(isPromise(rej));
6030
6136
  rej.catch(() => {});
@@ -6069,12 +6175,12 @@
6069
6175
  *
6070
6176
  * @return {Queue}
6071
6177
  */
6072
- const create = () => new Queue();
6178
+ const create$3 = () => new Queue();
6073
6179
 
6074
6180
  /**
6075
6181
  * @param {Queue} queue
6076
6182
  */
6077
- const isEmpty = queue => queue.start === null;
6183
+ const isEmpty$1 = queue => queue.start === null;
6078
6184
 
6079
6185
  /**
6080
6186
  * @param {Queue} queue
@@ -6099,12 +6205,15 @@
6099
6205
  if (n !== null) {
6100
6206
  // @ts-ignore
6101
6207
  queue.start = n.next;
6208
+ if (queue.start === null) {
6209
+ queue.end = null;
6210
+ }
6102
6211
  return n
6103
6212
  }
6104
6213
  return null
6105
6214
  };
6106
6215
 
6107
- class QueueItem extends QueueNode {
6216
+ class QueueItem$1 extends QueueNode {
6108
6217
  /**
6109
6218
  * @param {number} v
6110
6219
  */
@@ -6117,51 +6226,62 @@
6117
6226
  /**
6118
6227
  * @param {t.TestCase} tc
6119
6228
  */
6120
- const testEnqueueDequeue = tc => {
6229
+ const testEnqueueDequeue$1 = tc => {
6121
6230
  const N = 30;
6122
6231
  /**
6123
6232
  * @type {queue.Queue}
6124
6233
  */
6125
- const q = create();
6126
- assert(isEmpty(q));
6234
+ const q = create$3();
6235
+ assert(isEmpty$1(q));
6127
6236
  assert(dequeue(q) === null);
6128
6237
  for (let i = 0; i < N; i++) {
6129
- enqueue(q, new QueueItem(i));
6130
- assert(!isEmpty(q));
6238
+ enqueue(q, new QueueItem$1(i));
6239
+ assert(!isEmpty$1(q));
6131
6240
  }
6132
6241
  for (let i = 0; i < N; i++) {
6133
6242
  const item = /** @type {QueueItem} */ (dequeue(q));
6134
6243
  assert(item !== null && item.v === i);
6135
6244
  }
6245
+ assert(isEmpty$1(q));
6246
+ assert(dequeue(q) === null);
6247
+ for (let i = 0; i < N; i++) {
6248
+ enqueue(q, new QueueItem$1(i));
6249
+ assert(!isEmpty$1(q));
6250
+ }
6251
+ for (let i = 0; i < N; i++) {
6252
+ const item = /** @type {QueueItem} */ (dequeue(q));
6253
+ assert(item !== null && item.v === i);
6254
+ }
6255
+ assert(isEmpty$1(q));
6136
6256
  assert(dequeue(q) === null);
6137
6257
  };
6138
6258
 
6139
6259
  var queue = /*#__PURE__*/Object.freeze({
6140
6260
  __proto__: null,
6141
- testEnqueueDequeue: testEnqueueDequeue
6261
+ testEnqueueDequeue: testEnqueueDequeue$1
6142
6262
  });
6143
6263
 
6144
6264
  /**
6145
6265
  * @param {t.TestCase} tc
6146
6266
  */
6147
6267
  const testMap = tc => {
6148
- const m = create$7();
6268
+ const m = create$a();
6149
6269
  m.set(1, 2);
6150
6270
  m.set(2, 3);
6151
- assert(map$3(m, (value, key) => value * 2 + key).reduce(add$1) === 13);
6271
+ assert(map$4(m, (value, key) => value * 2 + key).reduce(add$1) === 13);
6152
6272
  let numberOfWrites = 0;
6153
6273
  const createT = () => {
6154
6274
  numberOfWrites++;
6155
6275
  return {}
6156
6276
  };
6157
- setIfUndefined(m, 3, createT);
6158
- setIfUndefined(m, 3, createT);
6159
- setIfUndefined(m, 3, createT);
6277
+ setIfUndefined$1(m, 3, createT);
6278
+ setIfUndefined$1(m, 3, createT);
6279
+ setIfUndefined$1(m, 3, createT);
6160
6280
  compare(copy(m), m);
6161
6281
  assert(numberOfWrites === 1);
6162
6282
  };
6163
6283
 
6164
- var map = /*#__PURE__*/Object.freeze({
6284
+ var map$1 = /*#__PURE__*/Object.freeze({
6165
6285
  __proto__: null,
6166
6286
  testMap: testMap
6167
6287
  });
@@ -6196,7 +6316,7 @@
6196
6316
  set = true;
6197
6317
  });
6198
6318
  timeout$1.destroy();
6199
- await create$2(resolve => {
6319
+ await create$5(resolve => {
6200
6320
  timeout(10, resolve);
6201
6321
  });
6202
6322
  assert(set === false);
@@ -6234,7 +6354,7 @@
6234
6354
  * @param {t.TestCase} tc
6235
6355
  */
6236
6356
  const testIdleCallback = async tc => {
6237
- await create$2(resolve => {
6357
+ await create$5(resolve => {
6238
6358
  idleCallback(resolve);
6239
6359
  });
6240
6360
  };
@@ -6289,7 +6409,7 @@
6289
6409
  * @param {t.TestCase} tc
6290
6410
  */
6291
6411
  const testPair = tc => {
6292
- const ps = [create$5(1, 2), create$5(3, 4), createReversed(6, 5)];
6412
+ const ps = [create$8(1, 2), create$8(3, 4), createReversed(6, 5)];
6293
6413
  describe('Counting elements in pair list');
6294
6414
  let countLeft = 0;
6295
6415
  let countRight = 0;
@@ -6299,8 +6419,8 @@
6299
6419
  });
6300
6420
  assert(countLeft === 9);
6301
6421
  assert(countRight === 12);
6302
- assert(countLeft === map$2(ps, left => left).reduce(add$1));
6303
- assert(countRight === map$2(ps, (left, right) => right).reduce(add$1));
6422
+ assert(countLeft === map$3(ps, left => left).reduce(add$1));
6423
+ assert(countRight === map$3(ps, (left, right) => right).reduce(add$1));
6304
6424
  };
6305
6425
 
6306
6426
  var pair = /*#__PURE__*/Object.freeze({
@@ -6312,7 +6432,7 @@
6312
6432
  * @param {t.TestCase} tc
6313
6433
  */
6314
6434
  const testObject = tc => {
6315
- assert(create$4().constructor === undefined, 'object.create creates an empty object without constructor');
6435
+ assert(create$7().constructor === undefined, 'object.create creates an empty object without constructor');
6316
6436
  describe('object.equalFlat');
6317
6437
  assert(equalFlat({}, {}), 'comparing equal objects');
6318
6438
  assert(equalFlat({ x: 1 }, { x: 1 }), 'comparing equal objects');
@@ -6333,7 +6453,7 @@
6333
6453
  forEach({ x: 1, y: 3 }, (v, k) => { forEachSum += v; });
6334
6454
  assert(forEachSum === 4);
6335
6455
  describe('object.map');
6336
- assert(map$1({ x: 1, z: 5 }, (v, k) => v).reduce(add$1) === 6);
6456
+ assert(map$2({ x: 1, z: 5 }, (v, k) => v).reduce(add$1) === 6);
6337
6457
  describe('object.length');
6338
6458
  assert(length$1({}) === 0);
6339
6459
  assert(length$1({ x: 1 }) === 1);
@@ -6433,6 +6553,50 @@
6433
6553
  testAnyEncoding: testAnyEncoding
6434
6554
  });
6435
6555
 
6556
+ /**
6557
+ * Utility module to work with sets.
6558
+ *
6559
+ * @module set
6560
+ */
6561
+
6562
+ const create$2 = () => new Set();
6563
+
6564
+ /**
6565
+ * @template T
6566
+ * @param {Set<T>} set
6567
+ * @return {T}
6568
+ */
6569
+ const first = set => {
6570
+ return set.values().next().value || undefined
6571
+ };
6572
+
6573
+ /**
6574
+ * @template T
6575
+ * @param {Iterable<T>} entries
6576
+ * @return {Set<T>}
6577
+ */
6578
+ const from = entries => {
6579
+ return new Set(entries)
6580
+ };
6581
+
6582
+ /**
6583
+ * @template T
6584
+ * @param {t.TestCase} tc
6585
+ */
6586
+ const testFirst = tc => {
6587
+ const two = from(['a', 'b']);
6588
+ const one = from(['b']);
6589
+ const zero = create$2();
6590
+ assert(first(two) === 'a');
6591
+ assert(first(one) === 'b');
6592
+ assert(first(zero) === undefined);
6593
+ };
6594
+
6595
+ var set$1 = /*#__PURE__*/Object.freeze({
6596
+ __proto__: null,
6597
+ testFirst: testFirst
6598
+ });
6599
+
6436
6600
  /**
6437
6601
  * Efficient sort implementations.
6438
6602
  *
@@ -6725,7 +6889,7 @@
6725
6889
  * @return {string}
6726
6890
  */
6727
6891
  const encodeQueryParams = params =>
6728
- map$1(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
6892
+ map$2(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
6729
6893
 
6730
6894
  /**
6731
6895
  * @param {Object<string,any>} params
@@ -6889,6 +7053,459 @@
6889
7053
  testStorageModule: testStorageModule
6890
7054
  });
6891
7055
 
7056
+ class ListNode {
7057
+ constructor () {
7058
+ /**
7059
+ * @type {this|null}
7060
+ */
7061
+ this.next = null;
7062
+ /**
7063
+ * @type {this|null}
7064
+ */
7065
+ this.prev = null;
7066
+ }
7067
+ }
7068
+
7069
+ /**
7070
+ * @template {ListNode} N
7071
+ */
7072
+ class List {
7073
+ constructor () {
7074
+ /**
7075
+ * @type {N | null}
7076
+ */
7077
+ this.start = null;
7078
+ /**
7079
+ * @type {N | null}
7080
+ */
7081
+ this.end = null;
7082
+ }
7083
+ }
7084
+
7085
+ /**
7086
+ * @note The queue implementation is experimental and unfinished.
7087
+ * Don't use this in production yet.
7088
+ *
7089
+ * @template {ListNode} N
7090
+ *
7091
+ * @return {List<N>}
7092
+ */
7093
+ const create$1 = () => new List();
7094
+
7095
+ /**
7096
+ * @template {ListNode} N
7097
+ *
7098
+ * @param {List<N>} queue
7099
+ */
7100
+ const isEmpty = queue => queue.start === null;
7101
+
7102
+ /**
7103
+ * Remove a single node from the queue. Only works with Queues that operate on Doubly-linked lists of nodes.
7104
+ *
7105
+ * @template {ListNode} N
7106
+ *
7107
+ * @param {List<N>} queue
7108
+ * @param {N} node
7109
+ */
7110
+ const removeNode = (queue, node) => {
7111
+ const prev = node.prev;
7112
+ const next = node.next;
7113
+ if (prev) {
7114
+ prev.next = next;
7115
+ } else {
7116
+ queue.start = next;
7117
+ }
7118
+ if (next) {
7119
+ next.prev = prev;
7120
+ } else {
7121
+ queue.end = prev;
7122
+ }
7123
+ return node
7124
+ };
7125
+
7126
+ /**
7127
+ * @template {ListNode} N
7128
+ *
7129
+ * @param {List<N>} queue
7130
+ * @param {N| null} left
7131
+ * @param {N| null} right
7132
+ * @param {N} node
7133
+ */
7134
+ const insertBetween = (queue, left, right, node) => {
7135
+ /* istanbul ignore if */
7136
+ if (left != null && left.next !== right) {
7137
+ throw unexpectedCase()
7138
+ }
7139
+ if (left) {
7140
+ left.next = node;
7141
+ } else {
7142
+ queue.start = node;
7143
+ }
7144
+ if (right) {
7145
+ right.prev = node;
7146
+ } else {
7147
+ queue.end = node;
7148
+ }
7149
+ node.prev = left;
7150
+ node.next = right;
7151
+ };
7152
+
7153
+ /**
7154
+ * @template {ListNode} N
7155
+ *
7156
+ * @param {List<N>} queue
7157
+ * @param {N} n
7158
+ */
7159
+ const pushEnd = (queue, n) =>
7160
+ insertBetween(queue, queue.end, null, n);
7161
+
7162
+ /**
7163
+ * @template {ListNode} N
7164
+ *
7165
+ * @param {List<N>} queue
7166
+ * @param {N} n
7167
+ */
7168
+ const pushFront = (queue, n) =>
7169
+ insertBetween(queue, null, queue.start, n);
7170
+
7171
+ /**
7172
+ * @template {ListNode} N
7173
+ *
7174
+ * @param {List<N>} list
7175
+ * @return {N| null}
7176
+ */
7177
+ const popFront = list =>
7178
+ list.start ? removeNode(list, list.start) : null;
7179
+
7180
+ /**
7181
+ * @template {ListNode} N
7182
+ *
7183
+ * @param {List<N>} list
7184
+ * @return {N| null}
7185
+ */
7186
+ const popEnd = list =>
7187
+ list.end ? removeNode(list, list.end) : null;
7188
+
7189
+ /**
7190
+ * @template {ListNode} N
7191
+ * @template M
7192
+ *
7193
+ * @param {List<N>} list
7194
+ * @param {function(N):M} f
7195
+ * @return {Array<M>}
7196
+ */
7197
+ const map = (list, f) => {
7198
+ /**
7199
+ * @type {Array<M>}
7200
+ */
7201
+ const arr = [];
7202
+ let n = list.start;
7203
+ while (n) {
7204
+ arr.push(f(n));
7205
+ n = n.next;
7206
+ }
7207
+ return arr
7208
+ };
7209
+
7210
+ class QueueItem extends ListNode {
7211
+ /**
7212
+ * @param {number} v
7213
+ */
7214
+ constructor (v) {
7215
+ super();
7216
+ this.v = v;
7217
+ }
7218
+ }
7219
+
7220
+ /**
7221
+ * @param {t.TestCase} tc
7222
+ */
7223
+ const testEnqueueDequeue = tc => {
7224
+ const N = 30;
7225
+ /**
7226
+ * @type {list.List<QueueItem>}
7227
+ */
7228
+ const q = create$1();
7229
+ assert(isEmpty(q));
7230
+ assert(popFront(q) === null);
7231
+ for (let i = 0; i < N; i++) {
7232
+ pushEnd(q, new QueueItem(i));
7233
+ assert(!isEmpty(q));
7234
+ }
7235
+ for (let i = 0; i < N; i++) {
7236
+ const item = /** @type {QueueItem} */ (popFront(q));
7237
+ assert(item !== null && item.v === i);
7238
+ }
7239
+ assert(isEmpty(q));
7240
+ assert(popFront(q) === null);
7241
+ for (let i = 0; i < N; i++) {
7242
+ pushEnd(q, new QueueItem(i));
7243
+ assert(!isEmpty(q));
7244
+ }
7245
+ for (let i = 0; i < N; i++) {
7246
+ const item = /** @type {QueueItem} */ (popFront(q));
7247
+ assert(item !== null && item.v === i);
7248
+ }
7249
+ assert(isEmpty(q));
7250
+ assert(popFront(q) === null);
7251
+ };
7252
+
7253
+ /**
7254
+ * @param {t.TestCase} tc
7255
+ */
7256
+ const testSelectivePop = tc => {
7257
+ /**
7258
+ * @type {list.List<QueueItem>}
7259
+ */
7260
+ const l = create$1();
7261
+ pushFront(l, new QueueItem(1));
7262
+ pushEnd(l, new QueueItem(3));
7263
+ const middleNode = new QueueItem(2);
7264
+ insertBetween(l, l.start, l.end, middleNode);
7265
+ compare(map(l, n => n.v), [1, 2, 3]);
7266
+ assert(removeNode(l, middleNode) === middleNode);
7267
+ compare(/** @type {QueueItem} */ (popEnd(l)).v, 3);
7268
+ compare(/** @type {QueueItem} */ (popEnd(l)).v, 1);
7269
+ compare(popEnd(l), null);
7270
+ assert(l.start === null);
7271
+ assert(l.end === null);
7272
+ };
7273
+
7274
+ var list = /*#__PURE__*/Object.freeze({
7275
+ __proto__: null,
7276
+ testEnqueueDequeue: testEnqueueDequeue,
7277
+ testSelectivePop: testSelectivePop
7278
+ });
7279
+
7280
+ /**
7281
+ * @template K, V
7282
+ *
7283
+ * @implements {list.ListNode}
7284
+ */
7285
+ class Entry {
7286
+ /**
7287
+ * @param {K} key
7288
+ * @param {V | Promise<V>} val
7289
+ */
7290
+ constructor (key, val) {
7291
+ /**
7292
+ * @type {this | null}
7293
+ */
7294
+ this.prev = null;
7295
+ /**
7296
+ * @type {this | null}
7297
+ */
7298
+ this.next = null;
7299
+ this.created = getUnixTime();
7300
+ this.val = val;
7301
+ this.key = key;
7302
+ }
7303
+ }
7304
+
7305
+ /**
7306
+ * @template K, V
7307
+ */
7308
+ class Cache {
7309
+ /**
7310
+ * @param {number} timeout
7311
+ */
7312
+ constructor (timeout) {
7313
+ this.timeout = timeout;
7314
+ /**
7315
+ * @type list.List<Entry<K, V>>
7316
+ */
7317
+ this._q = create$1();
7318
+ /**
7319
+ * @type {Map<K, Entry<K, V>>}
7320
+ */
7321
+ this._map = create$a();
7322
+ }
7323
+ }
7324
+
7325
+ /**
7326
+ * @template K, V
7327
+ *
7328
+ * @param {Cache<K, V>} cache
7329
+ * @return {number} Returns the current timestamp
7330
+ */
7331
+ const removeStale = cache => {
7332
+ const now = getUnixTime();
7333
+ const q = cache._q;
7334
+ while (q.start && now - q.start.created > cache.timeout) {
7335
+ cache._map.delete(q.start.key);
7336
+ popFront(q);
7337
+ }
7338
+ return now
7339
+ };
7340
+
7341
+ /**
7342
+ * @template K, V
7343
+ *
7344
+ * @param {Cache<K, V>} cache
7345
+ * @param {K} key
7346
+ * @param {V} value
7347
+ */
7348
+ const set = (cache, key, value) => {
7349
+ const now = removeStale(cache);
7350
+ const q = cache._q;
7351
+ const n = cache._map.get(key);
7352
+ if (n) {
7353
+ removeNode(q, n);
7354
+ pushEnd(q, n);
7355
+ n.created = now;
7356
+ n.val = value;
7357
+ } else {
7358
+ const node = new Entry(key, value);
7359
+ pushEnd(q, node);
7360
+ cache._map.set(key, node);
7361
+ }
7362
+ };
7363
+
7364
+ /**
7365
+ * @template K, V
7366
+ *
7367
+ * @param {Cache<K, V>} cache
7368
+ * @param {K} key
7369
+ * @return {Entry<K, V> | undefined}
7370
+ */
7371
+ const getNode = (cache, key) => {
7372
+ const now = removeStale(cache);
7373
+ const q = cache._q;
7374
+ const n = cache._map.get(key);
7375
+ if (n) {
7376
+ removeNode(q, n);
7377
+ pushEnd(q, n);
7378
+ n.created = now;
7379
+ return n
7380
+ }
7381
+ };
7382
+
7383
+ /**
7384
+ * @template K, V
7385
+ *
7386
+ * @param {Cache<K, V>} cache
7387
+ * @param {K} key
7388
+ * @return {V | undefined}
7389
+ */
7390
+ const get = (cache, key) => {
7391
+ const n = getNode(cache, key);
7392
+ return n && !(n.val instanceof Promise) ? n.val : undefined
7393
+ };
7394
+
7395
+ /**
7396
+ * Works well in conjunktion with setIfUndefined which has an async init function.
7397
+ * Using getAsync & setIfUndefined ensures that the init function is only called once.
7398
+ *
7399
+ * @template K, V
7400
+ *
7401
+ * @param {Cache<K, V>} cache
7402
+ * @param {K} key
7403
+ * @return {V | Promise<V> | undefined}
7404
+ */
7405
+ const getAsync = (cache, key) => {
7406
+ const n = getNode(cache, key);
7407
+ return n ? n.val : undefined
7408
+ };
7409
+
7410
+ /**
7411
+ * @template K, V
7412
+ *
7413
+ * @param {Cache<K, V>} cache
7414
+ * @param {K} key
7415
+ * @param {function():Promise<V>} init
7416
+ * @return {Promise<V> | V}
7417
+ */
7418
+ const setIfUndefined = (cache, key, init) => {
7419
+ const now = removeStale(cache);
7420
+ const q = cache._q;
7421
+ const n = cache._map.get(key);
7422
+ if (n) {
7423
+ removeNode(q, n);
7424
+ pushEnd(q, n);
7425
+ n.created = now;
7426
+ return n.val
7427
+ } else {
7428
+ const p = init();
7429
+ const node = new Entry(key, p);
7430
+ pushEnd(q, node);
7431
+ cache._map.set(key, node);
7432
+ p.then(v => {
7433
+ if (p === node.val) {
7434
+ node.val = v;
7435
+ }
7436
+ });
7437
+ return p
7438
+ }
7439
+ };
7440
+
7441
+ /**
7442
+ * @param {number} timeout
7443
+ */
7444
+ const create = timeout => new Cache(timeout);
7445
+
7446
+ /**
7447
+ * @param {t.TestCase} tc
7448
+ */
7449
+ const testCache = async tc => {
7450
+ /**
7451
+ * @type {cache.Cache<string, string>}
7452
+ */
7453
+ const c = create(50);
7454
+ set(c, 'a', '1');
7455
+ assert(get(c, 'a') === '1');
7456
+ assert(await getAsync(c, 'a') === '1');
7457
+ const p = setIfUndefined(c, 'b', () => resolveWith('2'));
7458
+ const q = setIfUndefined(c, 'b', () => resolveWith('3'));
7459
+ assert(p === q);
7460
+ assert(get(c, 'b') == null);
7461
+ assert(getAsync(c, 'b') === p);
7462
+ assert(await p === '2');
7463
+ assert(get(c, 'b') === '2');
7464
+ assert(getAsync(c, 'b') === '2');
7465
+
7466
+ await wait(5); // keys shouldn't be timed out yet
7467
+ assert(get(c, 'a') === '1');
7468
+ assert(get(c, 'b') === '2');
7469
+
7470
+ /**
7471
+ * @type {any}
7472
+ */
7473
+ const m = c._map;
7474
+ const aTimestamp1 = m.get('a').created;
7475
+ const bTimestamp1 = m.get('b').created;
7476
+
7477
+ // write new values and check later if the creation-timestamp was updated
7478
+ set(c, 'a', '11');
7479
+ await setIfUndefined(c, 'b', () => resolveWith('22')); // this shouldn't override, but update the timestamp
7480
+
7481
+ await wait(5); // keys should be updated and not timed out. Hence the creation time should be updated
7482
+ assert(get(c, 'a') === '11');
7483
+ assert(get(c, 'b') === '2');
7484
+ // timestamps should be updated
7485
+ assert(aTimestamp1 !== m.get('a').created);
7486
+ assert(bTimestamp1 !== m.get('b').created);
7487
+
7488
+ await wait(60); // now the keys should be timed-out
7489
+
7490
+ assert(get(c, 'a') == null);
7491
+ assert(getAsync(c, 'b') == null);
7492
+
7493
+ assert(c._map.size === 0);
7494
+ assert(c._q.start === null && c._q.end === null);
7495
+
7496
+ // test edge case of setIfUndefined
7497
+ const xp = setIfUndefined(c, 'a', () => resolve('x'));
7498
+ set(c, 'a', 'y');
7499
+ await xp;
7500
+ // we override the Entry.val property in cache when p resolves. However, we must prevent that when the value is overriden before p is resolved.
7501
+ assert(get(c, 'a') === 'y');
7502
+ };
7503
+
7504
+ var cache = /*#__PURE__*/Object.freeze({
7505
+ __proto__: null,
7506
+ testCache: testCache
7507
+ });
7508
+
6892
7509
  /* istanbul ignore if */
6893
7510
  if (isBrowser) {
6894
7511
  createVConsole(document.body);
@@ -6908,7 +7525,7 @@
6908
7525
  random,
6909
7526
  promise,
6910
7527
  queue,
6911
- map,
7528
+ map: map$1,
6912
7529
  eventloop,
6913
7530
  time,
6914
7531
  pair,
@@ -6916,11 +7533,14 @@
6916
7533
  math,
6917
7534
  number,
6918
7535
  buffer,
7536
+ set: set$1,
6919
7537
  sort,
6920
7538
  url,
6921
7539
  metric,
6922
7540
  func,
6923
- storage
7541
+ storage,
7542
+ list,
7543
+ cache
6924
7544
  }).then(success => {
6925
7545
  /* istanbul ignore next */
6926
7546
  if (isNode) {