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.cjs CHANGED
@@ -16,7 +16,7 @@ var isomorphic_js = require('isomorphic.js');
16
16
  *
17
17
  * @function
18
18
  */
19
- const create$7 = () => new Map();
19
+ const create$a = () => new Map();
20
20
 
21
21
  /**
22
22
  * Copy a Map object into a fresh Map object.
@@ -27,7 +27,7 @@ const create$7 = () => new Map();
27
27
  * @return {Map<X,Y>}
28
28
  */
29
29
  const copy = m => {
30
- const r = create$7();
30
+ const r = create$a();
31
31
  m.forEach((v, k) => { r.set(k, v); });
32
32
  return r
33
33
  };
@@ -47,7 +47,7 @@ const copy = m => {
47
47
  * @param {function():T} createT
48
48
  * @return {T}
49
49
  */
50
- const setIfUndefined = (map, key, createT) => {
50
+ const setIfUndefined$1 = (map, key, createT) => {
51
51
  let set = map.get(key);
52
52
  if (set === undefined) {
53
53
  map.set(key, set = createT());
@@ -66,7 +66,7 @@ const setIfUndefined = (map, key, createT) => {
66
66
  * @param {function(V,K):R} f
67
67
  * @return {Array<R>}
68
68
  */
69
- const map$3 = (m, f) => {
69
+ const map$4 = (m, f) => {
70
70
  const res = [];
71
71
  for (const [key, value] of m) {
72
72
  res.push(f(value, key));
@@ -189,6 +189,14 @@ const _decodeUtf8Native = buf => /** @type {TextDecoder} */ (utf8TextDecoder).de
189
189
  /* istanbul ignore next */
190
190
  const decodeUtf8 = utf8TextDecoder ? _decodeUtf8Native : _decodeUtf8Polyfill;
191
191
 
192
+ /**
193
+ * @param {string} str The initial string
194
+ * @param {number} index Starting position
195
+ * @param {number} remove Number of characters to remove
196
+ * @param {string} insert New content to insert
197
+ */
198
+ const splice = (str, index, remove, insert = '') => str.slice(0, index) + insert + str.slice(index + remove);
199
+
192
200
  /**
193
201
  * Often used conditions.
194
202
  *
@@ -289,7 +297,7 @@ let params;
289
297
  const computeParams = () => {
290
298
  if (params === undefined) {
291
299
  if (isNode) {
292
- params = create$7();
300
+ params = create$a();
293
301
  const pargs = process.argv;
294
302
  let currParamName = null;
295
303
  /* istanbul ignore next */
@@ -312,7 +320,7 @@ const computeParams = () => {
312
320
  }
313
321
  // in ReactNative for example this would not be true (unless connected to the Remote Debugger)
314
322
  } else if (typeof location === 'object') {
315
- params = create$7()
323
+ params = create$a()
316
324
  // eslint-disable-next-line no-undef
317
325
  ;(location.search || '?').slice(1).split('&').forEach(kv => {
318
326
  if (kv.length !== 0) {
@@ -322,7 +330,7 @@ const computeParams = () => {
322
330
  }
323
331
  });
324
332
  } else {
325
- params = create$7();
333
+ params = create$a();
326
334
  }
327
335
  }
328
336
  return params
@@ -372,7 +380,7 @@ const production = hasConf('production');
372
380
  *
373
381
  * @return {Symbol}
374
382
  */
375
- const create$6 = Symbol;
383
+ const create$9 = Symbol;
376
384
 
377
385
  /**
378
386
  * Working with value pairs.
@@ -400,7 +408,7 @@ class Pair {
400
408
  * @param {R} right
401
409
  * @return {Pair<L,R>}
402
410
  */
403
- const create$5 = (left, right) => new Pair(left, right);
411
+ const create$8 = (left, right) => new Pair(left, right);
404
412
 
405
413
  /**
406
414
  * @template L,R
@@ -423,7 +431,7 @@ const forEach$1 = (arr, f) => arr.forEach(p => f(p.left, p.right));
423
431
  * @param {function(L, R):X} f
424
432
  * @return {Array<X>}
425
433
  */
426
- const map$2 = (arr, f) => arr.map(p => f(p.left, p.right));
434
+ const map$3 = (arr, f) => arr.map(p => f(p.left, p.right));
427
435
 
428
436
  /* eslint-env browser */
429
437
 
@@ -542,7 +550,7 @@ const text = createTextNode;
542
550
  * @return {string}
543
551
  */
544
552
  /* istanbul ignore next */
545
- const mapToStyleString = m => map$3(m, (value, key) => `${key}:${value};`).join('');
553
+ const mapToStyleString = m => map$4(m, (value, key) => `${key}:${value};`).join('');
546
554
 
547
555
  /**
548
556
  * @param {Node} parent
@@ -864,7 +872,7 @@ const flatten = arr => arr.reduce((acc, val) => acc.concat(val), []);
864
872
  /**
865
873
  * @return {Object<string,any>} obj
866
874
  */
867
- const create$4 = () => Object.create(null);
875
+ const create$7 = () => Object.create(null);
868
876
 
869
877
  /**
870
878
  * Object.assign
@@ -892,7 +900,7 @@ const forEach = (obj, f) => {
892
900
  * @param {function(any,string):R} f
893
901
  * @return {Array<R>}
894
902
  */
895
- const map$1 = (obj, f) => {
903
+ const map$2 = (obj, f) => {
896
904
  const results = [];
897
905
  for (const key in obj) {
898
906
  results.push(f(obj[key], key));
@@ -1059,29 +1067,29 @@ const equalityDeep = (a, b) => {
1059
1067
  * @module logging
1060
1068
  */
1061
1069
 
1062
- const BOLD = create$6();
1063
- const UNBOLD = create$6();
1064
- const BLUE = create$6();
1065
- const GREY = create$6();
1066
- const GREEN = create$6();
1067
- const RED = create$6();
1068
- const PURPLE = create$6();
1069
- const ORANGE = create$6();
1070
- const UNCOLOR = create$6();
1070
+ const BOLD = create$9();
1071
+ const UNBOLD = create$9();
1072
+ const BLUE = create$9();
1073
+ const GREY = create$9();
1074
+ const GREEN = create$9();
1075
+ const RED = create$9();
1076
+ const PURPLE = create$9();
1077
+ const ORANGE = create$9();
1078
+ const UNCOLOR = create$9();
1071
1079
 
1072
1080
  /**
1073
1081
  * @type {Object<Symbol,pair.Pair<string,string>>}
1074
1082
  */
1075
1083
  const _browserStyleMap = {
1076
- [BOLD]: create$5('font-weight', 'bold'),
1077
- [UNBOLD]: create$5('font-weight', 'normal'),
1078
- [BLUE]: create$5('color', 'blue'),
1079
- [GREEN]: create$5('color', 'green'),
1080
- [GREY]: create$5('color', 'grey'),
1081
- [RED]: create$5('color', 'red'),
1082
- [PURPLE]: create$5('color', 'purple'),
1083
- [ORANGE]: create$5('color', 'orange'), // not well supported in chrome when debugging node with inspector - TODO: deprecate
1084
- [UNCOLOR]: create$5('color', 'black')
1084
+ [BOLD]: create$8('font-weight', 'bold'),
1085
+ [UNBOLD]: create$8('font-weight', 'normal'),
1086
+ [BLUE]: create$8('color', 'blue'),
1087
+ [GREEN]: create$8('color', 'green'),
1088
+ [GREY]: create$8('color', 'grey'),
1089
+ [RED]: create$8('color', 'red'),
1090
+ [PURPLE]: create$8('color', 'purple'),
1091
+ [ORANGE]: create$8('color', 'orange'), // not well supported in chrome when debugging node with inspector - TODO: deprecate
1092
+ [UNCOLOR]: create$8('color', 'black')
1085
1093
  };
1086
1094
 
1087
1095
  const _nodeStyleMap = {
@@ -1104,7 +1112,7 @@ const _nodeStyleMap = {
1104
1112
  const computeBrowserLoggingArgs = args => {
1105
1113
  const strBuilder = [];
1106
1114
  const styles = [];
1107
- const currentStyle = create$7();
1115
+ const currentStyle = create$a();
1108
1116
  /**
1109
1117
  * @type {Array<string|Object|number>}
1110
1118
  */
@@ -1282,7 +1290,7 @@ const _computeLineSpans = args => {
1282
1290
  } else {
1283
1291
  if (arg.constructor === String || arg.constructor === Number) {
1284
1292
  // @ts-ignore
1285
- const span = element('span', [create$5('style', mapToStyleString(currentStyle))], [text(arg)]);
1293
+ const span = element('span', [create$8('style', mapToStyleString(currentStyle))], [text(arg)]);
1286
1294
  if (span.innerHTML === '') {
1287
1295
  span.innerHTML = '&nbsp;';
1288
1296
  }
@@ -1328,10 +1336,10 @@ class VConsole {
1328
1336
  */
1329
1337
  group (args, collapsed = false) {
1330
1338
  enqueue$1(() => {
1331
- const triangleDown = element('span', [create$5('hidden', collapsed), create$5('style', 'color:grey;font-size:120%;')], [text('▼')]);
1332
- const triangleRight = element('span', [create$5('hidden', !collapsed), create$5('style', 'color:grey;font-size:125%;')], [text('▶')]);
1333
- const content = element('div', [create$5('style', `${lineStyle};padding-left:${this.depth * 10}px`)], [triangleDown, triangleRight, text(' ')].concat(_computeLineSpans(args)));
1334
- const nextContainer = element('div', [create$5('hidden', collapsed)]);
1339
+ const triangleDown = element('span', [create$8('hidden', collapsed), create$8('style', 'color:grey;font-size:120%;')], [text('▼')]);
1340
+ const triangleRight = element('span', [create$8('hidden', !collapsed), create$8('style', 'color:grey;font-size:125%;')], [text('▶')]);
1341
+ const content = element('div', [create$8('style', `${lineStyle};padding-left:${this.depth * 10}px`)], [triangleDown, triangleRight, text(' ')].concat(_computeLineSpans(args)));
1342
+ const nextContainer = element('div', [create$8('hidden', collapsed)]);
1335
1343
  const nextLine = element('div', [], [content, nextContainer]);
1336
1344
  append(this.ccontainer, [nextLine]);
1337
1345
  this.ccontainer = nextContainer;
@@ -1367,7 +1375,7 @@ class VConsole {
1367
1375
  */
1368
1376
  print (args) {
1369
1377
  enqueue$1(() => {
1370
- append(this.ccontainer, [element('div', [create$5('style', `${lineStyle};padding-left:${this.depth * 10}px`)], _computeLineSpans(args))]);
1378
+ append(this.ccontainer, [element('div', [create$8('style', `${lineStyle};padding-left:${this.depth * 10}px`)], _computeLineSpans(args))]);
1371
1379
  });
1372
1380
  }
1373
1381
 
@@ -1384,7 +1392,7 @@ class VConsole {
1384
1392
  */
1385
1393
  printImg (url, height) {
1386
1394
  enqueue$1(() => {
1387
- append(this.ccontainer, [element('img', [create$5('src', url), create$5('height', `${round(height * 1.5)}px`)])]);
1395
+ append(this.ccontainer, [element('img', [create$8('src', url), create$8('height', `${round(height * 1.5)}px`)])]);
1388
1396
  });
1389
1397
  }
1390
1398
 
@@ -1454,11 +1462,8 @@ const simpleDiffString = (a, b) => {
1454
1462
  while (left < a.length && left < b.length && a[left] === b[left]) {
1455
1463
  left++;
1456
1464
  }
1457
- if (left !== a.length || left !== b.length) {
1458
- // Only check right if a !== b
1459
- while (right + left < a.length && right + left < b.length && a[a.length - right - 1] === b[b.length - right - 1]) {
1460
- right++;
1461
- }
1465
+ while (right + left < a.length && right + left < b.length && a[a.length - right - 1] === b[b.length - right - 1]) {
1466
+ right++;
1462
1467
  }
1463
1468
  return {
1464
1469
  index: left,
@@ -1488,11 +1493,51 @@ const simpleDiffArray = (a, b, compare = equalityStrict) => {
1488
1493
  while (left < a.length && left < b.length && compare(a[left], b[left])) {
1489
1494
  left++;
1490
1495
  }
1491
- if (left !== a.length || left !== b.length) {
1492
- // Only check right if a !== b
1493
- while (right + left < a.length && right + left < b.length && compare(a[a.length - right - 1], b[b.length - right - 1])) {
1494
- right++;
1495
- }
1496
+ while (right + left < a.length && right + left < b.length && compare(a[a.length - right - 1], b[b.length - right - 1])) {
1497
+ right++;
1498
+ }
1499
+ return {
1500
+ index: left,
1501
+ remove: a.length - left - right,
1502
+ insert: b.slice(left, b.length - right)
1503
+ }
1504
+ };
1505
+
1506
+ /**
1507
+ * Diff text and try to diff at the current cursor position.
1508
+ *
1509
+ * @param {string} a
1510
+ * @param {string} b
1511
+ * @param {number} cursor This should refer to the current left cursor-range position
1512
+ */
1513
+ const simpleDiffStringWithCursor = (a, b, cursor) => {
1514
+ let left = 0; // number of same characters counting from left
1515
+ let right = 0; // number of same characters counting from right
1516
+ // Iterate left to the right until we find a changed character
1517
+ // First iteration considers the current cursor position
1518
+ while (
1519
+ left < a.length &&
1520
+ left < b.length &&
1521
+ a[left] === b[left] &&
1522
+ left < cursor
1523
+ ) {
1524
+ left++;
1525
+ }
1526
+ // Iterate right to the left until we find a changed character
1527
+ while (
1528
+ right + left < a.length &&
1529
+ right + left < b.length &&
1530
+ a[a.length - right - 1] === b[b.length - right - 1]
1531
+ ) {
1532
+ right++;
1533
+ }
1534
+ // Try to iterate left further to the right without caring about the current cursor position
1535
+ while (
1536
+ right + left < a.length &&
1537
+ right + left < b.length &&
1538
+ a[left] === b[left]
1539
+ ) {
1540
+ left++;
1496
1541
  }
1497
1542
  return {
1498
1543
  index: left,
@@ -1960,7 +2005,7 @@ const write = (encoder, num) => {
1960
2005
  * @param {number} pos Position to which to write data
1961
2006
  * @param {number} num Unsigned 8-bit integer
1962
2007
  */
1963
- const set = (encoder, pos, num) => {
2008
+ const set$2 = (encoder, pos, num) => {
1964
2009
  let buffer = null;
1965
2010
  // iterate all buffers and adjust position
1966
2011
  for (let i = 0; i < encoder.bufs.length && buffer === null; i++) {
@@ -1995,7 +2040,7 @@ const writeUint8 = write;
1995
2040
  * @param {number} pos The location where the data will be written.
1996
2041
  * @param {number} num The number that is to be encoded.
1997
2042
  */
1998
- const setUint8 = set;
2043
+ const setUint8 = set$2;
1999
2044
 
2000
2045
  /**
2001
2046
  * Write two bytes as an unsigned integer.
@@ -2017,8 +2062,8 @@ const writeUint16 = (encoder, num) => {
2017
2062
  * @param {number} num The number that is to be encoded.
2018
2063
  */
2019
2064
  const setUint16 = (encoder, pos, num) => {
2020
- set(encoder, pos, num & BITS8);
2021
- set(encoder, pos + 1, (num >>> 8) & BITS8);
2065
+ set$2(encoder, pos, num & BITS8);
2066
+ set$2(encoder, pos + 1, (num >>> 8) & BITS8);
2022
2067
  };
2023
2068
 
2024
2069
  /**
@@ -2059,7 +2104,7 @@ const writeUint32BigEndian = (encoder, num) => {
2059
2104
  */
2060
2105
  const setUint32 = (encoder, pos, num) => {
2061
2106
  for (let i = 0; i < 4; i++) {
2062
- set(encoder, pos + i, num & BITS8);
2107
+ set$2(encoder, pos + i, num & BITS8);
2063
2108
  num >>>= 8;
2064
2109
  }
2065
2110
  };
@@ -3362,7 +3407,7 @@ const DefaultPRNG = Xoroshiro128plus;
3362
3407
  * @param {number} seed A positive 32bit integer. Do not use negative numbers.
3363
3408
  * @return {PRNG}
3364
3409
  */
3365
- const create$3 = seed => new DefaultPRNG(seed);
3410
+ const create$6 = seed => new DefaultPRNG(seed);
3366
3411
 
3367
3412
  /**
3368
3413
  * Generates a single random bool.
@@ -3552,7 +3597,7 @@ const average = arr => arr.reduce(add$1, 0) / arr.length;
3552
3597
  * @param {function(PromiseResolve<T>,function(Error):void):any} f
3553
3598
  * @return {Promise<T>}
3554
3599
  */
3555
- const create$2 = f => /** @type {Promise<T>} */ (new Promise(f));
3600
+ const create$5 = f => /** @type {Promise<T>} */ (new Promise(f));
3556
3601
 
3557
3602
  /**
3558
3603
  * @param {function(function():void,function(Error):void):void} f
@@ -3581,6 +3626,13 @@ const reject = reason => Promise.reject(reason);
3581
3626
  */
3582
3627
  const resolve = res => Promise.resolve(res);
3583
3628
 
3629
+ /**
3630
+ * @template T
3631
+ * @param {T} res
3632
+ * @return {Promise<T>}
3633
+ */
3634
+ const resolveWith = res => Promise.resolve(res);
3635
+
3584
3636
  /**
3585
3637
  * @todo Next version, reorder parameters: check, [timeout, [intervalResolution]]
3586
3638
  *
@@ -3589,7 +3641,7 @@ const resolve = res => Promise.resolve(res);
3589
3641
  * @param {number} [intervalResolution]
3590
3642
  * @return {Promise<void>}
3591
3643
  */
3592
- const until = (timeout, check, intervalResolution = 10) => create$2((resolve, reject) => {
3644
+ const until = (timeout, check, intervalResolution = 10) => create$5((resolve, reject) => {
3593
3645
  const startTime = getUnixTime();
3594
3646
  const hasTimeout = timeout > 0;
3595
3647
  const untilInterval = () => {
@@ -3611,7 +3663,7 @@ const until = (timeout, check, intervalResolution = 10) => create$2((resolve, re
3611
3663
  * @param {number} timeout
3612
3664
  * @return {Promise<undefined>}
3613
3665
  */
3614
- const wait = timeout => create$2((resolve, reject) => setTimeout(resolve, timeout));
3666
+ const wait = timeout => create$5((resolve, reject) => setTimeout(resolve, timeout));
3615
3667
 
3616
3668
  /**
3617
3669
  * Checks if an object is a promise using ducktyping.
@@ -3718,7 +3770,7 @@ class TestCase {
3718
3770
  get prng () {
3719
3771
  /* istanbul ignore else */
3720
3772
  if (this._prng === null) {
3721
- this._prng = create$3(this.seed);
3773
+ this._prng = create$6(this.seed);
3722
3774
  }
3723
3775
  return this._prng
3724
3776
  }
@@ -4145,7 +4197,7 @@ const fails = f => {
4145
4197
  * @param {Object<string, Object<string, function(TestCase):void|Promise<any>>>} tests
4146
4198
  */
4147
4199
  const runTests = async tests => {
4148
- const numberOfTests = map$1(tests, mod => map$1(mod, f => /* istanbul ignore next */ f ? 1 : 0).reduce(add$1, 0)).reduce(add$1, 0);
4200
+ const numberOfTests = map$2(tests, mod => map$2(mod, f => /* istanbul ignore next */ f ? 1 : 0).reduce(add$1, 0)).reduce(add$1, 0);
4149
4201
  let successfulTests = 0;
4150
4202
  let testnumber = 0;
4151
4203
  const start = isomorphic_js.performance.now();
@@ -4311,12 +4363,22 @@ const testBomEncodingDecoding = tc => {
4311
4363
  }
4312
4364
  };
4313
4365
 
4366
+ /**
4367
+ * @param {t.TestCase} tc
4368
+ */
4369
+ const testSplice = tc => {
4370
+ const initial = 'xyz';
4371
+ compareStrings(splice(initial, 0, 2), 'z');
4372
+ compareStrings(splice(initial, 0, 2, 'u'), 'uz');
4373
+ };
4374
+
4314
4375
  var string = /*#__PURE__*/Object.freeze({
4315
4376
  __proto__: null,
4316
4377
  testLowercaseTransformation: testLowercaseTransformation,
4317
4378
  testRepeatStringUtf8Encoding: testRepeatStringUtf8Encoding,
4318
4379
  testRepeatStringUtf8Decoding: testRepeatStringUtf8Decoding,
4319
- testBomEncodingDecoding: testBomEncodingDecoding
4380
+ testBomEncodingDecoding: testBomEncodingDecoding,
4381
+ testSplice: testSplice
4320
4382
  });
4321
4383
 
4322
4384
  /* global BigInt */
@@ -5026,6 +5088,7 @@ var encoding = /*#__PURE__*/Object.freeze({
5026
5088
  function runDiffTest (a, b, expected) {
5027
5089
  const result = simpleDiffString(a, b);
5028
5090
  compare(result, expected);
5091
+ compare(result, simpleDiffStringWithCursor(a, b, a.length)); // check that the withCursor approach returns the same result
5029
5092
  const arrResult = simpleDiffArray(a.split(''), b.split(''));
5030
5093
  compare(arrResult, assign({}, result, { insert: result.insert.split('') }));
5031
5094
  }
@@ -5051,10 +5114,43 @@ const testRepeatDiffing = tc => {
5051
5114
  const a = word(tc.prng);
5052
5115
  const b = word(tc.prng);
5053
5116
  const change = simpleDiffString(a, b);
5054
- const recomposed = `${a.slice(0, change.index)}${change.insert}${a.slice(change.index + change.remove)}`;
5117
+ const recomposed = splice(a, change.index, change.remove, change.insert);
5055
5118
  compareStrings(recomposed, b);
5056
5119
  };
5057
5120
 
5121
+ /**
5122
+ * @param {t.TestCase} tc
5123
+ */
5124
+ const testSimpleDiffWithCursor = tc => {
5125
+ const initial = 'Hello WorldHello World';
5126
+ const expected = 'Hello World';
5127
+ {
5128
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 0); // should delete the first hello world
5129
+ compare(change, { insert: '', remove: 11, index: 0 });
5130
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5131
+ compareStrings(expected, recomposed);
5132
+ }
5133
+ {
5134
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 11); // should delete the second hello world
5135
+ compare(change, { insert: '', remove: 11, index: 11 });
5136
+ const recomposedSecond = splice(initial, change.index, change.remove, change.insert);
5137
+ compareStrings(recomposedSecond, expected);
5138
+ }
5139
+ {
5140
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 5); // should delete in the midst of Hello World
5141
+ compare(change, { insert: '', remove: 11, index: 5 });
5142
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5143
+ compareStrings(expected, recomposed);
5144
+ }
5145
+ {
5146
+ const initial = 'Hello my World';
5147
+ const change = simpleDiffStringWithCursor(initial, 'Hello World', 0); // Should delete after the current cursor position
5148
+ compare(change, { insert: '', remove: 3, index: 5 });
5149
+ const recomposed = splice(initial, change.index, change.remove, change.insert);
5150
+ compareStrings(expected, recomposed);
5151
+ }
5152
+ };
5153
+
5058
5154
  /**
5059
5155
  * @param {t.TestCase} tc
5060
5156
  */
@@ -5070,6 +5166,7 @@ var diff = /*#__PURE__*/Object.freeze({
5070
5166
  __proto__: null,
5071
5167
  testDiffing: testDiffing,
5072
5168
  testRepeatDiffing: testRepeatDiffing,
5169
+ testSimpleDiffWithCursor: testSimpleDiffWithCursor,
5073
5170
  testArrayDiffing: testArrayDiffing
5074
5171
  });
5075
5172
 
@@ -5082,7 +5179,7 @@ const testComparing = tc => {
5082
5179
  compare([1, 2], [1, 2], 'simple compare (array)');
5083
5180
  compare({ a: [1, 2] }, { a: [1, 2] }, 'simple compare nested');
5084
5181
  compare(new Set(['3', 1234]), new Set(['3', 1234]), 'compare Sets');
5085
- const map1 = create$7();
5182
+ const map1 = create$a();
5086
5183
  map1.set(1, 2);
5087
5184
  map1.set('x', {});
5088
5185
  map1.set(98, 'tst');
@@ -5186,7 +5283,7 @@ const testSkipping = () => {
5186
5283
  };
5187
5284
 
5188
5285
  const testAsync = async () => {
5189
- await measureTimeAsync('time', () => create$2(r => setTimeout(r)));
5286
+ await measureTimeAsync('time', () => create$5(r => setTimeout(r)));
5190
5287
  await groupAsync('some description', () => wait(1));
5191
5288
  };
5192
5289
 
@@ -5219,7 +5316,16 @@ var testing = /*#__PURE__*/Object.freeze({
5219
5316
  * @param {string} s
5220
5317
  * @return {Error}
5221
5318
  */
5222
- const create$1 = s => new Error(s);
5319
+ const create$4 = s => new Error(s);
5320
+
5321
+ /* istanbul ignore next */
5322
+ /**
5323
+ * @throws {Error}
5324
+ * @return {never}
5325
+ */
5326
+ const unexpectedCase = () => {
5327
+ throw create$4('Unexpected case')
5328
+ };
5223
5329
 
5224
5330
  /* eslint-env browser */
5225
5331
 
@@ -5230,7 +5336,7 @@ const create$1 = s => new Error(s);
5230
5336
  * @param {IDBRequest} request
5231
5337
  * @return {Promise<any>}
5232
5338
  */
5233
- const rtop = request => create$2((resolve, reject) => {
5339
+ const rtop = request => create$5((resolve, reject) => {
5234
5340
  /* istanbul ignore next */
5235
5341
  // @ts-ignore
5236
5342
  request.onerror = event => reject(new Error(event.target.error));
@@ -5247,7 +5353,7 @@ const rtop = request => create$2((resolve, reject) => {
5247
5353
  * @param {function(IDBDatabase):any} initDB Called when the database is first created
5248
5354
  * @return {Promise<IDBDatabase>}
5249
5355
  */
5250
- const openDB = (name, initDB) => create$2((resolve, reject) => {
5356
+ const openDB = (name, initDB) => create$5((resolve, reject) => {
5251
5357
  const request = indexedDB.open(name);
5252
5358
  /**
5253
5359
  * @param {any} event
@@ -5257,7 +5363,7 @@ const openDB = (name, initDB) => create$2((resolve, reject) => {
5257
5363
  /**
5258
5364
  * @param {any} event
5259
5365
  */
5260
- request.onerror = event => reject(create$1(event.target.error));
5366
+ request.onerror = event => reject(create$4(event.target.error));
5261
5367
  /* istanbul ignore next */
5262
5368
  request.onblocked = () => location.reload();
5263
5369
  /**
@@ -5300,7 +5406,7 @@ const createStores = (db, definitions) => definitions.forEach(d =>
5300
5406
  * @param {String | number | ArrayBuffer | Date | Array<any> } key
5301
5407
  * @return {Promise<String | number | ArrayBuffer | Date | Array<any>>}
5302
5408
  */
5303
- const get = (store, key) =>
5409
+ const get$1 = (store, key) =>
5304
5410
  rtop(store.get(key));
5305
5411
 
5306
5412
  /* istanbul ignore next */
@@ -5380,7 +5486,7 @@ const getAllKeysValues = (store, range) =>
5380
5486
  * @param {function(IDBCursorWithValue):void|boolean} f
5381
5487
  * @return {Promise<void>}
5382
5488
  */
5383
- const iterateOnRequest = (request, f) => create$2((resolve, reject) => {
5489
+ const iterateOnRequest = (request, f) => create$5((resolve, reject) => {
5384
5490
  /* istanbul ignore next */
5385
5491
  request.onerror = reject;
5386
5492
  /**
@@ -5511,19 +5617,19 @@ const testRetrieveElements = async () => {
5511
5617
  await iterateTests('range!=null', range);
5512
5618
 
5513
5619
  describe('idb.get');
5514
- const getV = await get(store, ['t', 1]);
5620
+ const getV = await get$1(store, ['t', 1]);
5515
5621
  assert(getV === 0);
5516
5622
  describe('idb.del');
5517
5623
  await del(store, ['t', 0]);
5518
- const getVDel = await get(store, ['t', 0]);
5624
+ const getVDel = await get$1(store, ['t', 0]);
5519
5625
  assert(getVDel === undefined);
5520
5626
  describe('idb.add');
5521
5627
  await add(store, 99, 42);
5522
- const idbVAdd = await get(store, 42);
5628
+ const idbVAdd = await get$1(store, 42);
5523
5629
  assert(idbVAdd === 99);
5524
5630
  describe('idb.addAutoKey');
5525
5631
  const key = await addAutoKey(store, 1234);
5526
- const retrieved = await get(store, key);
5632
+ const retrieved = await get$1(store, key);
5527
5633
  assert(retrieved === 1234);
5528
5634
  };
5529
5635
 
@@ -5973,7 +6079,7 @@ const measureP = (p, min, max) => {
5973
6079
  * @param {Promise<T>} p
5974
6080
  * @return {Promise<T>}
5975
6081
  */
5976
- const failsP = p => create$2((resolve, reject) => p.then(() => reject(create$1('Promise should fail')), resolve));
6082
+ const failsP = p => create$5((resolve, reject) => p.then(() => reject(create$4('Promise should fail')), resolve));
5977
6083
 
5978
6084
  /**
5979
6085
  * @param {t.TestCase} tc
@@ -5999,7 +6105,7 @@ const testRepeatPromise = async tc => {
5999
6105
  */
6000
6106
  const testispromise = tc => {
6001
6107
  assert(isPromise(new Promise(() => {})));
6002
- assert(isPromise(create$2(() => {})));
6108
+ assert(isPromise(create$5(() => {})));
6003
6109
  const rej = reject();
6004
6110
  assert(isPromise(rej));
6005
6111
  rej.catch(() => {});
@@ -6044,12 +6150,12 @@ class Queue {
6044
6150
  *
6045
6151
  * @return {Queue}
6046
6152
  */
6047
- const create = () => new Queue();
6153
+ const create$3 = () => new Queue();
6048
6154
 
6049
6155
  /**
6050
6156
  * @param {Queue} queue
6051
6157
  */
6052
- const isEmpty = queue => queue.start === null;
6158
+ const isEmpty$1 = queue => queue.start === null;
6053
6159
 
6054
6160
  /**
6055
6161
  * @param {Queue} queue
@@ -6074,12 +6180,15 @@ const dequeue = queue => {
6074
6180
  if (n !== null) {
6075
6181
  // @ts-ignore
6076
6182
  queue.start = n.next;
6183
+ if (queue.start === null) {
6184
+ queue.end = null;
6185
+ }
6077
6186
  return n
6078
6187
  }
6079
6188
  return null
6080
6189
  };
6081
6190
 
6082
- class QueueItem extends QueueNode {
6191
+ class QueueItem$1 extends QueueNode {
6083
6192
  /**
6084
6193
  * @param {number} v
6085
6194
  */
@@ -6092,51 +6201,62 @@ class QueueItem extends QueueNode {
6092
6201
  /**
6093
6202
  * @param {t.TestCase} tc
6094
6203
  */
6095
- const testEnqueueDequeue = tc => {
6204
+ const testEnqueueDequeue$1 = tc => {
6096
6205
  const N = 30;
6097
6206
  /**
6098
6207
  * @type {queue.Queue}
6099
6208
  */
6100
- const q = create();
6101
- assert(isEmpty(q));
6209
+ const q = create$3();
6210
+ assert(isEmpty$1(q));
6102
6211
  assert(dequeue(q) === null);
6103
6212
  for (let i = 0; i < N; i++) {
6104
- enqueue(q, new QueueItem(i));
6105
- assert(!isEmpty(q));
6213
+ enqueue(q, new QueueItem$1(i));
6214
+ assert(!isEmpty$1(q));
6106
6215
  }
6107
6216
  for (let i = 0; i < N; i++) {
6108
6217
  const item = /** @type {QueueItem} */ (dequeue(q));
6109
6218
  assert(item !== null && item.v === i);
6110
6219
  }
6220
+ assert(isEmpty$1(q));
6221
+ assert(dequeue(q) === null);
6222
+ for (let i = 0; i < N; i++) {
6223
+ enqueue(q, new QueueItem$1(i));
6224
+ assert(!isEmpty$1(q));
6225
+ }
6226
+ for (let i = 0; i < N; i++) {
6227
+ const item = /** @type {QueueItem} */ (dequeue(q));
6228
+ assert(item !== null && item.v === i);
6229
+ }
6230
+ assert(isEmpty$1(q));
6111
6231
  assert(dequeue(q) === null);
6112
6232
  };
6113
6233
 
6114
6234
  var queue = /*#__PURE__*/Object.freeze({
6115
6235
  __proto__: null,
6116
- testEnqueueDequeue: testEnqueueDequeue
6236
+ testEnqueueDequeue: testEnqueueDequeue$1
6117
6237
  });
6118
6238
 
6119
6239
  /**
6120
6240
  * @param {t.TestCase} tc
6121
6241
  */
6122
6242
  const testMap = tc => {
6123
- const m = create$7();
6243
+ const m = create$a();
6124
6244
  m.set(1, 2);
6125
6245
  m.set(2, 3);
6126
- assert(map$3(m, (value, key) => value * 2 + key).reduce(add$1) === 13);
6246
+ assert(map$4(m, (value, key) => value * 2 + key).reduce(add$1) === 13);
6127
6247
  let numberOfWrites = 0;
6128
6248
  const createT = () => {
6129
6249
  numberOfWrites++;
6130
6250
  return {}
6131
6251
  };
6132
- setIfUndefined(m, 3, createT);
6133
- setIfUndefined(m, 3, createT);
6134
- setIfUndefined(m, 3, createT);
6252
+ setIfUndefined$1(m, 3, createT);
6253
+ setIfUndefined$1(m, 3, createT);
6254
+ setIfUndefined$1(m, 3, createT);
6135
6255
  compare(copy(m), m);
6136
6256
  assert(numberOfWrites === 1);
6137
6257
  };
6138
6258
 
6139
- var map = /*#__PURE__*/Object.freeze({
6259
+ var map$1 = /*#__PURE__*/Object.freeze({
6140
6260
  __proto__: null,
6141
6261
  testMap: testMap
6142
6262
  });
@@ -6171,7 +6291,7 @@ const testTimeout = async tc => {
6171
6291
  set = true;
6172
6292
  });
6173
6293
  timeout$1.destroy();
6174
- await create$2(resolve => {
6294
+ await create$5(resolve => {
6175
6295
  timeout(10, resolve);
6176
6296
  });
6177
6297
  assert(set === false);
@@ -6209,7 +6329,7 @@ const testAnimationFrame = async tc => {
6209
6329
  * @param {t.TestCase} tc
6210
6330
  */
6211
6331
  const testIdleCallback = async tc => {
6212
- await create$2(resolve => {
6332
+ await create$5(resolve => {
6213
6333
  idleCallback(resolve);
6214
6334
  });
6215
6335
  };
@@ -6264,7 +6384,7 @@ var time = /*#__PURE__*/Object.freeze({
6264
6384
  * @param {t.TestCase} tc
6265
6385
  */
6266
6386
  const testPair = tc => {
6267
- const ps = [create$5(1, 2), create$5(3, 4), createReversed(6, 5)];
6387
+ const ps = [create$8(1, 2), create$8(3, 4), createReversed(6, 5)];
6268
6388
  describe('Counting elements in pair list');
6269
6389
  let countLeft = 0;
6270
6390
  let countRight = 0;
@@ -6274,8 +6394,8 @@ const testPair = tc => {
6274
6394
  });
6275
6395
  assert(countLeft === 9);
6276
6396
  assert(countRight === 12);
6277
- assert(countLeft === map$2(ps, left => left).reduce(add$1));
6278
- assert(countRight === map$2(ps, (left, right) => right).reduce(add$1));
6397
+ assert(countLeft === map$3(ps, left => left).reduce(add$1));
6398
+ assert(countRight === map$3(ps, (left, right) => right).reduce(add$1));
6279
6399
  };
6280
6400
 
6281
6401
  var pair = /*#__PURE__*/Object.freeze({
@@ -6287,7 +6407,7 @@ var pair = /*#__PURE__*/Object.freeze({
6287
6407
  * @param {t.TestCase} tc
6288
6408
  */
6289
6409
  const testObject = tc => {
6290
- assert(create$4().constructor === undefined, 'object.create creates an empty object without constructor');
6410
+ assert(create$7().constructor === undefined, 'object.create creates an empty object without constructor');
6291
6411
  describe('object.equalFlat');
6292
6412
  assert(equalFlat({}, {}), 'comparing equal objects');
6293
6413
  assert(equalFlat({ x: 1 }, { x: 1 }), 'comparing equal objects');
@@ -6308,7 +6428,7 @@ const testObject = tc => {
6308
6428
  forEach({ x: 1, y: 3 }, (v, k) => { forEachSum += v; });
6309
6429
  assert(forEachSum === 4);
6310
6430
  describe('object.map');
6311
- assert(map$1({ x: 1, z: 5 }, (v, k) => v).reduce(add$1) === 6);
6431
+ assert(map$2({ x: 1, z: 5 }, (v, k) => v).reduce(add$1) === 6);
6312
6432
  describe('object.length');
6313
6433
  assert(length$1({}) === 0);
6314
6434
  assert(length$1({ x: 1 }) === 1);
@@ -6408,6 +6528,50 @@ var buffer = /*#__PURE__*/Object.freeze({
6408
6528
  testAnyEncoding: testAnyEncoding
6409
6529
  });
6410
6530
 
6531
+ /**
6532
+ * Utility module to work with sets.
6533
+ *
6534
+ * @module set
6535
+ */
6536
+
6537
+ const create$2 = () => new Set();
6538
+
6539
+ /**
6540
+ * @template T
6541
+ * @param {Set<T>} set
6542
+ * @return {T}
6543
+ */
6544
+ const first = set => {
6545
+ return set.values().next().value || undefined
6546
+ };
6547
+
6548
+ /**
6549
+ * @template T
6550
+ * @param {Iterable<T>} entries
6551
+ * @return {Set<T>}
6552
+ */
6553
+ const from = entries => {
6554
+ return new Set(entries)
6555
+ };
6556
+
6557
+ /**
6558
+ * @template T
6559
+ * @param {t.TestCase} tc
6560
+ */
6561
+ const testFirst = tc => {
6562
+ const two = from(['a', 'b']);
6563
+ const one = from(['b']);
6564
+ const zero = create$2();
6565
+ assert(first(two) === 'a');
6566
+ assert(first(one) === 'b');
6567
+ assert(first(zero) === undefined);
6568
+ };
6569
+
6570
+ var set$1 = /*#__PURE__*/Object.freeze({
6571
+ __proto__: null,
6572
+ testFirst: testFirst
6573
+ });
6574
+
6411
6575
  /**
6412
6576
  * Efficient sort implementations.
6413
6577
  *
@@ -6700,7 +6864,7 @@ const decodeQueryParams = url => {
6700
6864
  * @return {string}
6701
6865
  */
6702
6866
  const encodeQueryParams = params =>
6703
- map$1(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
6867
+ map$2(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
6704
6868
 
6705
6869
  /**
6706
6870
  * @param {Object<string,any>} params
@@ -6864,6 +7028,459 @@ var storage = /*#__PURE__*/Object.freeze({
6864
7028
  testStorageModule: testStorageModule
6865
7029
  });
6866
7030
 
7031
+ class ListNode {
7032
+ constructor () {
7033
+ /**
7034
+ * @type {this|null}
7035
+ */
7036
+ this.next = null;
7037
+ /**
7038
+ * @type {this|null}
7039
+ */
7040
+ this.prev = null;
7041
+ }
7042
+ }
7043
+
7044
+ /**
7045
+ * @template {ListNode} N
7046
+ */
7047
+ class List {
7048
+ constructor () {
7049
+ /**
7050
+ * @type {N | null}
7051
+ */
7052
+ this.start = null;
7053
+ /**
7054
+ * @type {N | null}
7055
+ */
7056
+ this.end = null;
7057
+ }
7058
+ }
7059
+
7060
+ /**
7061
+ * @note The queue implementation is experimental and unfinished.
7062
+ * Don't use this in production yet.
7063
+ *
7064
+ * @template {ListNode} N
7065
+ *
7066
+ * @return {List<N>}
7067
+ */
7068
+ const create$1 = () => new List();
7069
+
7070
+ /**
7071
+ * @template {ListNode} N
7072
+ *
7073
+ * @param {List<N>} queue
7074
+ */
7075
+ const isEmpty = queue => queue.start === null;
7076
+
7077
+ /**
7078
+ * Remove a single node from the queue. Only works with Queues that operate on Doubly-linked lists of nodes.
7079
+ *
7080
+ * @template {ListNode} N
7081
+ *
7082
+ * @param {List<N>} queue
7083
+ * @param {N} node
7084
+ */
7085
+ const removeNode = (queue, node) => {
7086
+ const prev = node.prev;
7087
+ const next = node.next;
7088
+ if (prev) {
7089
+ prev.next = next;
7090
+ } else {
7091
+ queue.start = next;
7092
+ }
7093
+ if (next) {
7094
+ next.prev = prev;
7095
+ } else {
7096
+ queue.end = prev;
7097
+ }
7098
+ return node
7099
+ };
7100
+
7101
+ /**
7102
+ * @template {ListNode} N
7103
+ *
7104
+ * @param {List<N>} queue
7105
+ * @param {N| null} left
7106
+ * @param {N| null} right
7107
+ * @param {N} node
7108
+ */
7109
+ const insertBetween = (queue, left, right, node) => {
7110
+ /* istanbul ignore if */
7111
+ if (left != null && left.next !== right) {
7112
+ throw unexpectedCase()
7113
+ }
7114
+ if (left) {
7115
+ left.next = node;
7116
+ } else {
7117
+ queue.start = node;
7118
+ }
7119
+ if (right) {
7120
+ right.prev = node;
7121
+ } else {
7122
+ queue.end = node;
7123
+ }
7124
+ node.prev = left;
7125
+ node.next = right;
7126
+ };
7127
+
7128
+ /**
7129
+ * @template {ListNode} N
7130
+ *
7131
+ * @param {List<N>} queue
7132
+ * @param {N} n
7133
+ */
7134
+ const pushEnd = (queue, n) =>
7135
+ insertBetween(queue, queue.end, null, n);
7136
+
7137
+ /**
7138
+ * @template {ListNode} N
7139
+ *
7140
+ * @param {List<N>} queue
7141
+ * @param {N} n
7142
+ */
7143
+ const pushFront = (queue, n) =>
7144
+ insertBetween(queue, null, queue.start, n);
7145
+
7146
+ /**
7147
+ * @template {ListNode} N
7148
+ *
7149
+ * @param {List<N>} list
7150
+ * @return {N| null}
7151
+ */
7152
+ const popFront = list =>
7153
+ list.start ? removeNode(list, list.start) : null;
7154
+
7155
+ /**
7156
+ * @template {ListNode} N
7157
+ *
7158
+ * @param {List<N>} list
7159
+ * @return {N| null}
7160
+ */
7161
+ const popEnd = list =>
7162
+ list.end ? removeNode(list, list.end) : null;
7163
+
7164
+ /**
7165
+ * @template {ListNode} N
7166
+ * @template M
7167
+ *
7168
+ * @param {List<N>} list
7169
+ * @param {function(N):M} f
7170
+ * @return {Array<M>}
7171
+ */
7172
+ const map = (list, f) => {
7173
+ /**
7174
+ * @type {Array<M>}
7175
+ */
7176
+ const arr = [];
7177
+ let n = list.start;
7178
+ while (n) {
7179
+ arr.push(f(n));
7180
+ n = n.next;
7181
+ }
7182
+ return arr
7183
+ };
7184
+
7185
+ class QueueItem extends ListNode {
7186
+ /**
7187
+ * @param {number} v
7188
+ */
7189
+ constructor (v) {
7190
+ super();
7191
+ this.v = v;
7192
+ }
7193
+ }
7194
+
7195
+ /**
7196
+ * @param {t.TestCase} tc
7197
+ */
7198
+ const testEnqueueDequeue = tc => {
7199
+ const N = 30;
7200
+ /**
7201
+ * @type {list.List<QueueItem>}
7202
+ */
7203
+ const q = create$1();
7204
+ assert(isEmpty(q));
7205
+ assert(popFront(q) === null);
7206
+ for (let i = 0; i < N; i++) {
7207
+ pushEnd(q, new QueueItem(i));
7208
+ assert(!isEmpty(q));
7209
+ }
7210
+ for (let i = 0; i < N; i++) {
7211
+ const item = /** @type {QueueItem} */ (popFront(q));
7212
+ assert(item !== null && item.v === i);
7213
+ }
7214
+ assert(isEmpty(q));
7215
+ assert(popFront(q) === null);
7216
+ for (let i = 0; i < N; i++) {
7217
+ pushEnd(q, new QueueItem(i));
7218
+ assert(!isEmpty(q));
7219
+ }
7220
+ for (let i = 0; i < N; i++) {
7221
+ const item = /** @type {QueueItem} */ (popFront(q));
7222
+ assert(item !== null && item.v === i);
7223
+ }
7224
+ assert(isEmpty(q));
7225
+ assert(popFront(q) === null);
7226
+ };
7227
+
7228
+ /**
7229
+ * @param {t.TestCase} tc
7230
+ */
7231
+ const testSelectivePop = tc => {
7232
+ /**
7233
+ * @type {list.List<QueueItem>}
7234
+ */
7235
+ const l = create$1();
7236
+ pushFront(l, new QueueItem(1));
7237
+ pushEnd(l, new QueueItem(3));
7238
+ const middleNode = new QueueItem(2);
7239
+ insertBetween(l, l.start, l.end, middleNode);
7240
+ compare(map(l, n => n.v), [1, 2, 3]);
7241
+ assert(removeNode(l, middleNode) === middleNode);
7242
+ compare(/** @type {QueueItem} */ (popEnd(l)).v, 3);
7243
+ compare(/** @type {QueueItem} */ (popEnd(l)).v, 1);
7244
+ compare(popEnd(l), null);
7245
+ assert(l.start === null);
7246
+ assert(l.end === null);
7247
+ };
7248
+
7249
+ var list = /*#__PURE__*/Object.freeze({
7250
+ __proto__: null,
7251
+ testEnqueueDequeue: testEnqueueDequeue,
7252
+ testSelectivePop: testSelectivePop
7253
+ });
7254
+
7255
+ /**
7256
+ * @template K, V
7257
+ *
7258
+ * @implements {list.ListNode}
7259
+ */
7260
+ class Entry {
7261
+ /**
7262
+ * @param {K} key
7263
+ * @param {V | Promise<V>} val
7264
+ */
7265
+ constructor (key, val) {
7266
+ /**
7267
+ * @type {this | null}
7268
+ */
7269
+ this.prev = null;
7270
+ /**
7271
+ * @type {this | null}
7272
+ */
7273
+ this.next = null;
7274
+ this.created = getUnixTime();
7275
+ this.val = val;
7276
+ this.key = key;
7277
+ }
7278
+ }
7279
+
7280
+ /**
7281
+ * @template K, V
7282
+ */
7283
+ class Cache {
7284
+ /**
7285
+ * @param {number} timeout
7286
+ */
7287
+ constructor (timeout) {
7288
+ this.timeout = timeout;
7289
+ /**
7290
+ * @type list.List<Entry<K, V>>
7291
+ */
7292
+ this._q = create$1();
7293
+ /**
7294
+ * @type {Map<K, Entry<K, V>>}
7295
+ */
7296
+ this._map = create$a();
7297
+ }
7298
+ }
7299
+
7300
+ /**
7301
+ * @template K, V
7302
+ *
7303
+ * @param {Cache<K, V>} cache
7304
+ * @return {number} Returns the current timestamp
7305
+ */
7306
+ const removeStale = cache => {
7307
+ const now = getUnixTime();
7308
+ const q = cache._q;
7309
+ while (q.start && now - q.start.created > cache.timeout) {
7310
+ cache._map.delete(q.start.key);
7311
+ popFront(q);
7312
+ }
7313
+ return now
7314
+ };
7315
+
7316
+ /**
7317
+ * @template K, V
7318
+ *
7319
+ * @param {Cache<K, V>} cache
7320
+ * @param {K} key
7321
+ * @param {V} value
7322
+ */
7323
+ const set = (cache, key, value) => {
7324
+ const now = removeStale(cache);
7325
+ const q = cache._q;
7326
+ const n = cache._map.get(key);
7327
+ if (n) {
7328
+ removeNode(q, n);
7329
+ pushEnd(q, n);
7330
+ n.created = now;
7331
+ n.val = value;
7332
+ } else {
7333
+ const node = new Entry(key, value);
7334
+ pushEnd(q, node);
7335
+ cache._map.set(key, node);
7336
+ }
7337
+ };
7338
+
7339
+ /**
7340
+ * @template K, V
7341
+ *
7342
+ * @param {Cache<K, V>} cache
7343
+ * @param {K} key
7344
+ * @return {Entry<K, V> | undefined}
7345
+ */
7346
+ const getNode = (cache, key) => {
7347
+ const now = removeStale(cache);
7348
+ const q = cache._q;
7349
+ const n = cache._map.get(key);
7350
+ if (n) {
7351
+ removeNode(q, n);
7352
+ pushEnd(q, n);
7353
+ n.created = now;
7354
+ return n
7355
+ }
7356
+ };
7357
+
7358
+ /**
7359
+ * @template K, V
7360
+ *
7361
+ * @param {Cache<K, V>} cache
7362
+ * @param {K} key
7363
+ * @return {V | undefined}
7364
+ */
7365
+ const get = (cache, key) => {
7366
+ const n = getNode(cache, key);
7367
+ return n && !(n.val instanceof Promise) ? n.val : undefined
7368
+ };
7369
+
7370
+ /**
7371
+ * Works well in conjunktion with setIfUndefined which has an async init function.
7372
+ * Using getAsync & setIfUndefined ensures that the init function is only called once.
7373
+ *
7374
+ * @template K, V
7375
+ *
7376
+ * @param {Cache<K, V>} cache
7377
+ * @param {K} key
7378
+ * @return {V | Promise<V> | undefined}
7379
+ */
7380
+ const getAsync = (cache, key) => {
7381
+ const n = getNode(cache, key);
7382
+ return n ? n.val : undefined
7383
+ };
7384
+
7385
+ /**
7386
+ * @template K, V
7387
+ *
7388
+ * @param {Cache<K, V>} cache
7389
+ * @param {K} key
7390
+ * @param {function():Promise<V>} init
7391
+ * @return {Promise<V> | V}
7392
+ */
7393
+ const setIfUndefined = (cache, key, init) => {
7394
+ const now = removeStale(cache);
7395
+ const q = cache._q;
7396
+ const n = cache._map.get(key);
7397
+ if (n) {
7398
+ removeNode(q, n);
7399
+ pushEnd(q, n);
7400
+ n.created = now;
7401
+ return n.val
7402
+ } else {
7403
+ const p = init();
7404
+ const node = new Entry(key, p);
7405
+ pushEnd(q, node);
7406
+ cache._map.set(key, node);
7407
+ p.then(v => {
7408
+ if (p === node.val) {
7409
+ node.val = v;
7410
+ }
7411
+ });
7412
+ return p
7413
+ }
7414
+ };
7415
+
7416
+ /**
7417
+ * @param {number} timeout
7418
+ */
7419
+ const create = timeout => new Cache(timeout);
7420
+
7421
+ /**
7422
+ * @param {t.TestCase} tc
7423
+ */
7424
+ const testCache = async tc => {
7425
+ /**
7426
+ * @type {cache.Cache<string, string>}
7427
+ */
7428
+ const c = create(50);
7429
+ set(c, 'a', '1');
7430
+ assert(get(c, 'a') === '1');
7431
+ assert(await getAsync(c, 'a') === '1');
7432
+ const p = setIfUndefined(c, 'b', () => resolveWith('2'));
7433
+ const q = setIfUndefined(c, 'b', () => resolveWith('3'));
7434
+ assert(p === q);
7435
+ assert(get(c, 'b') == null);
7436
+ assert(getAsync(c, 'b') === p);
7437
+ assert(await p === '2');
7438
+ assert(get(c, 'b') === '2');
7439
+ assert(getAsync(c, 'b') === '2');
7440
+
7441
+ await wait(5); // keys shouldn't be timed out yet
7442
+ assert(get(c, 'a') === '1');
7443
+ assert(get(c, 'b') === '2');
7444
+
7445
+ /**
7446
+ * @type {any}
7447
+ */
7448
+ const m = c._map;
7449
+ const aTimestamp1 = m.get('a').created;
7450
+ const bTimestamp1 = m.get('b').created;
7451
+
7452
+ // write new values and check later if the creation-timestamp was updated
7453
+ set(c, 'a', '11');
7454
+ await setIfUndefined(c, 'b', () => resolveWith('22')); // this shouldn't override, but update the timestamp
7455
+
7456
+ await wait(5); // keys should be updated and not timed out. Hence the creation time should be updated
7457
+ assert(get(c, 'a') === '11');
7458
+ assert(get(c, 'b') === '2');
7459
+ // timestamps should be updated
7460
+ assert(aTimestamp1 !== m.get('a').created);
7461
+ assert(bTimestamp1 !== m.get('b').created);
7462
+
7463
+ await wait(60); // now the keys should be timed-out
7464
+
7465
+ assert(get(c, 'a') == null);
7466
+ assert(getAsync(c, 'b') == null);
7467
+
7468
+ assert(c._map.size === 0);
7469
+ assert(c._q.start === null && c._q.end === null);
7470
+
7471
+ // test edge case of setIfUndefined
7472
+ const xp = setIfUndefined(c, 'a', () => resolve('x'));
7473
+ set(c, 'a', 'y');
7474
+ await xp;
7475
+ // 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.
7476
+ assert(get(c, 'a') === 'y');
7477
+ };
7478
+
7479
+ var cache = /*#__PURE__*/Object.freeze({
7480
+ __proto__: null,
7481
+ testCache: testCache
7482
+ });
7483
+
6867
7484
  /* istanbul ignore if */
6868
7485
  if (isBrowser) {
6869
7486
  createVConsole(document.body);
@@ -6883,7 +7500,7 @@ runTests({
6883
7500
  random,
6884
7501
  promise,
6885
7502
  queue,
6886
- map,
7503
+ map: map$1,
6887
7504
  eventloop,
6888
7505
  time,
6889
7506
  pair,
@@ -6891,11 +7508,14 @@ runTests({
6891
7508
  math,
6892
7509
  number,
6893
7510
  buffer,
7511
+ set: set$1,
6894
7512
  sort,
6895
7513
  url,
6896
7514
  metric,
6897
7515
  func,
6898
- storage
7516
+ storage,
7517
+ list,
7518
+ cache
6899
7519
  }).then(success => {
6900
7520
  /* istanbul ignore next */
6901
7521
  if (isNode) {