indexeddbshim 19.0.5 → 19.0.6

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 (60) hide show
  1. package/badges/coverage-badge.svg +1 -1
  2. package/badges/tests-badge.svg +1 -1
  3. package/dist/CFG.d.ts +1 -1
  4. package/dist/CFG.d.ts.map +1 -1
  5. package/dist/DOMException.d.ts.map +1 -1
  6. package/dist/IDBCursor.d.ts.map +1 -1
  7. package/dist/IDBDatabase.d.ts.map +1 -1
  8. package/dist/IDBFactory.d.ts +1 -2
  9. package/dist/IDBFactory.d.ts.map +1 -1
  10. package/dist/IDBIndex.d.ts +2 -6
  11. package/dist/IDBIndex.d.ts.map +1 -1
  12. package/dist/IDBKeyRange.d.ts.map +1 -1
  13. package/dist/IDBObjectStore.d.ts.map +1 -1
  14. package/dist/IDBRecord.d.ts.map +1 -1
  15. package/dist/IDBRequest.d.ts.map +1 -1
  16. package/dist/IDBTransaction.d.ts.map +1 -1
  17. package/dist/Key.d.ts.map +1 -1
  18. package/dist/Sca.d.ts.map +1 -1
  19. package/dist/indexeddbshim-Key.js +40 -28
  20. package/dist/indexeddbshim-Key.js.map +1 -1
  21. package/dist/indexeddbshim-Key.min.js +2 -2
  22. package/dist/indexeddbshim-Key.min.js.map +1 -1
  23. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +511 -217
  24. package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
  25. package/dist/indexeddbshim-UnicodeIdentifiers.js +539 -244
  26. package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
  27. package/dist/indexeddbshim-UnicodeIdentifiers.min.js +3 -3
  28. package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
  29. package/dist/indexeddbshim-node.cjs +511 -217
  30. package/dist/indexeddbshim-node.cjs.map +1 -1
  31. package/dist/indexeddbshim-noninvasive.js +539 -244
  32. package/dist/indexeddbshim-noninvasive.js.map +1 -1
  33. package/dist/indexeddbshim-noninvasive.min.js +3 -3
  34. package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
  35. package/dist/indexeddbshim.js +539 -244
  36. package/dist/indexeddbshim.js.map +1 -1
  37. package/dist/indexeddbshim.min.js +3 -3
  38. package/dist/indexeddbshim.min.js.map +1 -1
  39. package/dist/nodeWebSQL.d.ts.map +1 -1
  40. package/dist/setGlobalVars.d.ts +1 -1
  41. package/dist/setGlobalVars.d.ts.map +1 -1
  42. package/dist/util.d.ts.map +1 -1
  43. package/package.json +22 -17
  44. package/src/CFG.js +18 -4
  45. package/src/DOMException.js +6 -0
  46. package/src/DOMStringList.js +3 -0
  47. package/src/IDBCursor.js +36 -3
  48. package/src/IDBDatabase.js +26 -10
  49. package/src/IDBFactory.js +105 -5
  50. package/src/IDBIndex.js +49 -32
  51. package/src/IDBKeyRange.js +8 -7
  52. package/src/IDBObjectStore.js +25 -2
  53. package/src/IDBRecord.js +2 -0
  54. package/src/IDBRequest.js +7 -4
  55. package/src/IDBTransaction.js +97 -26
  56. package/src/Key.js +17 -16
  57. package/src/Sca.js +9 -4
  58. package/src/nodeWebSQL.js +1 -0
  59. package/src/setGlobalVars.js +86 -77
  60. package/src/util.js +5 -6
@@ -1,4 +1,4 @@
1
- /*! indexeddbshim - v19.0.5 - 9/17/2026 */
1
+ /*! indexeddbshim - v19.0.6 - 9/22/2026 */
2
2
 
3
3
  (function (global, factory) {
4
4
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -481,6 +481,7 @@
481
481
  var ShimDOMException$1 = typeof DOMException === 'undefined'
482
482
  // Todo: Better polyfill (if even needed here)
483
483
  /* eslint-disable no-shadow -- Polyfill */
484
+ /* c8 ignore start -- Only reachable when the global `DOMException` is absent, which it never is in this project's test environment (Node always provides it) */
484
485
  // eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
485
486
  ?
486
487
  /**
@@ -498,9 +499,10 @@
498
499
  configurable: true
499
500
  });
500
501
  return err;
501
- } : DOMException;
502
+ }
503
+ /* c8 ignore stop */ : DOMException;
502
504
 
503
- /** @type {WeakMap<object, any>} */
505
+ /** @type {WeakMap<object, EventWithProps>} */
504
506
  var ev = new WeakMap();
505
507
  /** @type {WeakMap<object, EventWithProps>} */
506
508
  var evCfg = new WeakMap();
@@ -546,11 +548,12 @@
546
548
  obj[prop] = {
547
549
  configurable: true,
548
550
  get: function get() {
549
- return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false : undefined;
551
+ return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
552
+ /* c8 ignore next -- Every prop this is ever called with ('type'/'bubbles'/'cancelable'/'timeStamp'/'composed'/'detail') always ends up set on `_evCfg` or `_ev` by the time it's read, so this is unreachable */ : undefined;
550
553
  }
551
554
  };
552
555
  return obj;
553
- }, /** @type {{[key: string]: any}} */{}));
556
+ }, /** @type {PropertyDescriptorMap} */{}));
554
557
  }
555
558
 
556
559
  /**
@@ -573,8 +576,9 @@
573
576
  throw new TypeError('Illegal invocation');
574
577
  }
575
578
  var _evCfg = getEvCfg(this);
576
- var _ev = ev.get(this);
577
- return Boolean(Object.hasOwn(_evCfg, 'isTrusted') ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
579
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
580
+ return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
581
+ /* c8 ignore next -- Nothing currently sets `_evCfg.isTrusted` (see the commented-out assignment above); kept for when/if it's revived */ ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
578
582
  }
579
583
 
580
584
  /**
@@ -725,15 +729,15 @@
725
729
  // this untyped alias, rather than `ShimEvent.prototype` directly, keeps
726
730
  // that dynamic-augmentation pattern working without a `@ts-expect-error`
727
731
  // on every single line below.
728
- /** @type {any} */
729
- var ShimEventProto = ShimEvent.prototype;
732
+
733
+ var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
730
734
 
731
735
  /** @this {EventWithProps} */
732
736
  ShimEventProto.preventDefault = function preventDefault() {
733
737
  if (!(this instanceof ShimEvent)) {
734
738
  throw new TypeError('Illegal invocation');
735
739
  }
736
- var _ev = ev.get(this);
740
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
737
741
  var _evCfg = getEvCfg(this);
738
742
  if (this.cancelable && !_evCfg._passive) {
739
743
  _evCfg.defaultPrevented = true;
@@ -931,13 +935,12 @@
931
935
  return _createClass(CustomEvent);
932
936
  }(Event);
933
937
  var ShimCustomEvent = CustomEvent;
934
- /** @type {any} */
935
- var ShimCustomEventProto = ShimCustomEvent.prototype;
938
+ var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
936
939
  /**
937
940
  * @param {string} type
938
941
  * @param {boolean} [bubbles]
939
942
  * @param {boolean} [cancelable]
940
- * @param {any} [detail]
943
+ * @param {unknown} [detail]
941
944
  * @this {EventWithProps}
942
945
  */
943
946
  ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
@@ -949,6 +952,10 @@
949
952
  throw new TypeError('Illegal invocation');
950
953
  }
951
954
  var _evCfg = getEvCfg(this);
955
+ if (_evCfg._dispatched) {
956
+ return;
957
+ }
958
+
952
959
  // @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
953
960
  // eslint-disable-next-line prefer-rest-params -- Keep signature
954
961
  initEventInternal(this, type, {
@@ -956,16 +963,13 @@
956
963
  cancelable: cancelable,
957
964
  detail: detail
958
965
  }, arguments[4]);
959
- if (_evCfg._dispatched) {
960
- return;
961
- }
962
966
  if (detail !== undefined) {
963
967
  _evCfg.detail = detail;
964
968
  }
965
969
  // `initCustomEvent` deliberately excluded -- see the matching comment
966
970
  // in `initEventInternal` for `initEvent`, above; the same reasoning
967
971
  // applies here.
968
- definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
972
+ definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
969
973
  };
970
974
  // @ts-expect-error Not part of the class body itself
971
975
  ShimCustomEvent[Symbol.toStringTag] = 'Function';
@@ -1372,7 +1376,7 @@
1372
1376
  /** @type {string[]} */
1373
1377
  this._extraProperties.forEach(function (prop) {
1374
1378
  if (Reflect.has(e, prop)) {
1375
- /** @type {{[key: string]: any}} */eventCopy[prop] = /** @type {{[key: string]: any}} */e[prop]; // Todo: Put internal to `ShimEvent`?
1379
+ /** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
1376
1380
  }
1377
1381
  });
1378
1382
  }
@@ -1451,6 +1455,7 @@
1451
1455
  if (child) {
1452
1456
  child._defaultSync = this._defaultSync;
1453
1457
  }
1458
+ /* c8 ignore next -- `cfg._children` always has exactly as many entries as remaining capturing-phase steps (built from the same walk that starts this phase), so `child` is never falsy here; the `|| this` fallback is defensive only */
1454
1459
  return (child || this)._dispatchEvent(eventCopy, false);
1455
1460
  }
1456
1461
  case phases.AT_TARGET:
@@ -1748,7 +1753,7 @@
1748
1753
  * databaseNameLengthLimit: number|false,
1749
1754
  * escapeNFDForDatabaseNames: boolean,
1750
1755
  * addSQLiteExtension: boolean,
1751
- * memoryDatabase: string,
1756
+ * memoryDatabase: string|null|undefined,
1752
1757
  * deleteDatabaseFiles: boolean,
1753
1758
  * databaseBasePath: string,
1754
1759
  * sysDatabaseBasePath: string,
@@ -1891,13 +1896,27 @@
1891
1896
  // Various types of in-memory databases that can auto-delete
1892
1897
  ['memoryDatabase',
1893
1898
  /**
1894
- * @param {string} val
1899
+ * `null`/`undefined` are accepted (and left unvalidated against the
1900
+ * regex below) specifically so this can be reset back to its
1901
+ * unset/disabled state after being set: unlike other `CFG`
1902
+ * boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
1903
+ * with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
1904
+ * usage sites check `typeof CFG.memoryDatabase === 'string'`, so
1905
+ * even the empty string counts as "on" (it's a distinct, valid
1906
+ * in-memory mode of its own -- an unnamed private temporary
1907
+ * database -- not an "off" state). Without this, once set to any
1908
+ * string there would be no value passable back through this same
1909
+ * validator that turns `useMemoryDatabase` false again.
1910
+ * @param {string|null|undefined} val
1895
1911
  * @throws {TypeError}
1896
1912
  * @returns {void}
1897
1913
  */
1898
1914
  function (val) {
1915
+ if (val === null || val === undefined) {
1916
+ return;
1917
+ }
1899
1918
  if (!/^(?::memory:|file::memory:(\?(?:[\0-"\$-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?(#(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?)?$/.test(/** @type {string} */val)) {
1900
- throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a ' + '"file::memory:[?queryString][#hash] URL".');
1919
+ throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
1901
1920
  }
1902
1921
  }],
1903
1922
  // NODE-SPECIFIC CONFIG
@@ -1951,10 +1970,7 @@
1951
1970
  return arg.replaceAll(/((?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])))(?!(?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|(^|(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))((?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g, function (_, unmatchedHighSurrogate, precedingLow, unmatchedLowSurrogate) {
1952
1971
  // Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
1953
1972
  // but Chrome having problems
1954
- if (unmatchedHighSurrogate) {
1955
- return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
1956
- }
1957
- return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1973
+ return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1958
1974
  });
1959
1975
  }
1960
1976
 
@@ -2621,7 +2637,8 @@
2621
2637
  function createNativeDOMException(name, message) {
2622
2638
  // @ts-expect-error It's ok
2623
2639
  // eslint-disable-next-line new-cap -- Ok
2624
- return new DOMException.prototype.constructor(message, name || 'DOMException');
2640
+ return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
2641
+ name || 'DOMException');
2625
2642
  }
2626
2643
 
2627
2644
  // From web-platform-tests testharness.js name_code_map (though not in new spec)
@@ -2785,8 +2802,10 @@
2785
2802
  */
2786
2803
  get: function get() {
2787
2804
  if (!(this instanceof DOMException ||
2805
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2788
2806
  // @ts-ignore Just checking; needed under some TS versions
2789
2807
  this instanceof DummyDOMException ||
2808
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2790
2809
  // @ts-ignore Just checking; needed under some TS versions
2791
2810
  this instanceof Error)) {
2792
2811
  throw new TypeError('Illegal invocation');
@@ -2845,6 +2864,7 @@
2845
2864
  value: DOMException
2846
2865
  });
2847
2866
 
2867
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2848
2868
  // @ts-ignore We don't need all its properties; needed under some TS versions
2849
2869
  return DOMException;
2850
2870
  }
@@ -2857,6 +2877,7 @@
2857
2877
  * @returns {Error}
2858
2878
  */
2859
2879
  function createNonNativeDOMException(name, message) {
2880
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2860
2881
  // @ts-ignore It's ok; needed under some TS versions
2861
2882
  return new ShimNonNativeDOMException(message, name);
2862
2883
  }
@@ -2879,6 +2900,8 @@
2879
2900
  return;
2880
2901
  }
2881
2902
  var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
2903
+
2904
+ /* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
2882
2905
  var method = typeof console.error === 'function' ? 'error' : 'log';
2883
2906
  console[method](name + ': ' + message + '. ' + (msg || ''));
2884
2907
  if (console.trace) {
@@ -3064,8 +3087,10 @@
3064
3087
  */
3065
3088
  IDBRequest.__super = function IDBRequest() {
3066
3089
  var _this = this;
3090
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3067
3091
  // @ts-ignore It's ok
3068
3092
  this[Symbol.toStringTag] = 'IDBRequest';
3093
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3069
3094
  // @ts-ignore Part of `ShimEventTarget`
3070
3095
  this.__setOptions({
3071
3096
  legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
@@ -3123,10 +3148,7 @@
3123
3148
  * @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
3124
3149
  */
3125
3150
  IDBRequest.prototype.__getParent = function () {
3126
- if (this.toString() === '[object IDBOpenDBRequest]') {
3127
- return null;
3128
- }
3129
- return this.__transaction;
3151
+ return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
3130
3152
  };
3131
3153
 
3132
3154
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
@@ -3185,8 +3207,10 @@
3185
3207
  function IDBOpenDBRequest() {
3186
3208
  IDBRequest.__super.call(this);
3187
3209
 
3210
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3188
3211
  // @ts-ignore It's ok
3189
3212
  this[Symbol.toStringTag] = 'IDBOpenDBRequest';
3213
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3190
3214
  // @ts-ignore It's ok
3191
3215
  this.__setOptions({
3192
3216
  legacyOutputDidListenersThrowFlag: true,
@@ -4197,8 +4221,14 @@
4197
4221
  }
4198
4222
  if (!multiEntry || !fullKeys && keys.every(function (k) {
4199
4223
  return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
4200
- }) || fullKeys && keys.every(function (k) {
4201
- return cmp(/** @type {Key} */k, /** @type {Key} */ /** @type {unknown} */key) !== 0;
4224
+ }) ||
4225
+ // `keys` holds full `{type, value}` objects here (see
4226
+ // `safePush` below), so -- like the sibling branch
4227
+ // above -- `cmp` (which expects raw `Value`s, not
4228
+ // decoded key objects) must compare their `.value`s,
4229
+ // not the wrapper objects themselves.
4230
+ fullKeys && keys.every(function (k) {
4231
+ return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
4202
4232
  })) {
4203
4233
  safePush(keys, fullKeys ? key : key.value);
4204
4234
  }
@@ -4223,12 +4253,9 @@
4223
4253
  {
4224
4254
  var date = /** @type {Date} */input;
4225
4255
  if (!Number.isNaN(date.getTime())) {
4226
- return fullKeys ? {
4227
- type: type,
4228
- value: date.getTime()
4229
- } : {
4256
+ return {
4230
4257
  type: type,
4231
- value: new Date(date)
4258
+ value: fullKeys ? date.getTime() : new Date(date)
4232
4259
  };
4233
4260
  }
4234
4261
  return {
@@ -4316,10 +4343,7 @@
4316
4343
  if (r.failure) {
4317
4344
  return r;
4318
4345
  }
4319
- if (!multiEntry) {
4320
- return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
4321
- }
4322
- return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4346
+ return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4323
4347
  }
4324
4348
 
4325
4349
  /**
@@ -4500,10 +4524,7 @@
4500
4524
  */
4501
4525
  function isMultiEntryMatch(encodedEntry, encodedKey) {
4502
4526
  var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
4503
- if (keyType === 'array') {
4504
- return encodedKey.indexOf(encodedEntry) > 1;
4505
- }
4506
- return encodedKey === encodedEntry;
4527
+ return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
4507
4528
  }
4508
4529
 
4509
4530
  /**
@@ -4621,10 +4642,7 @@
4621
4642
  * @returns {undefined|ValueType}
4622
4643
  */
4623
4644
  function _decode(key, inArray) {
4624
- if (typeof key !== 'string') {
4625
- return undefined;
4626
- }
4627
- return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4645
+ return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4628
4646
  }
4629
4647
 
4630
4648
  /**
@@ -5030,10 +5048,11 @@
5030
5048
  if (hasLower && hasUpper) {
5031
5049
  sql.push('AND');
5032
5050
  }
5033
- if (hasUpper) {
5034
- sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5035
- sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5051
+ if (!hasUpper) {
5052
+ return;
5036
5053
  }
5054
+ sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5055
+ sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5037
5056
  }
5038
5057
 
5039
5058
  /**
@@ -5046,10 +5065,7 @@
5046
5065
  if (instanceOf(value, IDBKeyRange)) {
5047
5066
  // We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
5048
5067
  var range = /** @type {IDBKeyRangeFull} */value;
5049
- if (range.toString() !== '[object IDBKeyRange]') {
5050
- return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
5051
- }
5052
- return range;
5068
+ return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
5053
5069
  }
5054
5070
  if (isNullish(value)) {
5055
5071
  if (nullDisallowed) {
@@ -5094,9 +5110,11 @@
5094
5110
  if (testObject.test) {
5095
5111
  cleanInterface = true;
5096
5112
  }
5113
+ /* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5097
5114
  } catch (err) {
5098
5115
  // Object.defineProperty does not work as intended.
5099
5116
  }
5117
+ /* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5100
5118
  }
5101
5119
 
5102
5120
  /**
@@ -5297,6 +5315,7 @@
5297
5315
  this._length = 0;
5298
5316
  };
5299
5317
  DOMStringList.prototype = DOMStringListAlias.prototype;
5318
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
5300
5319
  // @ts-ignore It's ok; needed under some TS versions
5301
5320
  return /** @type {DOMStringListFull} */new DOMStringList();
5302
5321
  }
@@ -5596,12 +5615,14 @@
5596
5615
  */
5597
5616
  IDBTransaction.prototype.__executeRequests = function () {
5598
5617
  var me = this;
5618
+ /* c8 ignore start -- Dead code: `__executeRequests` has exactly one caller (a single `setTimeout` scheduled once per transaction), so `me.__running` can never already be `true` when this function starts. */
5599
5619
  if (me.__running) {
5600
5620
  if (CFG.DEBUG) {
5601
5621
  console.log('Looks like the request set is already running', me.mode);
5602
5622
  }
5603
5623
  return;
5604
5624
  }
5625
+ /* c8 ignore stop -- see comment above */
5605
5626
 
5606
5627
  // The synchronous script that created this transaction (and
5607
5628
  // synchronously queued whatever requests it wanted to) has now
@@ -5651,6 +5672,7 @@
5651
5672
  queueMicrotask(cb);
5652
5673
  return;
5653
5674
  }
5675
+ /* c8 ignore start -- Browser-only path: in every automated test environment (Node's websql-configurable/better-sqlite3 driver, and the fake/mock drivers modeled after it) `__usesStandardDriver()` is always `false` (they support the 4-arg `nonstandardTransCb` signature), so `isStandardDriver` is never `true` and this branch is never reached. Only a real standard (3-arg) WebSQL driver, as found in an actual browser, would exercise it. */
5654
5676
  try {
5655
5677
  tx.executeSql('SELECT 1', [], function () {
5656
5678
  cb();
@@ -5664,6 +5686,7 @@
5664
5686
  // abort the transaction here.
5665
5687
  me.__abortTransaction(/** @type {Error|DOMException} */err);
5666
5688
  }
5689
+ /* c8 ignore stop -- see comment above */
5667
5690
  }
5668
5691
 
5669
5692
  /**
@@ -5676,21 +5699,26 @@
5676
5699
  * @returns {void}
5677
5700
  */
5678
5701
  function success(result, req) {
5702
+ /* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path (e.g. a driver-level failure or explicit `abort()`) racing with this request's own in-flight SQL success callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
5679
5703
  if (me.__errored || me.__requestsFinished) {
5680
5704
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5681
5705
  return;
5682
5706
  }
5707
+ /* c8 ignore stop -- see comment above */
5683
5708
  if (req) {
5684
5709
  q.req = req; // Need to do this in case of cursors
5685
5710
  }
5711
+ /* c8 ignore start -- Dead code: `launchQueuedOp` only ever passes `success` as a callback in the branch where `q.req` is already truthy, and a falsy `req` param here leaves `q.req` unchanged, so `q.req` can't be falsy at this point. */
5686
5712
  if (!q.req) {
5687
- // TS guard
5688
5713
  return;
5689
5714
  }
5715
+ /* c8 ignore stop -- see comment above */
5716
+ /* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's success callback more than once for the same queued op; not reliably reproducible without directly manipulating the SQL driver. */
5690
5717
  if (q.req.__done) {
5691
5718
  // Avoid continuing with aborted requests
5692
5719
  return;
5693
5720
  }
5721
+ /* c8 ignore stop -- see comment above */
5694
5722
  q.req.__done = true;
5695
5723
  q.req.__result = result;
5696
5724
  q.req.__error = null;
@@ -5707,6 +5735,7 @@
5707
5735
  // is what actually resets `__handlerActive`, once it's
5708
5736
  // confirmed (across its own bounded microtask wait) that no
5709
5737
  // such continuation queued anything.
5738
+ /* c8 ignore start -- Deliberately not tested: throwing from a request's `onsuccess` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
5710
5739
  if (e.__legacyOutputDidListenersThrowError) {
5711
5740
  logError('Error', 'An error occurred in a success handler attached to request chain', e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
5712
5741
  if (!me.__committed) {
@@ -5716,6 +5745,7 @@
5716
5745
  return;
5717
5746
  }
5718
5747
  }
5748
+ /* c8 ignore stop -- see comment above */
5719
5749
  runContinuationSafely(advanceAfterDispatch);
5720
5750
  }
5721
5751
 
@@ -5727,15 +5757,19 @@
5727
5757
  * @returns {void}
5728
5758
  */
5729
5759
  function error() {
5760
+ /* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this request's own in-flight SQL error callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
5730
5761
  if (me.__errored || me.__requestsFinished) {
5731
5762
  // We've already called "onerror", "onabort", or thrown within
5732
5763
  // the transaction, so don't do it again.
5733
5764
  return;
5734
5765
  }
5766
+ /* c8 ignore stop -- see comment above */
5767
+ /* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's error callback more than once, or after its success callback already ran; not reliably reproducible without directly manipulating the SQL driver. */
5735
5768
  if (q.req && q.req.__done) {
5736
5769
  // Avoid continuing with aborted requests
5737
5770
  return;
5738
5771
  }
5772
+ /* c8 ignore stop -- see comment above */
5739
5773
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
5740
5774
  args[_key] = arguments[_key];
5741
5775
  }
@@ -5760,10 +5794,11 @@
5760
5794
  }
5761
5795
  });
5762
5796
  q.req.addDefaultEventListener('error', function () {
5797
+ /* c8 ignore start -- Defensive: this default listener is skipped entirely by `eventtargeter` whenever the event was `preventDefault()`-ed (the only case in which the shared `q` variable above could have already advanced to a different, non-request queue entry by the time a default listener runs); not reachable via the public API under normal (synchronous) dispatch. */
5763
5798
  if (!q.req) {
5764
- // TS guard
5765
5799
  return;
5766
5800
  }
5801
+ /* c8 ignore stop -- see comment above */
5767
5802
  me.__abortTransaction(q.req.__error);
5768
5803
  });
5769
5804
  me.__active = true;
@@ -5775,16 +5810,19 @@
5775
5810
  q.req.dispatchEvent(e);
5776
5811
  // Do not set __active or __handlerActive flags to false yet --
5777
5812
  // see the matching comment in `success`, above.
5778
- if (e.__legacyOutputDidListenersThrowError) {
5779
- logError('Error', 'An error occurred in an error handler attached to request chain', e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
5780
- e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5781
- if (me.__committed) {
5782
- // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5783
- runContinuationSafely(advanceAfterDispatch);
5784
- return;
5785
- }
5786
- me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5813
+ /* c8 ignore start -- Deliberately not tested: throwing from a request's `onerror` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
5814
+ if (!e.__legacyOutputDidListenersThrowError) {
5815
+ return;
5787
5816
  }
5817
+ logError('Error', 'An error occurred in an error handler attached to request chain', e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
5818
+ e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5819
+ if (me.__committed) {
5820
+ // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5821
+ runContinuationSafely(advanceAfterDispatch);
5822
+ return;
5823
+ }
5824
+ me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5825
+ /* c8 ignore stop -- see comment above */
5788
5826
  }
5789
5827
 
5790
5828
  /**
@@ -5808,10 +5846,12 @@
5808
5846
  // (not reset here).
5809
5847
  return true;
5810
5848
  }
5849
+ /* c8 ignore start -- Defensive: reaching this queue entry via the normal advancement path after it was independently marked `__done` (e.g. by `__abortTransaction`'s own separate, async per-request error dispatch) requires a narrow race between that async cleanup and this synchronous advancement; not reliably reproducible without directly manipulating that timing. */
5811
5850
  if (q.req.__done) {
5812
5851
  // Avoid continuing with aborted requests
5813
5852
  return false;
5814
5853
  }
5854
+ /* c8 ignore stop -- see comment above */
5815
5855
  // We're now handing off to (possibly async) work for
5816
5856
  // this request, so the transaction is no longer active
5817
5857
  // until its own `success`/`error` dispatch (below)
@@ -5836,18 +5876,22 @@
5836
5876
  return;
5837
5877
  }
5838
5878
  q.op(tx, q.args, success, error, executeNextRequest);
5879
+ /* c8 ignore start -- Defensive: `q.op` (the SQL driver callback) is expected to report failures via its own `error`/`failure` callback argument rather than throwing synchronously; not reliably reproducible without directly forcing the driver to throw. */
5839
5880
  } catch (e) {
5840
5881
  error(/** @type {Error} */e);
5841
5882
  }
5883
+ /* c8 ignore stop -- see comment above */
5842
5884
  }
5843
5885
 
5844
5886
  /**
5845
5887
  * @returns {void}
5846
5888
  */
5847
5889
  function runQueuedRequest() {
5890
+ /* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
5848
5891
  if (!prepareNextRequest()) {
5849
5892
  return;
5850
5893
  }
5894
+ /* c8 ignore stop -- see comment above */
5851
5895
  launchQueuedOp();
5852
5896
  }
5853
5897
 
@@ -5878,9 +5922,11 @@
5878
5922
  * @returns {void}
5879
5923
  */
5880
5924
  function checkQueueEntry(attemptsLeft) {
5925
+ /* c8 ignore start -- Defensive: only reached if the transaction is independently errored/finished (e.g. an explicit `abort()`) during this function's keep-alive polling wait; not reliably reproducible without a contrived timing race. */
5881
5926
  if (me.__errored || me.__requestsFinished) {
5882
5927
  return;
5883
5928
  }
5929
+ /* c8 ignore stop -- see comment above */
5884
5930
  if (i < me.__requests.length) {
5885
5931
  runQueuedRequest();
5886
5932
  return;
@@ -5902,10 +5948,12 @@
5902
5948
  * @returns {void}
5903
5949
  */
5904
5950
  function executeNextRequest() {
5951
+ /* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
5905
5952
  if (me.__errored || me.__requestsFinished) {
5906
5953
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5907
5954
  return;
5908
5955
  }
5956
+ /* c8 ignore stop -- see comment above */
5909
5957
  i++;
5910
5958
  if (i >= me.__requests.length) {
5911
5959
  checkQueueEntry(keepAliveAttempts);
@@ -5940,31 +5988,34 @@
5940
5988
  * @returns {void}
5941
5989
  */
5942
5990
  function advanceAfterDispatch() {
5991
+ /* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
5943
5992
  if (me.__errored || me.__requestsFinished) {
5944
5993
  return;
5945
5994
  }
5995
+ /* c8 ignore stop -- see comment above */
5946
5996
  i++;
5947
5997
  if (i >= me.__requests.length) {
5948
5998
  checkQueueEntry(keepAliveAttempts);
5949
5999
  return;
5950
6000
  }
5951
6001
  keepAliveAndWait(function () {
5952
- if (me.__errored || me.__requestsFinished) {
5953
- return;
5954
- }
5955
- if (!prepareNextRequest()) {
6002
+ /* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished (or the next request's preparation failed) by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
6003
+ if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
5956
6004
  return;
5957
6005
  }
6006
+ /* c8 ignore stop -- see comment above */
5958
6007
  launchQueuedOp();
5959
6008
  });
5960
6009
  }
5961
6010
  executeNextRequest();
5962
6011
  }, function webSQLError(webSQLErr) {
6012
+ /* c8 ignore start -- Dead code: the underlying websql-configurable driver's `_onTransactionComplete` always passes either `null` or a genuine `Error`/`DOMException` as this callback's argument, never the literal value `true`, under any driver used by the test suite. */
5963
6013
  // @ts-expect-error It's ok
5964
6014
  if (webSQLErr === true) {
5965
6015
  // Not a genuine SQL error
5966
6016
  return;
5967
6017
  }
6018
+ /* c8 ignore stop -- see comment above */
5968
6019
  var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
5969
6020
  me.__abortTransaction(err);
5970
6021
  }, function () {
@@ -5975,18 +6026,25 @@
5975
6026
  // Node
5976
6027
  return;
5977
6028
  }
6029
+ /* c8 ignore start -- Defensive: reaching this callback before `requestsFinished` has already set `__transactionEndCallback` (or finished) would require the underlying driver's own "queue empty" signal to race ahead of this codebase's own request-completion tracking; not observed (nor reliably reproducible) in this test suite, where the latter always wins. */
5978
6030
  if (!me.__transactionEndCallback && !me.__requestsFinished) {
5979
6031
  me.__transactionFinished = true;
5980
6032
  return;
5981
6033
  }
5982
- if (me.__transactionEndCallback && !me.__completed && !me.__transFinishedCbFired) {
5983
- me.__transFinishedCbFired = true;
5984
- me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6034
+ /* c8 ignore stop -- see comment above */
6035
+ /* c8 ignore start -- Dead code in practice: by the time this callback runs, `requestsFinished` has always already set `__transactionEndCallback` (per the guard above), and `__completed`/`__transFinishedCbFired` are always already set true by `requestsFinished`'s own `__callTransFinishedCb` call, so this guard always returns early and the fall-through body below is never reached; not reliably reproducible without a contrived timing race. */
6036
+ if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
6037
+ return;
5985
6038
  }
6039
+ me.__transFinishedCbFired = true;
6040
+ me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6041
+ /* c8 ignore stop -- see comment above */
5986
6042
  }, function (currentTask, err, done, rollback, commit) {
6043
+ /* c8 ignore start -- Defensive: `err` here would mean the underlying WebSQL/SQLite driver reported a genuine unhandled SQL error bubbling out of this transaction's own executed statements -- every `executeSql` error callback in this codebase already handles/reports its own errors (returning `false`), so this is not reliably reproducible without mocking the SQL layer. */
5987
6044
  if (err) {
5988
6045
  return true;
5989
6046
  }
6047
+ /* c8 ignore stop -- see comment above */
5990
6048
  // `readonly` transactions never hold a real SQL transaction open
5991
6049
  // (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
5992
6050
  // them), so there's no commit/rollback round trip to defer --
@@ -6035,6 +6093,7 @@
6035
6093
  */
6036
6094
  function complete() {
6037
6095
  me.__completed = true;
6096
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6038
6097
  if (CFG.DEBUG) {
6039
6098
  console.log('Transaction completed');
6040
6099
  }
@@ -6044,6 +6103,7 @@
6044
6103
  me.dispatchEvent(evt);
6045
6104
  me.__internal = false;
6046
6105
  me.dispatchEvent(createEvent('__complete'));
6106
+ /* c8 ignore start -- Deliberately not tested: throwing from an `oncomplete`/`__complete` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
6047
6107
  } catch (e) {
6048
6108
  me.__internal = false;
6049
6109
  // An error occurred in the "oncomplete" handler.
@@ -6051,6 +6111,7 @@
6051
6111
  // (this may seem odd/bad, but it's how all native IndexedDB implementations work)
6052
6112
  me.__errored = true;
6053
6113
  throw e;
6114
+ /* c8 ignore stop -- see comment above */
6054
6115
  } finally {
6055
6116
  activeTransactions.delete(me);
6056
6117
  me.__storeHandles = {};
@@ -6058,10 +6119,12 @@
6058
6119
  }
6059
6120
  }
6060
6121
  if (me.mode === 'readwrite' || me.mode === 'readonly') {
6122
+ /* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described above (also `c8 ignore`d there), which is not observed in this test suite. */
6061
6123
  if (me.__transactionFinished) {
6062
6124
  complete();
6063
6125
  return;
6064
6126
  }
6127
+ /* c8 ignore stop -- see comment above */
6065
6128
  me.__transactionEndCallback = complete;
6066
6129
  // The underlying SQL driver's own "queue empty" check
6067
6130
  // (`nonstandardTransCb`, above) typically already ran and
@@ -6097,6 +6160,7 @@
6097
6160
  IDBTransaction.prototype.__createRequest = function (source) {
6098
6161
  var me = this;
6099
6162
  var request = IDBRequest.__createInstance();
6163
+ /* c8 ignore next -- Defensive: every call site (via `__addToTransactionQueue` or directly) always passes an explicit `source`, so the `me.db` fallback is not reachable via the public API. */
6100
6164
  request.__source = source !== undefined ? source : me.db;
6101
6165
  request.__transaction = me;
6102
6166
  return request;
@@ -6166,9 +6230,11 @@
6166
6230
  * @returns {void}
6167
6231
  */
6168
6232
  IDBTransaction.prototype.__assertActive = function () {
6233
+ /* c8 ignore start -- Defensive: every call site (via `__addToTransactionQueue`/`__addNonRequestToTransactionQueue`) either already performed the static `IDBTransaction.__assertActive(tx)` check synchronously just beforehand, or queues against a transaction just created fresh (necessarily active), so this redundant instance-level check is not reachable via the public API. */
6169
6234
  if (!this.__active || !this.__handlerActive || this.__committed) {
6170
6235
  throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
6171
6236
  }
6237
+ /* c8 ignore stop -- see comment above */
6172
6238
  };
6173
6239
 
6174
6240
  /**
@@ -6182,6 +6248,7 @@
6182
6248
  }
6183
6249
  };
6184
6250
 
6251
+ /* c8 ignore start -- Dead code: this instance method has no callers anywhere in src/ (confirmed via grep); every real call site uses the static `IDBTransaction.__assertVersionChange(tx)` directly instead. */
6185
6252
  /**
6186
6253
  * @this {IDBTransactionFull}
6187
6254
  * @returns {void}
@@ -6189,6 +6256,7 @@
6189
6256
  IDBTransaction.prototype.__assertVersionChange = function () {
6190
6257
  IDBTransaction.__assertVersionChange(this);
6191
6258
  };
6259
+ /* c8 ignore stop -- see comment above */
6192
6260
 
6193
6261
  /**
6194
6262
  * Returns the specified object store.
@@ -6210,9 +6278,12 @@
6210
6278
  throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
6211
6279
  }
6212
6280
  var store = me.db.__objectStores[objectStoreName];
6281
+ /* c8 ignore start -- Defensive: `me.__objectStoreNames` (checked just above) and `me.db.__objectStores` are always kept in sync by every code path that adds/renames/removes a store, so a name that passes the participation check above should always also be found here; not reliably reproducible via the public API. */
6213
6282
  if (!store) {
6214
6283
  throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
6215
6284
  }
6285
+ /* c8 ignore stop -- see comment above */
6286
+
6216
6287
  if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
6217
6288
  // These latter conditions are to allow store
6218
6289
  // recreation to create new clone object
@@ -6231,10 +6302,12 @@
6231
6302
  IDBTransaction.prototype.__abortTransaction = function (err) {
6232
6303
  var me = this;
6233
6304
  logError('Error', 'An error occurred in a transaction', err);
6305
+ /* c8 ignore start -- Defensive re-entrancy guard: only reached if `__abortTransaction` is invoked a second time on the same transaction after `__errored` is already `true` (e.g. two independent internal error paths racing); not reliably reproducible without a contrived timing race. */
6234
6306
  if (me.__errored) {
6235
6307
  // We've already called "onerror", "onabort", or thrown, so don't do it again.
6236
6308
  return;
6237
6309
  }
6310
+ /* c8 ignore stop -- see comment above */
6238
6311
  me.__errored = true;
6239
6312
  if (me.mode === 'versionchange') {
6240
6313
  // Steps for aborting an upgrade transaction
@@ -6264,19 +6337,16 @@
6264
6337
  if (err !== null) {
6265
6338
  me.__error = err;
6266
6339
  }
6340
+
6341
+ /* c8 ignore start -- Defense in depth: `err` is only ever `null` here via `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)` call, which now checks `__requestsFinished` itself first and throws `InvalidStateError` synchronously before ever reaching this point -- so this guard should not see a non-null `err` in practice. */
6267
6342
  if (me.__requestsFinished && err !== null) {
6268
6343
  // The transaction has already completed, so we can't call "onerror" or "onabort".
6269
- // So throw the error instead. `err` is only ever `null` here via
6270
- // `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
6271
- // call, which now checks `__requestsFinished` itself first and
6272
- // throws `InvalidStateError` synchronously before ever reaching
6273
- // this point -- so this guard is just defense in depth against
6274
- // `err` somehow being `null` some other way, not something this
6275
- // path should see in practice.
6344
+ // So throw the error instead.
6276
6345
  setTimeout(function () {
6277
6346
  throw err;
6278
6347
  }, 0);
6279
6348
  }
6349
+ /* c8 ignore stop -- see comment above */
6280
6350
 
6281
6351
  /**
6282
6352
  * @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
@@ -6285,13 +6355,17 @@
6285
6355
  */
6286
6356
  function abort(tx, errOrResult) {
6287
6357
  if (!tx) {
6358
+ /* c8 ignore next -- Debug-only log; only reached via the no-op `abort()` calls below (rare paths), and requires `CFG.DEBUG` to have any effect anyway. */
6288
6359
  if (CFG.DEBUG) {
6289
6360
  console.log('Rollback not possible due to missing transaction', me);
6290
6361
  }
6362
+ /* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver erroring on the manual `ROLLBACK` executed below (with a result object exposing a numeric `code`) is not reliably reproducible without mocking the SQL layer. */
6291
6363
  } else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
6292
6364
  if (CFG.DEBUG) {
6293
6365
  console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
6294
6366
  }
6367
+ /* c8 ignore stop -- see comment above */
6368
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6295
6369
  } else if (CFG.DEBUG) {
6296
6370
  console.log('Rollback succeeded', me);
6297
6371
  }
@@ -6307,10 +6381,11 @@
6307
6381
  // behaves first-in-first-out with the same timeout so we could
6308
6382
  // just use a `forEach`.
6309
6383
  return promises.then(function () {
6384
+ /* c8 ignore start -- Dead code: the preceding `.filter()` only keeps entries with a truthy `q.req`, and nothing ever resets `q.req` back to a falsy value afterward, so this invariant can't actually be violated. */
6310
6385
  if (!q.req) {
6311
- // TS guard
6312
6386
  throw new Error('Missing request');
6313
6387
  }
6388
+ /* c8 ignore stop -- see comment above */
6314
6389
  q.req.__done = true;
6315
6390
  q.req.__result = undefined;
6316
6391
  q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
@@ -6321,10 +6396,11 @@
6321
6396
  return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
6322
6397
  function (resolve) {
6323
6398
  setTimeout(function () {
6399
+ /* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
6324
6400
  if (!q.req) {
6325
- // TS guard
6326
6401
  throw new Error('Missing request');
6327
6402
  }
6403
+ /* c8 ignore stop -- see comment above */
6328
6404
  q.req.dispatchEvent(reqEvt); // No need to catch errors
6329
6405
  resolve();
6330
6406
  }, 0);
@@ -6344,10 +6420,12 @@
6344
6420
  releaseFinishedTransaction(me);
6345
6421
  }, 0);
6346
6422
  return undefined;
6423
+ /* c8 ignore start -- Diagnostic safety net: nothing in the preceding promise chain normally rejects (the only throws it could catch are the dead invariant-violation checks above), so this handler is not reachable in practice. */
6347
6424
  }).catch(function (err) {
6348
6425
  console.log('Abort error');
6349
6426
  throw err;
6350
6427
  });
6428
+ /* c8 ignore stop -- see comment above */
6351
6429
  }
6352
6430
  me.__transFinishedCb(true, function (rollback) {
6353
6431
  if (rollback && me.__tx) {
@@ -6355,20 +6433,24 @@
6355
6433
  // rollback automatically), but for Node.js, etc., we give chance for
6356
6434
  // manual aborts which would otherwise not work.
6357
6435
  if (me.mode === 'readwrite') {
6436
+ /* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described earlier in this file (also `c8 ignore`d there), which is not observed in this test suite. */
6358
6437
  if (me.__transactionFinished) {
6359
6438
  abort();
6360
6439
  return;
6361
6440
  }
6441
+ /* c8 ignore stop -- see comment above */
6362
6442
  me.__transactionEndCallback = abort;
6363
6443
  return;
6364
6444
  }
6365
6445
  try {
6366
6446
  me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
6447
+ /* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
6367
6448
  } catch (err) {
6368
6449
  // Browser errs when transaction has ended and since it most likely already erred here,
6369
6450
  // we call to abort
6370
6451
  abort();
6371
6452
  }
6453
+ /* c8 ignore stop -- see comment above */
6372
6454
  } else {
6373
6455
  abort(null, {
6374
6456
  code: 0
@@ -6386,6 +6468,7 @@
6386
6468
  if (!(me instanceof IDBTransaction)) {
6387
6469
  throw new TypeError('Illegal invocation');
6388
6470
  }
6471
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6389
6472
  if (CFG.DEBUG) {
6390
6473
  console.log('The transaction was aborted', me);
6391
6474
  }
@@ -6417,6 +6500,7 @@
6417
6500
  if (!me.__active || !me.__handlerActive || me.__committed) {
6418
6501
  throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
6419
6502
  }
6503
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6420
6504
  if (CFG.DEBUG) {
6421
6505
  console.log('The transaction was explicitly committed', me);
6422
6506
  }
@@ -6459,6 +6543,7 @@
6459
6543
  };
6460
6544
 
6461
6545
  // object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
6546
+ /* c8 ignore start -- Dead code: this function has no callers anywhere in src/ (confirmed via grep); object store methods use `IDBTransaction.__assertActive`/`__assertNotFinished` directly instead. */
6462
6547
  /**
6463
6548
  *
6464
6549
  * @param {IDBTransactionFull} tx
@@ -6474,6 +6559,7 @@
6474
6559
  throw err;
6475
6560
  }
6476
6561
  };
6562
+ /* c8 ignore stop -- see comment above */
6477
6563
 
6478
6564
  /**
6479
6565
  *
@@ -7571,7 +7657,7 @@
7571
7657
  return Number.isNaN(t) ? "NaN" : t;
7572
7658
  },
7573
7659
  revive: function revive(e) {
7574
- return "NaN" === e ? new Date(NaN) : new Date(e);
7660
+ return new Date("NaN" === e ? NaN : e);
7575
7661
  }
7576
7662
  }
7577
7663
  },
@@ -8431,9 +8517,12 @@
8431
8517
  }).find(function (preset) {
8432
8518
  return preset && !Array.isArray(preset) && 'filelist' in preset;
8433
8519
  });
8434
- var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist : undefined;
8435
- var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test : undefined;
8436
- var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive : undefined;
8520
+ var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
8521
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8522
+ var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
8523
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
8524
+ var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
8525
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
8437
8526
  var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
8438
8527
  /**
8439
8528
  * @param {unknown} x
@@ -8441,10 +8530,7 @@
8441
8530
  * @returns {boolean}
8442
8531
  */
8443
8532
  test: function test(x, state) {
8444
- if (typeof FileList !== 'undefined') {
8445
- return x instanceof FileList;
8446
- }
8447
- return typeof origTest === 'function' ? origTest(x, state) : false;
8533
+ return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
8448
8534
  },
8449
8535
  /**
8450
8536
  * @param {unknown} x
@@ -8455,10 +8541,12 @@
8455
8541
  if (typeof FileList !== 'undefined') {
8456
8542
  return Reflect.construct(FileList, [x]);
8457
8543
  }
8544
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
8458
8545
  return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
8459
8546
  }
8460
- }) : undefined;
8461
- var typeson = new Typeson().register([fe, customFileList ? {
8547
+ }) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8548
+ var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
8549
+ customFileList ? {
8462
8550
  filelist: customFileList
8463
8551
  } : {}]);
8464
8552
 
@@ -8614,7 +8702,6 @@
8614
8702
  * __unique: boolean,
8615
8703
  * __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
8616
8704
  * __keyPath: import('./Key.js').KeyPath,
8617
- * __recreated?: boolean,
8618
8705
  * __fetchIndexData: (
8619
8706
  * range: Query,
8620
8707
  * opType: "value"|"key"|"count",
@@ -8708,6 +8795,7 @@
8708
8795
  storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
8709
8796
  me.__pendingName = oldName;
8710
8797
  var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
8798
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
8711
8799
  // @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
8712
8800
  _toConsumableArray(objectStore.indexNames).filter(function (indexName) {
8713
8801
  return indexName !== newName;
@@ -8759,7 +8847,7 @@
8759
8847
  }
8760
8848
  });
8761
8849
  /** @type {const} */
8762
- ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName', '__recreated'].forEach(function (p) {
8850
+ ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
8763
8851
  // @ts-expect-error Why is this type "never"?
8764
8852
  idx[p] = index[p];
8765
8853
  });
@@ -8791,11 +8879,12 @@
8791
8879
  var transaction = store.transaction;
8792
8880
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8793
8881
  transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
8794
- var columnExists = idx && (idx.__deleted || idx.__recreated); // This check must occur here rather than earlier as properties may not have been set yet otherwise
8882
+ var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
8795
8883
 
8796
8884
  /** @type {{[key: string]: boolean}} */
8797
8885
  var indexValues = {};
8798
8886
 
8887
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8799
8888
  /**
8800
8889
  * @param {WebSQLTransaction} tx
8801
8890
  * @param {(Error & {code?: number})} err
@@ -8804,6 +8893,7 @@
8804
8893
  function error(tx, err) {
8805
8894
  failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
8806
8895
  }
8896
+ /* c8 ignore stop -- see comment above */
8807
8897
 
8808
8898
  /**
8809
8899
  * @param {WebSQLTransaction} tx
@@ -8853,12 +8943,6 @@
8853
8943
  } else {
8854
8944
  delete index.__pendingCreate;
8855
8945
  delete indexHandle.__pendingCreate;
8856
- if (index.__deleted) {
8857
- delete index.__deleted;
8858
- delete indexHandle.__deleted;
8859
- index.__recreated = true;
8860
- indexHandle.__recreated = true;
8861
- }
8862
8946
  indexValues = {};
8863
8947
  success(store);
8864
8948
  }
@@ -8867,7 +8951,7 @@
8867
8951
  }, /** @type {SqlErrorCallback} */error);
8868
8952
  }
8869
8953
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
8870
- var escapedIndexNameSQL = escapeIndexNameForSQL(index.name);
8954
+ var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
8871
8955
 
8872
8956
  /**
8873
8957
  * @param {WebSQLTransaction} tx
@@ -8919,6 +9003,7 @@
8919
9003
  var transaction = store.transaction;
8920
9004
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8921
9005
  transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
9006
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8922
9007
  /**
8923
9008
  * @param {WebSQLTransaction} tx
8924
9009
  * @param {(Error & {code?: number})} err
@@ -8927,6 +9012,7 @@
8927
9012
  function error(tx, err) {
8928
9013
  failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
8929
9014
  }
9015
+ /* c8 ignore stop -- see comment above */
8930
9016
 
8931
9017
  /**
8932
9018
  * @returns {void}
@@ -8935,7 +9021,6 @@
8935
9021
  // Update the object store's index list
8936
9022
  IDBIndex.__updateIndexList(store, tx, function (store) {
8937
9023
  delete index.__pendingDelete;
8938
- delete index.__recreated;
8939
9024
  index.__deleted = true;
8940
9025
  if (indexHandle) {
8941
9026
  indexHandle.__deleted = true;
@@ -8996,20 +9081,18 @@
8996
9081
  * @param {Query} range
8997
9082
  * @param {"value"|"key"|"count"} opType
8998
9083
  * @param {boolean} nullDisallowed
8999
- * @param {number} [count]
9000
9084
  * @this {IDBIndexFull}
9001
9085
  * @returns {import('./IDBRequest.js').IDBRequestFull}
9002
9086
  */
9003
- IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, count) {
9087
+ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
9004
9088
  var me = this;
9005
- if (count !== undefined) {
9006
- count = enforceRange(count, 'unsigned long');
9007
- }
9008
9089
  IDBIndex.__invalidStateIfDeleted(me);
9009
9090
  IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
9091
+ /* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
9010
9092
  if (me.objectStore.__deleted) {
9011
9093
  throw createDOMException('InvalidStateError', "This index's object store has been deleted");
9012
9094
  }
9095
+ /* c8 ignore stop -- see comment above */
9013
9096
  IDBTransaction.__assertActive(me.objectStore.transaction);
9014
9097
  if (nullDisallowed && isNullish(range)) {
9015
9098
  throw createDOMException('DataError', 'No key or range was specified');
@@ -9019,7 +9102,7 @@
9019
9102
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
9020
9103
  args[_key] = arguments[_key];
9021
9104
  }
9022
- executeFetchIndexData.apply(void 0, [count].concat(_toConsumableArray(fetchArgs), args));
9105
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
9023
9106
  }, undefined, me);
9024
9107
  };
9025
9108
 
@@ -9178,13 +9261,16 @@
9178
9261
  var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
9179
9262
  return colInfo.join(' ');
9180
9263
  });
9264
+ /* c8 ignore next -- Defensive: the sole caller always supplies a non-empty `colInfoToPreserveArr` (seeded with `key`/`value` column info), so the empty-array fallback is unreachable. */
9181
9265
  var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
9266
+ /* c8 ignore next -- Defensive: see comment above. */
9182
9267
  var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
9183
9268
 
9184
9269
  // We could adapt the approach at https://stackoverflow.com/a/8430746/271577
9185
9270
  // to make the approach reusable without passing column names, but it is a bit fragile
9186
9271
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
9187
9272
  store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
9273
+ /* c8 ignore start -- Defensive: only reached if one of the chained `CREATE TABLE`/`INSERT`/`DROP TABLE`/`ALTER TABLE` statements below fails, which is not reliably reproducible without mocking the SQL layer. */
9188
9274
  /**
9189
9275
  * @param {WebSQLTransaction} tx
9190
9276
  * @param {(Error & {code?: number})} err
@@ -9193,6 +9279,7 @@
9193
9279
  function sqlError(tx, err) {
9194
9280
  error(err);
9195
9281
  }
9282
+ /* c8 ignore stop -- see comment above */
9196
9283
  /**
9197
9284
  * @returns {void}
9198
9285
  */
@@ -9201,8 +9288,14 @@
9201
9288
  cb(tx, success);
9202
9289
  return;
9203
9290
  }
9291
+ /* c8 ignore start -- Defensive: `__renameIndex`'s only caller (the `IDBIndex.prototype.name` setter) always supplies a `cb`, so this fallback is dead with the current call graph. */
9204
9292
  success();
9205
9293
  }
9294
+ /* c8 ignore stop -- see comment above */
9295
+ if (!CFG.useSQLiteIndexes) {
9296
+ finish();
9297
+ return;
9298
+ }
9206
9299
  // See https://www.sqlite.org/lang_altertable.html#otheralter
9207
9300
  // We don't query for indexes as we already have the info
9208
9301
  // This approach has the advantage of auto-deleting indexes via the DROP TABLE
@@ -9226,10 +9319,6 @@
9226
9319
  console.log(sql);
9227
9320
  }
9228
9321
  tx.executeSql(sql, [], function (tx) {
9229
- if (!CFG.useSQLiteIndexes) {
9230
- finish();
9231
- return;
9232
- }
9233
9322
  var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
9234
9323
  .map(function (escapedIndexNameSQL) {
9235
9324
  return new SyncPromise(function (resolve, reject) {
@@ -9238,13 +9327,16 @@
9238
9327
  // if (CFG.DEBUG) { console.log(sql); }
9239
9328
  // tx.executeSql(sql, [], function () {
9240
9329
  var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
9330
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
9241
9331
  if (CFG.DEBUG) {
9242
9332
  console.log(sql);
9243
9333
  }
9244
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9334
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9335
+ /** @type {SqlErrorCallback} */
9245
9336
  function (tx, err) {
9246
9337
  reject(err);
9247
- });
9338
+ }
9339
+ /* c8 ignore stop -- see comment above */);
9248
9340
  // }, function (tx, err) {
9249
9341
  // reject(err);
9250
9342
  // });
@@ -9262,19 +9354,25 @@
9262
9354
  if (CFG.DEBUG) {
9263
9355
  console.log(sql);
9264
9356
  }
9265
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9357
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9358
+ /** @type {SqlErrorCallback} */
9266
9359
  function (tx, err) {
9267
9360
  reject(err);
9268
- });
9269
- }, /** @type {SqlErrorCallback} */
9361
+ }
9362
+ /* c8 ignore stop -- see comment above */);
9363
+ }, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9364
+ /** @type {SqlErrorCallback} */
9270
9365
  function (tx, err) {
9271
9366
  reject(err);
9272
- });
9367
+ }
9368
+ /* c8 ignore stop -- see comment above */);
9273
9369
  }));
9274
9370
  SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
9275
9371
  error).catch(function (err) {
9372
+ /* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
9276
9373
  console.log('Index rename error');
9277
9374
  throw err;
9375
+ /* c8 ignore stop -- see comment above */
9278
9376
  });
9279
9377
  }, /** @type {SqlErrorCallback} */sqlError);
9280
9378
  }, /** @type {SqlErrorCallback} */sqlError);
@@ -9303,7 +9401,6 @@
9303
9401
  /* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
9304
9402
 
9305
9403
  /**
9306
- * @param {number|null} count
9307
9404
  * @param {boolean} unboundedDisallowed
9308
9405
  * @param {IDBIndexFull} index
9309
9406
  * @param {boolean} hasKey
@@ -9320,12 +9417,9 @@
9320
9417
  * @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
9321
9418
  * @returns {void}
9322
9419
  */
9323
- function executeFetchIndexData(count, unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9420
+ function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9324
9421
  if (unboundedDisallowed) {
9325
- count = 1;
9326
- }
9327
- if (count) {
9328
- sql.push('LIMIT', String(count));
9422
+ sql.push('LIMIT', '1');
9329
9423
  }
9330
9424
  var isCount = opType === 'count';
9331
9425
  if (CFG.DEBUG) {
@@ -9363,41 +9457,48 @@
9363
9457
  var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
9364
9458
  var encodedKey = _encode(range, index.multiEntry);
9365
9459
  var _loop = function _loop() {
9366
- var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9367
- var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9368
- _decode(row[escapedIndexNameForKeyCol]);
9369
- var record;
9370
- if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9371
- /**
9372
- * @param {import('./Key.js').ValueType} check
9373
- * @returns {boolean}
9374
- */
9375
- function (check) {
9376
- return rowKey.includes(check);
9377
- }) ||
9378
- // More precise than our SQL
9379
- isMultiEntryMatch(
9380
- // Added `JSON.stringify` as was having problems with
9381
- // `JSON.stringify` encoding added to nested
9382
- // array keys
9383
- JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9384
- recordCount++;
9385
- record = row;
9386
- } else if (!hasKey && !multiChecks) {
9387
- if (rowKey !== undefined) {
9388
- recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9460
+ var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9461
+ var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9462
+ _decode(row[escapedIndexNameForKeyCol]);
9463
+ var record;
9464
+ if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9465
+ /**
9466
+ * @param {import('./Key.js').ValueType} check
9467
+ * @returns {boolean}
9468
+ */
9469
+ function (check) {
9470
+ return rowKey.includes(check);
9471
+ }) ||
9472
+ // More precise than our SQL
9473
+ isMultiEntryMatch(
9474
+ // Added `JSON.stringify` as was having problems with
9475
+ // `JSON.stringify` encoding added to nested
9476
+ // array keys
9477
+ JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9478
+ recordCount++;
9389
9479
  record = row;
9480
+ } else if (!hasKey && !multiChecks) {
9481
+ if (rowKey !== undefined) {
9482
+ recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9483
+ record = row;
9484
+ }
9390
9485
  }
9391
- }
9392
- if (record) {
9486
+ /* c8 ignore start -- Defensive: the SQL `LIKE` clause is a coarse pre-filter and this precise re-check in JS is meant to catch its false positives, but the encoding's per-character dash-prefix plus trailing-space delimiter (see `Key.js` string encoding) and fixed-length number encoding prevent one encoded value from ever being a spurious substring of another, so a `LIKE` hit always also passes this check in practice. */
9487
+ if (!record) {
9488
+ return 0; // continue
9489
+ }
9490
+ /* c8 ignore stop -- see comment above */
9491
+
9393
9492
  records.push(decode$1(record));
9394
9493
  if (unboundedDisallowed) {
9395
9494
  return 1; // break
9396
9495
  }
9397
- }
9398
- };
9496
+ },
9497
+ _ret;
9399
9498
  for (var i = 0; i < data.rows.length; i++) {
9400
- if (_loop()) break;
9499
+ _ret = _loop();
9500
+ if (_ret === 0) continue;
9501
+ if (_ret === 1) break;
9401
9502
  }
9402
9503
  } else {
9403
9504
  for (var _i = 0; _i < data.rows.length; _i++) {
@@ -9411,8 +9512,16 @@
9411
9512
  if (isCount) {
9412
9513
  success(recordCount);
9413
9514
  } else if (recordCount === 0) {
9515
+ // `unboundedDisallowed` is always `true` here: this function is only reached (for
9516
+ // non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
9517
+ // through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
9518
+ // different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
9519
+ // (returning `[]` here) is unreachable given current callers.
9520
+ /* c8 ignore next -- see comment above */
9414
9521
  success(unboundedDisallowed ? undefined : []);
9415
9522
  } else {
9523
+ // `unboundedDisallowed` is always `true` here; see comment above.
9524
+ /* c8 ignore next -- see comment above */
9416
9525
  success(unboundedDisallowed ? records[0] : records);
9417
9526
  }
9418
9527
  }, /** @type {SqlErrorCallback} */error);
@@ -9656,6 +9765,7 @@
9656
9765
  tx.executeSql(sql, sqlValues, function (tx) {
9657
9766
  // This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
9658
9767
  var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
9768
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
9659
9769
  if (CFG.DEBUG) {
9660
9770
  console.log(sql);
9661
9771
  }
@@ -9664,8 +9774,10 @@
9664
9774
  success();
9665
9775
  });
9666
9776
  }, function (tx, err) {
9777
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9667
9778
  error(err);
9668
9779
  return false;
9780
+ /* c8 ignore stop -- see comment above */
9669
9781
  });
9670
9782
  });
9671
9783
  }
@@ -9739,6 +9851,7 @@
9739
9851
  storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
9740
9852
  }
9741
9853
  transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
9854
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9742
9855
  /**
9743
9856
  * @param {WebSQLTransaction} tx
9744
9857
  * @param {(Error & {code?: number})} [err]
@@ -9751,6 +9864,8 @@
9751
9864
  failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
9752
9865
  return false;
9753
9866
  }
9867
+ /* c8 ignore stop -- see comment above */
9868
+
9754
9869
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
9755
9870
  // key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
9756
9871
  var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
@@ -9805,6 +9920,7 @@
9805
9920
 
9806
9921
  // Remove the object store from WebSQL
9807
9922
  transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
9923
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9808
9924
  /**
9809
9925
  * @param {WebSQLTransaction} tx
9810
9926
  * @param {(Error & {code?: number})} [err]
@@ -9817,6 +9933,8 @@
9817
9933
  failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
9818
9934
  return false;
9819
9935
  }
9936
+ /* c8 ignore stop -- see comment above */
9937
+
9820
9938
  tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
9821
9939
  if (data.rows.length > 0) {
9822
9940
  tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
@@ -9996,13 +10114,15 @@
9996
10114
  return;
9997
10115
  }
9998
10116
  var indexKeyValue = indexKey.value;
10117
+ /* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
9999
10118
  if (indexKeyValue === undefined) {
10000
10119
  resolve(undefined);
10001
10120
  return;
10002
10121
  }
10122
+ /* c8 ignore stop -- see comment above */
10003
10123
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
10004
10124
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
10005
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10125
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
10006
10126
  if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
10007
10127
  resolve(undefined);
10008
10128
  return;
@@ -10082,16 +10202,18 @@
10082
10202
  * @returns {void}
10083
10203
  */
10084
10204
  function setIndexInfo(index) {
10205
+ /* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
10085
10206
  if (indexKeyValue === undefined) {
10086
10207
  return;
10087
10208
  }
10209
+ /* c8 ignore stop -- see comment above */
10088
10210
  paramMap[index.__currentName] = /** @type {string} */
10089
10211
  _encode(indexKeyValue, index.multiEntry);
10090
10212
  }
10091
10213
  if (index.unique) {
10092
10214
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
10093
10215
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
10094
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10216
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
10095
10217
  if (key === undefined) {
10096
10218
  setIndexInfo(index);
10097
10219
  resolve(undefined);
@@ -10182,6 +10304,7 @@
10182
10304
  _me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
10183
10305
  ky = _me$__validateKeyAndV2[0],
10184
10306
  clonedValue = _me$__validateKeyAndV2[1];
10307
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10185
10308
  // @ts-ignore -- Private API
10186
10309
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
10187
10310
  return request;
@@ -10213,6 +10336,7 @@
10213
10336
  _me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
10214
10337
  ky = _me$__validateKeyAndV4[0],
10215
10338
  clonedValue = _me$__validateKeyAndV4[1];
10339
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10216
10340
  // @ts-ignore -- Private API
10217
10341
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
10218
10342
  return request;
@@ -10239,8 +10363,10 @@
10239
10363
  }
10240
10364
  cb(tx);
10241
10365
  }, function (tx, err) {
10366
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10242
10367
  error(err);
10243
10368
  return false;
10369
+ /* c8 ignore stop -- see comment above */
10244
10370
  });
10245
10371
  };
10246
10372
 
@@ -10349,16 +10475,20 @@
10349
10475
  return;
10350
10476
  }
10351
10477
  ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
10478
+ /* c8 ignore start -- Defensive: catches unexpected decode failures (e.g. corrupted stored data); not reliably reproducible via the public API since encode/decode are always paired and never write undecodable data. */
10352
10479
  } catch (e) {
10353
10480
  // If no result is returned, or error occurs when parsing JSON
10354
10481
  if (CFG.DEBUG) {
10355
10482
  console.log(e);
10356
10483
  }
10357
10484
  }
10485
+ /* c8 ignore stop -- see comment above */
10358
10486
  success(ret);
10359
10487
  }, function (tx, err) {
10488
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10360
10489
  error(err);
10361
10490
  return false;
10491
+ /* c8 ignore stop -- see comment above */
10362
10492
  });
10363
10493
  }, undefined, me);
10364
10494
  };
@@ -10470,8 +10600,10 @@
10470
10600
  });
10471
10601
  success();
10472
10602
  }, function (tx, err) {
10603
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10473
10604
  error(err);
10474
10605
  return false;
10606
+ /* c8 ignore stop -- see comment above */
10475
10607
  });
10476
10608
  }, undefined, me);
10477
10609
  };
@@ -10499,8 +10631,10 @@
10499
10631
  });
10500
10632
  success();
10501
10633
  }, function (tx, err) {
10634
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10502
10635
  error(err);
10503
10636
  return false;
10637
+ /* c8 ignore stop -- see comment above */
10504
10638
  });
10505
10639
  }, undefined, me);
10506
10640
  };
@@ -10835,7 +10969,7 @@
10835
10969
  if (keyPath !== null && !isValidKeyPath(keyPath)) {
10836
10970
  throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
10837
10971
  }
10838
- if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
10972
+ if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
10839
10973
  throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
10840
10974
  }
10841
10975
  var autoInc = createOptions.autoIncrement;
@@ -10984,7 +11118,6 @@
10984
11118
  }
10985
11119
  };
10986
11120
 
10987
- // Todo __forceClose: Add tests for `__forceClose`
10988
11121
  /**
10989
11122
  *
10990
11123
  * @param {string} msg
@@ -10993,23 +11126,39 @@
10993
11126
  */
10994
11127
  IDBDatabase.prototype.__forceClose = function (msg) {
10995
11128
  var me = this;
11129
+ // `close()` (below) resets `me.__transactions` to `[]`, so the
11130
+ // transactions to abort -- and the total count the completion check
11131
+ // below needs -- must be captured before calling it, not read back off
11132
+ // `me.__transactions` afterward.
11133
+ var transactions = me.__transactions;
10996
11134
  me.close();
11135
+
11136
+ /**
11137
+ * @returns {void}
11138
+ */
11139
+ function dispatchClose() {
11140
+ // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
11141
+ var evt = createEvent('close');
11142
+ setTimeout(function () {
11143
+ me.dispatchEvent(evt);
11144
+ }, 0);
11145
+ }
11146
+ if (!transactions.length) {
11147
+ dispatchClose();
11148
+ return;
11149
+ }
10997
11150
  var ct = 0;
10998
- me.__transactions.forEach(function (trans) {
11151
+ transactions.forEach(function (trans) {
10999
11152
  // eslint-disable-next-line camelcase -- Clear API
11000
11153
  trans.on__abort = function () {
11001
11154
  ct++;
11002
- if (ct === me.__transactions.length) {
11003
- // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
11004
- var evt = createEvent('close');
11005
- setTimeout(function () {
11006
- me.dispatchEvent(evt);
11007
- }, 0);
11155
+ if (ct !== transactions.length) {
11156
+ return;
11008
11157
  }
11158
+ dispatchClose();
11009
11159
  };
11010
11160
  trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
11011
11161
  });
11012
- me.__transactions = [];
11013
11162
  };
11014
11163
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
11015
11164
  defineOuterInterface(IDBDatabase.prototype, listeners);
@@ -11176,6 +11325,7 @@
11176
11325
  return undefined;
11177
11326
  }
11178
11327
  var e = /** @type {Event & IDBVersionChangeEvent} */
11328
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11179
11329
  // @ts-ignore It's ok; needed under some TS versions
11180
11330
  new IDBVersionChangeEvent('versionchange', {
11181
11331
  oldVersion: oldVersion,
@@ -11223,6 +11373,7 @@
11223
11373
  }
11224
11374
  };
11225
11375
  var e = /** @type {Event & IDBVersionChangeEvent} */
11376
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11226
11377
  // @ts-ignore It's ok; needed under some TS versions
11227
11378
  new IDBVersionChangeEvent('blocked', {
11228
11379
  oldVersion: oldVersion,
@@ -11283,6 +11434,13 @@
11283
11434
 
11284
11435
  /** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
11285
11436
  var sysdb;
11437
+ // Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
11438
+ // later change to that config (e.g. toggling in-memory mode on and back
11439
+ // off) causes `sysdb` to be recreated for the new setting rather than
11440
+ // staying pinned, forever, to whatever it was the first time any database
11441
+ // was created in the process.
11442
+ /** @type {string|null|undefined} */
11443
+ var sysdbMemoryDatabaseSetting;
11286
11444
  var nameCounter = 0;
11287
11445
 
11288
11446
  /**
@@ -11364,12 +11522,20 @@
11364
11522
  function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
11365
11523
  var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
11366
11524
  if (useMemoryDatabase) {
11525
+ /* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
11526
+ was initialized as an empty placeholder by `open()`'s connection-queue
11527
+ setup (`addRequestToConnectionQueue`, above `openDB`) but never
11528
+ populated with an actual instance -- e.g. `__openDatabase` throwing
11529
+ after a `dbVersions` row already existed for `name` from an earlier,
11530
+ successful `open()` -- or if `name` was never added to the cache at
11531
+ all. Not reachable via normal, non-tampered API usage. */
11367
11532
  var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
11368
11533
  if (!latestSQLiteDBCached) {
11369
11534
  console.warn('Could not find a memory database instance to delete.');
11370
11535
  databaseDeleted();
11371
11536
  return;
11372
11537
  }
11538
+ /* c8 ignore stop -- see comment above */
11373
11539
  var _sqliteDB = latestSQLiteDBCached._db;
11374
11540
  if (!_sqliteDB || !_sqliteDB.close) {
11375
11541
  console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
@@ -11423,15 +11589,24 @@
11423
11589
  tables.item(i).name)), [], function () {
11424
11590
  deleteTables(i + 1);
11425
11591
  }, function () {
11592
+ /* c8 ignore start -- Defensive: continues deleting the rest
11593
+ even if this specific store's table is already gone (e.g.
11594
+ duplicate `__sys__` rows for the same escaped table name, or
11595
+ external tampering); not reachable via normal API usage. */
11426
11596
  deleteTables(i + 1);
11427
11597
  return false;
11598
+ /* c8 ignore stop -- see comment above */
11428
11599
  });
11429
11600
  }
11430
11601
  })(0);
11431
11602
  }, function () {
11432
- // __sys__ table does not exist, but that does not mean delete did not happen
11603
+ /* c8 ignore start -- `__sys__` is always created by `openDB` before this
11604
+ database's `dbVersions` row (a prerequisite for reaching this code at
11605
+ all) is ever inserted; only reachable if the file was tampered with/
11606
+ removed externally afterward. */
11433
11607
  databaseDeleted();
11434
11608
  return false;
11609
+ /* c8 ignore stop -- see comment above */
11435
11610
  });
11436
11611
  });
11437
11612
  }
@@ -11462,9 +11637,11 @@
11462
11637
  }
11463
11638
  failure(er);
11464
11639
  }
11465
- if (sysdb) {
11640
+ if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
11466
11641
  success();
11467
11642
  } else {
11643
+ // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
11644
+ sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
11468
11645
  // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
11469
11646
  sysdb = __openDatabase(typeof CFG.memoryDatabase === 'string' ? CFG.memoryDatabase : joinPath(typeof CFG.sysDatabaseBasePath === 'string' ? CFG.sysDatabaseBasePath : CFG.databaseBasePath || '', '__sysdb__' + (CFG.addSQLiteExtension !== false ? '.sqlite' : '')), '1', 'System Database', CFG.DEFAULT_DB_SIZE);
11470
11647
  sysdb.transaction(function (systx) {
@@ -11644,6 +11821,17 @@
11644
11821
  * @returns {void}
11645
11822
  */
11646
11823
  var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11824
+ /* c8 ignore start -- This initial definition is always
11825
+ superseded before ever being invoked: the `sysdb.transaction(...)`
11826
+ call below always reaches its `nonstandardTransCb` (4th arg)
11827
+ after this same SQL batch finishes running (since `dbCreateError`
11828
+ always reports errors as "handled" and this call site is never
11829
+ a `readTransaction`), which unconditionally reassigns
11830
+ `sysdbFinishedCb` to a version using the library's own
11831
+ `rollback`/`commit` -- well before any real invocation from
11832
+ `on__beforecomplete`/`on__preabort`/`on__abort` below (those only
11833
+ fire once the upgrade transaction itself later completes/aborts).
11834
+ Kept as a defensive fallback in case that invariant ever changes. */
11647
11835
  if (err) {
11648
11836
  /**
11649
11837
  * @param {unknown} [errorToShow]
@@ -11692,6 +11880,7 @@
11692
11880
  }
11693
11881
  // In browser, should auto-commit
11694
11882
  cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11883
+ /* c8 ignore stop -- see comment above */
11695
11884
  };
11696
11885
  sysdb.transaction(function (systx) {
11697
11886
  /**
@@ -11699,6 +11888,7 @@
11699
11888
  */
11700
11889
  function versionSet() {
11701
11890
  var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
11891
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11702
11892
  // @ts-ignore It's ok; needed under some TS versions
11703
11893
  new IDBVersionChangeEvent('upgradeneeded', {
11704
11894
  oldVersion: oldVersion,
@@ -11824,9 +12014,17 @@
11824
12014
  // eslint-disable-next-line camelcase -- Clear API
11825
12015
  req.transaction.on__complete = function () {
11826
12016
  var pos = connection.__transactions.indexOf(req.transaction);
12017
+ // `req.transaction` (the versionchange transaction) is created
12018
+ // directly via `IDBTransaction.__createInstance` above, never
12019
+ // via `IDBDatabase.prototype.transaction()` (the only place
12020
+ // that pushes onto `connection.__transactions`), so `pos` is
12021
+ // always -1 here.
12022
+ /* c8 ignore start -- see comment above */
11827
12023
  if (pos !== -1) {
11828
12024
  connection.__transactions.splice(pos, 1);
11829
12025
  }
12026
+ /* c8 ignore stop -- see comment above */
12027
+
11830
12028
  if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
11831
12029
  req.__transaction = null;
11832
12030
  var err = createDOMException('AbortError', 'The connection has been closed.');
@@ -11862,9 +12060,16 @@
11862
12060
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
11863
12061
  }
11864
12062
  }, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
12063
+ // Defensive fallback, not reachable in practice: same reasoning
12064
+ // as `deleteDatabase`'s own `nonstandardTransCb` below
12065
+ // (`currentTask.readOnly` is always false here, and
12066
+ // `dbCreateError` always returns `false`, so `err` is never
12067
+ // truthy either).
12068
+ /* c8 ignore start -- see comment above */
11865
12069
  if (currentTask.readOnly || err) {
11866
12070
  return true;
11867
12071
  }
12072
+ /* c8 ignore stop -- see comment above */
11868
12073
  sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11869
12074
  if (err) {
11870
12075
  rollback(err,
@@ -11879,7 +12084,17 @@
11879
12084
  } else {
11880
12085
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
11881
12086
  }
11882
- }, function (sqlErr) {
12087
+ },
12088
+ // Deeply-nested defensive path: only reached if
12089
+ // the *revert* SQL (undoing the `dbVersions`
12090
+ // INSERT/UPDATE after the original version-
12091
+ // upgrade itself already failed) fails a
12092
+ // *second* time. Not feasibly triggerable
12093
+ // without fault-injecting the underlying SQL
12094
+ // driver on this specific, already-failing
12095
+ // revert statement.
12096
+ function (sqlErr) {
12097
+ /* c8 ignore next 2 -- see comment above */
11883
12098
  isRevertingSysdb = false;
11884
12099
  cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11885
12100
  }, function () {
@@ -11895,8 +12110,20 @@
11895
12110
  });
11896
12111
  return undefined;
11897
12112
  }).catch(function (err) {
12113
+ /* c8 ignore start -- Purely defensive: nothing in
12114
+ `triggerAnyVersionChangeAndBlockedEvents`'s promise chain
12115
+ (or this `.then()` continuation above) ever rejects/throws
12116
+ under any reachable application-level condition -- all of
12117
+ its continuations resolve cleanly, and its `dispatchEvent`
12118
+ calls are deliberately fire-and-forget ("No need to catch
12119
+ errors"), running inside a `setTimeout` where a listener
12120
+ throwing becomes an uncaught exception in that macrotask
12121
+ rather than a promise rejection here. This exists solely
12122
+ to surface a truly-unexpected internal bug via the console
12123
+ before rethrowing, not to handle a real, testable error path. */
11898
12124
  console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
11899
12125
  throw err;
12126
+ /* c8 ignore stop -- see comment above */
11900
12127
  });
11901
12128
  } else {
11902
12129
  finishRequest();
@@ -11924,11 +12151,19 @@
11924
12151
  if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
11925
12152
  db = websqlDBCache[name][version];
11926
12153
  } else {
11927
- db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
12154
+ db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
11928
12155
  if (useDatabaseCache) {
12156
+ /* c8 ignore start -- Defensive: by the time `openDB` runs,
12157
+ `websqlDBCache[name]` has always already been created by
12158
+ `addRequestToConnectionQueue`'s own callback above (guarded
12159
+ by this same `useDatabaseCache` condition), which always
12160
+ runs first and unconditionally ensures the entry exists
12161
+ before ever calling `openDB`. Kept as a safety net in case
12162
+ that invariant ever changes. */
11929
12163
  if (!Object.hasOwn(websqlDBCache, name)) {
11930
12164
  websqlDBCache[name] = {};
11931
12165
  }
12166
+ /* c8 ignore stop -- see comment above */
11932
12167
  websqlDBCache[name][version] = db;
11933
12168
  }
11934
12169
  }
@@ -12079,6 +12314,7 @@
12079
12314
  req.__result = undefined;
12080
12315
  req.__done = true;
12081
12316
  var e = /** @type {Event & IDBVersionChangeEvent} */
12317
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12082
12318
  // @ts-ignore It's ok; needed under some TS versions
12083
12319
  new IDBVersionChangeEvent('success', {
12084
12320
  oldVersion: version,
@@ -12121,9 +12357,23 @@
12121
12357
  cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
12122
12358
  }, dbError);
12123
12359
  }, dbError, undefined, function (currentTask, err, done, rollback, commit) {
12360
+ /* c8 ignore start -- Defensive fallback, not reachable in
12361
+ practice: `currentTask.readOnly` is always `false` here
12362
+ (this callback is only ever attached to the writable
12363
+ `sysdb.transaction(...)` call above, never to a
12364
+ `sysdb.readTransaction(...)`), and `err` can only be
12365
+ truthy if the `DELETE FROM dbVersions` statement's own
12366
+ error callback (`dbError`) reports the failure back to
12367
+ `websql-configurable` as unhandled -- but `dbError`
12368
+ deliberately always `return`s `false`, which tells the
12369
+ library the error was already handled (and to keep
12370
+ `err` falsy here), precisely so this custom
12371
+ `sysdbFinishedCbDelete` rollback/commit path below is
12372
+ used instead of the library's own default rollback. */
12124
12373
  if (currentTask.readOnly || err) {
12125
12374
  return true;
12126
12375
  }
12376
+ /* c8 ignore stop -- see comment above */
12127
12377
  sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
12128
12378
  if (err) {
12129
12379
  rollback(err, cb);
@@ -12249,10 +12499,9 @@
12249
12499
  };
12250
12500
 
12251
12501
  /**
12252
- * @todo forceClose: Test
12253
12502
  * This is provided to facilitate unit-testing of the
12254
12503
  * closing of a database connection with a forced flag:
12255
- * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>
12504
+ * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
12256
12505
  * @param {string} dbName
12257
12506
  * @param {Integer} connIdx
12258
12507
  * @param {string} msg
@@ -12353,6 +12602,7 @@
12353
12602
  * @this {IDBRecordFull}
12354
12603
  */
12355
12604
  function IDBRecord() {
12605
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12356
12606
  // @ts-ignore Should be ok
12357
12607
  this[Symbol.toStringTag] = 'IDBRecord';
12358
12608
  this.__key = key;
@@ -12389,6 +12639,7 @@
12389
12639
  if (!(this instanceof IDBRecordAlias)) {
12390
12640
  throw new TypeError('Illegal invocation');
12391
12641
  }
12642
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12392
12643
  // @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
12393
12644
  return this['__' + prop];
12394
12645
  });
@@ -12731,6 +12982,7 @@
12731
12982
  success(undefined, undefined, undefined);
12732
12983
  }
12733
12984
  }, function (tx, err) {
12985
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
12734
12986
  if (CFG.DEBUG) {
12735
12987
  console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
12736
12988
  }
@@ -12914,7 +13166,16 @@
12914
13166
  if (a.key > b.key) {
12915
13167
  return me.direction === 'prev' ? -1 : 1;
12916
13168
  }
13169
+ /* c8 ignore start -- Defensive: only reachable if two matches
13170
+ in the same batch shared both the same `matchingKey` and
13171
+ the same primary `key`, which would require the same
13172
+ record's multi-entry array to contain a duplicate value.
13173
+ `Key.js`'s array-to-key conversion already drops duplicate
13174
+ values when a multi-entry index entry is built, so this
13175
+ can never happen in practice; kept only to satisfy the
13176
+ `Array.prototype.sort` comparator contract. */
12917
13177
  return 0;
13178
+ /* c8 ignore stop -- see comment above */
12918
13179
  });
12919
13180
  me.__prefetchedIndex = 0;
12920
13181
  me.__prefetchedData = {
@@ -12933,13 +13194,19 @@
12933
13194
  console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
12934
13195
  }
12935
13196
  me.__decode(rows[0], success);
12936
- }, function (tx, err) {
13197
+ },
13198
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13199
+ execution error (e.g. I/O error, corruption) while querying for
13200
+ multi-entry cursor matches; not reliably reproducible without
13201
+ mocking the SQL layer. */
13202
+ function (tx, err) {
12937
13203
  if (CFG.DEBUG) {
12938
13204
  console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
12939
13205
  }
12940
13206
  error(err);
12941
13207
  return false;
12942
13208
  });
13209
+ /* c8 ignore stop -- see comment above */
12943
13210
  }
12944
13211
  runQuery();
12945
13212
  };
@@ -13048,6 +13315,7 @@
13048
13315
  * @returns {void}
13049
13316
  */
13050
13317
  IDBCursor.prototype.__invalidateCache = function () {
13318
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13051
13319
  // @ts-ignore Why is this not being found?; needed under some TS versions
13052
13320
  this.__prefetchedData = null;
13053
13321
  this.__multiEntryExhausted = false;
@@ -13072,7 +13340,7 @@
13072
13340
  convertValueToKeyRethrowingAndIfInvalid(key);
13073
13341
  var cmpResult = cmp(key, me.key);
13074
13342
  if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
13075
- throw createDOMException('DataError', 'Cannot ' + (advanceState ? 'advance' : 'continue') + ' the cursor in an unexpected direction');
13343
+ throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
13076
13344
  }
13077
13345
  }
13078
13346
  this.__continueFinish(key, undefined, advanceState);
@@ -13329,6 +13597,7 @@
13329
13597
  // continuation logic in `__findBasic` to see this update's
13330
13598
  // effect on ordering (see "Modify records during cursor
13331
13599
  // iteration" in idbcursor_update_index.any.js).
13600
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13332
13601
  // @ts-ignore -- API (not erring in TS 6)
13333
13602
  IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
13334
13603
  }
@@ -13378,14 +13647,33 @@
13378
13647
  // We don't invalidate the cache (as we don't access it anymore
13379
13648
  // and it will set the index off)
13380
13649
  success(undefined);
13650
+ /* c8 ignore start -- Defensive: `__find` (invoked just above) has
13651
+ already confirmed a row exists for this primary key within the
13652
+ same transaction queue, so `rowsAffected` should always be 1 in
13653
+ normal usage. This branch would only be reached if the underlying
13654
+ row were removed by another request queued in the same
13655
+ transaction between `__find`'s check and this DELETE actually
13656
+ running (e.g. deleting the same record directly via the object
13657
+ store while a cursor over it is mid-iteration); attempts to
13658
+ construct such a scenario instead trigger a transaction abort
13659
+ (`AbortError`) before this callback ever runs, since the default
13660
+ action of an unhandled request error is to abort the
13661
+ transaction. */
13381
13662
  } else {
13382
13663
  // @ts-expect-error Apparently ok
13383
13664
  error('No rows with key found' + key);
13384
13665
  }
13385
- }, function (tx, data) {
13666
+ /* c8 ignore stop -- see comment above */
13667
+ },
13668
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13669
+ execution error (e.g. I/O error, corruption) while deleting the
13670
+ current row; not reliably reproducible without mocking the SQL
13671
+ layer. */
13672
+ function (tx, data) {
13386
13673
  error(data);
13387
13674
  return false;
13388
13675
  });
13676
+ /* c8 ignore stop -- see comment above */
13389
13677
  }, error);
13390
13678
  }, undefined, me);
13391
13679
  };
@@ -13796,7 +14084,7 @@
13796
14084
  setConfig(initialConfig);
13797
14085
  }
13798
14086
  var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
13799
- /** @type {unknown} */idb || globalThis || {};
14087
+ /** @type {unknown} */idb || globalThis;
13800
14088
  /**
13801
14089
  * @param {string} name
13802
14090
  * @param {unknown} value
@@ -13887,80 +14175,87 @@
13887
14175
  });
13888
14176
  }
13889
14177
  var shimIDBFactory = IDBFactory;
13890
- if (CFG.win.openDatabase !== undefined) {
13891
- shimIndexedDB.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
13892
- // Polyfill ALL of IndexedDB, using WebSQL
13893
- shim('indexedDB', shimIndexedDB, {
13894
- enumerable: true,
13895
- configurable: true,
13896
- get: function get() {
13897
- if (this !== IDB && !isNullish(this) && !this.shimNS) {
13898
- // Latter is hack for test environment
13899
- throw new TypeError('Illegal invocation');
13900
- }
13901
- return shimIndexedDB;
14178
+ if (CFG.win.openDatabase === undefined) {
14179
+ return;
14180
+ }
14181
+ shimIndexedDB.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
14182
+ // Polyfill ALL of IndexedDB, using WebSQL
14183
+ shim('indexedDB', shimIndexedDB, {
14184
+ enumerable: true,
14185
+ configurable: true,
14186
+ get: function get() {
14187
+ if (this !== IDB && !isNullish(this) && !this.shimNS) {
14188
+ // Latter is hack for test environment
14189
+ throw new TypeError('Illegal invocation');
13902
14190
  }
13903
- });
13904
- /** @type {[string, unknown][]} */
13905
- [['IDBFactory', shimIDBFactory], ['IDBDatabase', IDBDatabase], ['IDBObjectStore', IDBObjectStore], ['IDBIndex', IDBIndex], ['IDBTransaction', IDBTransaction], ['IDBCursor', IDBCursor], ['IDBCursorWithValue', IDBCursorWithValue], ['IDBRecord', IDBRecord], ['IDBKeyRange', IDBKeyRange], ['IDBRequest', IDBRequest], ['IDBOpenDBRequest', IDBOpenDBRequest], ['IDBVersionChangeEvent', IDBVersionChangeEvent]].forEach(function (_ref3) {
13906
- var _ref4 = _slicedToArray(_ref3, 2),
13907
- prop = _ref4[0],
13908
- obj = _ref4[1];
13909
- shim(prop, obj, {
13910
- enumerable: false,
13911
- configurable: true
13912
- });
13913
- });
13914
- // For Node environments
13915
- if (CFG.fs) {
13916
- setFS(CFG.fs);
14191
+ return shimIndexedDB;
13917
14192
  }
13918
- if (CFG.fullIDLSupport) {
13919
- // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
13920
-
13921
- Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
13922
- Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
13923
- Object.setPrototypeOf(IDBDatabase, EventTarget);
13924
- Object.setPrototypeOf(IDBRequest, EventTarget);
13925
- Object.setPrototypeOf(IDBTransaction, EventTarget);
13926
- Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
13927
- // `ShimDOMException` is the real native `DOMException` when one
13928
- // is available (see `DOMException.js`'s `useNativeDOMException`)
13929
- // -- which, unlike the shim classes above, is a single,
13930
- // process-wide singleton shared by reference across every
13931
- // sandbox this library gets installed into (see
13932
- // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
13933
- // already has the correct prototype chain out of the box
13934
- // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
13935
- // not `Error`), so forcing it here isn't just unneeded but
13936
- // actively wrong -- and, because it's shared, permanently
13937
- // wrong for every later use of `DOMException` in the same
13938
- // process (e.g. a later WPT test file's own idlharness-style
13939
- // check that `DOMException` does *not* inherit from `Error`
13940
- // on the class side), not just this one shim install.
13941
- if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
13942
- Object.setPrototypeOf(ShimDOMException, Error);
13943
- Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13944
- }
14193
+ });
14194
+ /** @type {[string, unknown][]} */
14195
+ [['IDBFactory', shimIDBFactory], ['IDBDatabase', IDBDatabase], ['IDBObjectStore', IDBObjectStore], ['IDBIndex', IDBIndex], ['IDBTransaction', IDBTransaction], ['IDBCursor', IDBCursor], ['IDBCursorWithValue', IDBCursorWithValue], ['IDBRecord', IDBRecord], ['IDBKeyRange', IDBKeyRange], ['IDBRequest', IDBRequest], ['IDBOpenDBRequest', IDBOpenDBRequest], ['IDBVersionChangeEvent', IDBVersionChangeEvent]].forEach(function (_ref3) {
14196
+ var _ref4 = _slicedToArray(_ref3, 2),
14197
+ prop = _ref4[0],
14198
+ obj = _ref4[1];
14199
+ shim(prop, obj, {
14200
+ enumerable: false,
14201
+ configurable: true
14202
+ });
14203
+ });
14204
+ // For Node environments
14205
+ if (CFG.fs) {
14206
+ setFS(CFG.fs);
14207
+ }
14208
+ if (CFG.fullIDLSupport) {
14209
+ // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
14210
+
14211
+ Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
14212
+ Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
14213
+ Object.setPrototypeOf(IDBDatabase, EventTarget);
14214
+ Object.setPrototypeOf(IDBRequest, EventTarget);
14215
+ Object.setPrototypeOf(IDBTransaction, EventTarget);
14216
+ Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
14217
+ // `ShimDOMException` is the real native `DOMException` when one
14218
+ // is available (see `DOMException.js`'s `useNativeDOMException`)
14219
+ // -- which, unlike the shim classes above, is a single,
14220
+ // process-wide singleton shared by reference across every
14221
+ // sandbox this library gets installed into (see
14222
+ // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
14223
+ // already has the correct prototype chain out of the box
14224
+ // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
14225
+ // not `Error`), so forcing it here isn't just unneeded but
14226
+ // actively wrong -- and, because it's shared, permanently
14227
+ // wrong for every later use of `DOMException` in the same
14228
+ // process (e.g. a later WPT test file's own idlharness-style
14229
+ // check that `DOMException` does *not* inherit from `Error`
14230
+ // on the class side), not just this one shim install.
14231
+ if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
14232
+ Object.setPrototypeOf(ShimDOMException, Error);
14233
+ Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13945
14234
  }
13946
- if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
13947
- if (CFG.addNonIDBGlobals) {
13948
- // As `DOMStringList` exists per IDL (and Chrome) in the global
13949
- // thread (but not in workers), we prefix the name to avoid
13950
- // shadowing or conflicts
13951
- setNonIDBGlobals('Shim');
13952
- }
13953
- if (CFG.replaceNonIDBGlobals) {
13954
- setNonIDBGlobals();
13955
- }
14235
+ }
14236
+ if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
14237
+ if (CFG.addNonIDBGlobals) {
14238
+ // As `DOMStringList` exists per IDL (and Chrome) in the global
14239
+ // thread (but not in workers), we prefix the name to avoid
14240
+ // shadowing or conflicts
14241
+ setNonIDBGlobals('Shim');
13956
14242
  }
13957
- /* c8 ignore start -- TS guard */
13958
- if (!IDB.shimIndexedDB) {
13959
- return;
14243
+ if (CFG.replaceNonIDBGlobals) {
14244
+ setNonIDBGlobals();
13960
14245
  }
13961
- /* c8 ignore stop -- TS guard */
13962
- IDB.shimIndexedDB.__setConnectionQueueOrigin();
13963
14246
  }
14247
+ /* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
14248
+ confirmed truthy just before this function (`__useShim`) was
14249
+ defined and immediately invoked (see the `if ('shimIndexedDB'
14250
+ in IDB && IDB.shimIndexedDB)` guard above), and nothing in
14251
+ this function's body reassigns or deletes it. Only reachable
14252
+ if `IDB` is some unusual object (e.g. a Proxy) whose
14253
+ `shimIndexedDB` property value changes between reads. */
14254
+ if (!IDB.shimIndexedDB) {
14255
+ return;
14256
+ }
14257
+ /* c8 ignore stop -- see comment above */
14258
+ IDB.shimIndexedDB.__setConnectionQueueOrigin();
13964
14259
  };
13965
14260
  IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
13966
14261
  CFG.DEBUG = val;