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 (factory) {
4
4
  typeof define === 'function' && define.amd ? define(factory) :
@@ -473,6 +473,7 @@
473
473
  var ShimDOMException$1 = typeof DOMException === 'undefined'
474
474
  // Todo: Better polyfill (if even needed here)
475
475
  /* eslint-disable no-shadow -- Polyfill */
476
+ /* 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) */
476
477
  // eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
477
478
  ?
478
479
  /**
@@ -490,9 +491,10 @@
490
491
  configurable: true
491
492
  });
492
493
  return err;
493
- } : DOMException;
494
+ }
495
+ /* c8 ignore stop */ : DOMException;
494
496
 
495
- /** @type {WeakMap<object, any>} */
497
+ /** @type {WeakMap<object, EventWithProps>} */
496
498
  var ev = new WeakMap();
497
499
  /** @type {WeakMap<object, EventWithProps>} */
498
500
  var evCfg = new WeakMap();
@@ -538,11 +540,12 @@
538
540
  obj[prop] = {
539
541
  configurable: true,
540
542
  get: function get() {
541
- return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false : undefined;
543
+ return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
544
+ /* 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;
542
545
  }
543
546
  };
544
547
  return obj;
545
- }, /** @type {{[key: string]: any}} */{}));
548
+ }, /** @type {PropertyDescriptorMap} */{}));
546
549
  }
547
550
 
548
551
  /**
@@ -565,8 +568,9 @@
565
568
  throw new TypeError('Illegal invocation');
566
569
  }
567
570
  var _evCfg = getEvCfg(this);
568
- var _ev = ev.get(this);
569
- return Boolean(Object.hasOwn(_evCfg, 'isTrusted') ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
571
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
572
+ return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
573
+ /* 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);
570
574
  }
571
575
 
572
576
  /**
@@ -717,15 +721,15 @@
717
721
  // this untyped alias, rather than `ShimEvent.prototype` directly, keeps
718
722
  // that dynamic-augmentation pattern working without a `@ts-expect-error`
719
723
  // on every single line below.
720
- /** @type {any} */
721
- var ShimEventProto = ShimEvent.prototype;
724
+
725
+ var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
722
726
 
723
727
  /** @this {EventWithProps} */
724
728
  ShimEventProto.preventDefault = function preventDefault() {
725
729
  if (!(this instanceof ShimEvent)) {
726
730
  throw new TypeError('Illegal invocation');
727
731
  }
728
- var _ev = ev.get(this);
732
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
729
733
  var _evCfg = getEvCfg(this);
730
734
  if (this.cancelable && !_evCfg._passive) {
731
735
  _evCfg.defaultPrevented = true;
@@ -923,13 +927,12 @@
923
927
  return _createClass(CustomEvent);
924
928
  }(Event);
925
929
  var ShimCustomEvent = CustomEvent;
926
- /** @type {any} */
927
- var ShimCustomEventProto = ShimCustomEvent.prototype;
930
+ var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
928
931
  /**
929
932
  * @param {string} type
930
933
  * @param {boolean} [bubbles]
931
934
  * @param {boolean} [cancelable]
932
- * @param {any} [detail]
935
+ * @param {unknown} [detail]
933
936
  * @this {EventWithProps}
934
937
  */
935
938
  ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
@@ -941,6 +944,10 @@
941
944
  throw new TypeError('Illegal invocation');
942
945
  }
943
946
  var _evCfg = getEvCfg(this);
947
+ if (_evCfg._dispatched) {
948
+ return;
949
+ }
950
+
944
951
  // @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
945
952
  // eslint-disable-next-line prefer-rest-params -- Keep signature
946
953
  initEventInternal(this, type, {
@@ -948,16 +955,13 @@
948
955
  cancelable: cancelable,
949
956
  detail: detail
950
957
  }, arguments[4]);
951
- if (_evCfg._dispatched) {
952
- return;
953
- }
954
958
  if (detail !== undefined) {
955
959
  _evCfg.detail = detail;
956
960
  }
957
961
  // `initCustomEvent` deliberately excluded -- see the matching comment
958
962
  // in `initEventInternal` for `initEvent`, above; the same reasoning
959
963
  // applies here.
960
- definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
964
+ definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
961
965
  };
962
966
  // @ts-expect-error Not part of the class body itself
963
967
  ShimCustomEvent[Symbol.toStringTag] = 'Function';
@@ -1364,7 +1368,7 @@
1364
1368
  /** @type {string[]} */
1365
1369
  this._extraProperties.forEach(function (prop) {
1366
1370
  if (Reflect.has(e, prop)) {
1367
- /** @type {{[key: string]: any}} */eventCopy[prop] = /** @type {{[key: string]: any}} */e[prop]; // Todo: Put internal to `ShimEvent`?
1371
+ /** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
1368
1372
  }
1369
1373
  });
1370
1374
  }
@@ -1443,6 +1447,7 @@
1443
1447
  if (child) {
1444
1448
  child._defaultSync = this._defaultSync;
1445
1449
  }
1450
+ /* 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 */
1446
1451
  return (child || this)._dispatchEvent(eventCopy, false);
1447
1452
  }
1448
1453
  case phases.AT_TARGET:
@@ -1740,7 +1745,7 @@
1740
1745
  * databaseNameLengthLimit: number|false,
1741
1746
  * escapeNFDForDatabaseNames: boolean,
1742
1747
  * addSQLiteExtension: boolean,
1743
- * memoryDatabase: string,
1748
+ * memoryDatabase: string|null|undefined,
1744
1749
  * deleteDatabaseFiles: boolean,
1745
1750
  * databaseBasePath: string,
1746
1751
  * sysDatabaseBasePath: string,
@@ -1883,13 +1888,27 @@
1883
1888
  // Various types of in-memory databases that can auto-delete
1884
1889
  ['memoryDatabase',
1885
1890
  /**
1886
- * @param {string} val
1891
+ * `null`/`undefined` are accepted (and left unvalidated against the
1892
+ * regex below) specifically so this can be reset back to its
1893
+ * unset/disabled state after being set: unlike other `CFG`
1894
+ * boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
1895
+ * with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
1896
+ * usage sites check `typeof CFG.memoryDatabase === 'string'`, so
1897
+ * even the empty string counts as "on" (it's a distinct, valid
1898
+ * in-memory mode of its own -- an unnamed private temporary
1899
+ * database -- not an "off" state). Without this, once set to any
1900
+ * string there would be no value passable back through this same
1901
+ * validator that turns `useMemoryDatabase` false again.
1902
+ * @param {string|null|undefined} val
1887
1903
  * @throws {TypeError}
1888
1904
  * @returns {void}
1889
1905
  */
1890
1906
  function (val) {
1907
+ if (val === null || val === undefined) {
1908
+ return;
1909
+ }
1891
1910
  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)) {
1892
- throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a ' + '"file::memory:[?queryString][#hash] URL".');
1911
+ throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
1893
1912
  }
1894
1913
  }],
1895
1914
  // NODE-SPECIFIC CONFIG
@@ -1943,10 +1962,7 @@
1943
1962
  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) {
1944
1963
  // Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
1945
1964
  // but Chrome having problems
1946
- if (unmatchedHighSurrogate) {
1947
- return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
1948
- }
1949
- return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1965
+ return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1950
1966
  });
1951
1967
  }
1952
1968
 
@@ -2613,7 +2629,8 @@
2613
2629
  function createNativeDOMException(name, message) {
2614
2630
  // @ts-expect-error It's ok
2615
2631
  // eslint-disable-next-line new-cap -- Ok
2616
- return new DOMException.prototype.constructor(message, name || 'DOMException');
2632
+ return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
2633
+ name || 'DOMException');
2617
2634
  }
2618
2635
 
2619
2636
  // From web-platform-tests testharness.js name_code_map (though not in new spec)
@@ -2777,8 +2794,10 @@
2777
2794
  */
2778
2795
  get: function get() {
2779
2796
  if (!(this instanceof DOMException ||
2797
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2780
2798
  // @ts-ignore Just checking; needed under some TS versions
2781
2799
  this instanceof DummyDOMException ||
2800
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2782
2801
  // @ts-ignore Just checking; needed under some TS versions
2783
2802
  this instanceof Error)) {
2784
2803
  throw new TypeError('Illegal invocation');
@@ -2837,6 +2856,7 @@
2837
2856
  value: DOMException
2838
2857
  });
2839
2858
 
2859
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2840
2860
  // @ts-ignore We don't need all its properties; needed under some TS versions
2841
2861
  return DOMException;
2842
2862
  }
@@ -2849,6 +2869,7 @@
2849
2869
  * @returns {Error}
2850
2870
  */
2851
2871
  function createNonNativeDOMException(name, message) {
2872
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2852
2873
  // @ts-ignore It's ok; needed under some TS versions
2853
2874
  return new ShimNonNativeDOMException(message, name);
2854
2875
  }
@@ -2871,6 +2892,8 @@
2871
2892
  return;
2872
2893
  }
2873
2894
  var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
2895
+
2896
+ /* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
2874
2897
  var method = typeof console.error === 'function' ? 'error' : 'log';
2875
2898
  console[method](name + ': ' + message + '. ' + (msg || ''));
2876
2899
  if (console.trace) {
@@ -3056,8 +3079,10 @@
3056
3079
  */
3057
3080
  IDBRequest.__super = function IDBRequest() {
3058
3081
  var _this = this;
3082
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3059
3083
  // @ts-ignore It's ok
3060
3084
  this[Symbol.toStringTag] = 'IDBRequest';
3085
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3061
3086
  // @ts-ignore Part of `ShimEventTarget`
3062
3087
  this.__setOptions({
3063
3088
  legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
@@ -3115,10 +3140,7 @@
3115
3140
  * @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
3116
3141
  */
3117
3142
  IDBRequest.prototype.__getParent = function () {
3118
- if (this.toString() === '[object IDBOpenDBRequest]') {
3119
- return null;
3120
- }
3121
- return this.__transaction;
3143
+ return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
3122
3144
  };
3123
3145
 
3124
3146
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
@@ -3177,8 +3199,10 @@
3177
3199
  function IDBOpenDBRequest() {
3178
3200
  IDBRequest.__super.call(this);
3179
3201
 
3202
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3180
3203
  // @ts-ignore It's ok
3181
3204
  this[Symbol.toStringTag] = 'IDBOpenDBRequest';
3205
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3182
3206
  // @ts-ignore It's ok
3183
3207
  this.__setOptions({
3184
3208
  legacyOutputDidListenersThrowFlag: true,
@@ -4189,8 +4213,14 @@
4189
4213
  }
4190
4214
  if (!multiEntry || !fullKeys && keys.every(function (k) {
4191
4215
  return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
4192
- }) || fullKeys && keys.every(function (k) {
4193
- return cmp(/** @type {Key} */k, /** @type {Key} */ /** @type {unknown} */key) !== 0;
4216
+ }) ||
4217
+ // `keys` holds full `{type, value}` objects here (see
4218
+ // `safePush` below), so -- like the sibling branch
4219
+ // above -- `cmp` (which expects raw `Value`s, not
4220
+ // decoded key objects) must compare their `.value`s,
4221
+ // not the wrapper objects themselves.
4222
+ fullKeys && keys.every(function (k) {
4223
+ return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
4194
4224
  })) {
4195
4225
  safePush(keys, fullKeys ? key : key.value);
4196
4226
  }
@@ -4215,12 +4245,9 @@
4215
4245
  {
4216
4246
  var date = /** @type {Date} */input;
4217
4247
  if (!Number.isNaN(date.getTime())) {
4218
- return fullKeys ? {
4219
- type: type,
4220
- value: date.getTime()
4221
- } : {
4248
+ return {
4222
4249
  type: type,
4223
- value: new Date(date)
4250
+ value: fullKeys ? date.getTime() : new Date(date)
4224
4251
  };
4225
4252
  }
4226
4253
  return {
@@ -4308,10 +4335,7 @@
4308
4335
  if (r.failure) {
4309
4336
  return r;
4310
4337
  }
4311
- if (!multiEntry) {
4312
- return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
4313
- }
4314
- return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4338
+ return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4315
4339
  }
4316
4340
 
4317
4341
  /**
@@ -4492,10 +4516,7 @@
4492
4516
  */
4493
4517
  function isMultiEntryMatch(encodedEntry, encodedKey) {
4494
4518
  var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
4495
- if (keyType === 'array') {
4496
- return encodedKey.indexOf(encodedEntry) > 1;
4497
- }
4498
- return encodedKey === encodedEntry;
4519
+ return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
4499
4520
  }
4500
4521
 
4501
4522
  /**
@@ -4613,10 +4634,7 @@
4613
4634
  * @returns {undefined|ValueType}
4614
4635
  */
4615
4636
  function _decode(key, inArray) {
4616
- if (typeof key !== 'string') {
4617
- return undefined;
4618
- }
4619
- return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4637
+ return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4620
4638
  }
4621
4639
 
4622
4640
  /**
@@ -5022,10 +5040,11 @@
5022
5040
  if (hasLower && hasUpper) {
5023
5041
  sql.push('AND');
5024
5042
  }
5025
- if (hasUpper) {
5026
- sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5027
- sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5043
+ if (!hasUpper) {
5044
+ return;
5028
5045
  }
5046
+ sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5047
+ sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5029
5048
  }
5030
5049
 
5031
5050
  /**
@@ -5038,10 +5057,7 @@
5038
5057
  if (instanceOf(value, IDBKeyRange)) {
5039
5058
  // We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
5040
5059
  var range = /** @type {IDBKeyRangeFull} */value;
5041
- if (range.toString() !== '[object IDBKeyRange]') {
5042
- return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
5043
- }
5044
- return range;
5060
+ return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
5045
5061
  }
5046
5062
  if (isNullish(value)) {
5047
5063
  if (nullDisallowed) {
@@ -5086,9 +5102,11 @@
5086
5102
  if (testObject.test) {
5087
5103
  cleanInterface = true;
5088
5104
  }
5105
+ /* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5089
5106
  } catch (err) {
5090
5107
  // Object.defineProperty does not work as intended.
5091
5108
  }
5109
+ /* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5092
5110
  }
5093
5111
 
5094
5112
  /**
@@ -5289,6 +5307,7 @@
5289
5307
  this._length = 0;
5290
5308
  };
5291
5309
  DOMStringList.prototype = DOMStringListAlias.prototype;
5310
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
5292
5311
  // @ts-ignore It's ok; needed under some TS versions
5293
5312
  return /** @type {DOMStringListFull} */new DOMStringList();
5294
5313
  }
@@ -5588,12 +5607,14 @@
5588
5607
  */
5589
5608
  IDBTransaction.prototype.__executeRequests = function () {
5590
5609
  var me = this;
5610
+ /* 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. */
5591
5611
  if (me.__running) {
5592
5612
  if (CFG.DEBUG) {
5593
5613
  console.log('Looks like the request set is already running', me.mode);
5594
5614
  }
5595
5615
  return;
5596
5616
  }
5617
+ /* c8 ignore stop -- see comment above */
5597
5618
 
5598
5619
  // The synchronous script that created this transaction (and
5599
5620
  // synchronously queued whatever requests it wanted to) has now
@@ -5643,6 +5664,7 @@
5643
5664
  queueMicrotask(cb);
5644
5665
  return;
5645
5666
  }
5667
+ /* 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. */
5646
5668
  try {
5647
5669
  tx.executeSql('SELECT 1', [], function () {
5648
5670
  cb();
@@ -5656,6 +5678,7 @@
5656
5678
  // abort the transaction here.
5657
5679
  me.__abortTransaction(/** @type {Error|DOMException} */err);
5658
5680
  }
5681
+ /* c8 ignore stop -- see comment above */
5659
5682
  }
5660
5683
 
5661
5684
  /**
@@ -5668,21 +5691,26 @@
5668
5691
  * @returns {void}
5669
5692
  */
5670
5693
  function success(result, req) {
5694
+ /* 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. */
5671
5695
  if (me.__errored || me.__requestsFinished) {
5672
5696
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5673
5697
  return;
5674
5698
  }
5699
+ /* c8 ignore stop -- see comment above */
5675
5700
  if (req) {
5676
5701
  q.req = req; // Need to do this in case of cursors
5677
5702
  }
5703
+ /* 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. */
5678
5704
  if (!q.req) {
5679
- // TS guard
5680
5705
  return;
5681
5706
  }
5707
+ /* c8 ignore stop -- see comment above */
5708
+ /* 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. */
5682
5709
  if (q.req.__done) {
5683
5710
  // Avoid continuing with aborted requests
5684
5711
  return;
5685
5712
  }
5713
+ /* c8 ignore stop -- see comment above */
5686
5714
  q.req.__done = true;
5687
5715
  q.req.__result = result;
5688
5716
  q.req.__error = null;
@@ -5699,6 +5727,7 @@
5699
5727
  // is what actually resets `__handlerActive`, once it's
5700
5728
  // confirmed (across its own bounded microtask wait) that no
5701
5729
  // such continuation queued anything.
5730
+ /* 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. */
5702
5731
  if (e.__legacyOutputDidListenersThrowError) {
5703
5732
  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
5704
5733
  if (!me.__committed) {
@@ -5708,6 +5737,7 @@
5708
5737
  return;
5709
5738
  }
5710
5739
  }
5740
+ /* c8 ignore stop -- see comment above */
5711
5741
  runContinuationSafely(advanceAfterDispatch);
5712
5742
  }
5713
5743
 
@@ -5719,15 +5749,19 @@
5719
5749
  * @returns {void}
5720
5750
  */
5721
5751
  function error() {
5752
+ /* 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. */
5722
5753
  if (me.__errored || me.__requestsFinished) {
5723
5754
  // We've already called "onerror", "onabort", or thrown within
5724
5755
  // the transaction, so don't do it again.
5725
5756
  return;
5726
5757
  }
5758
+ /* c8 ignore stop -- see comment above */
5759
+ /* 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. */
5727
5760
  if (q.req && q.req.__done) {
5728
5761
  // Avoid continuing with aborted requests
5729
5762
  return;
5730
5763
  }
5764
+ /* c8 ignore stop -- see comment above */
5731
5765
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
5732
5766
  args[_key] = arguments[_key];
5733
5767
  }
@@ -5752,10 +5786,11 @@
5752
5786
  }
5753
5787
  });
5754
5788
  q.req.addDefaultEventListener('error', function () {
5789
+ /* 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. */
5755
5790
  if (!q.req) {
5756
- // TS guard
5757
5791
  return;
5758
5792
  }
5793
+ /* c8 ignore stop -- see comment above */
5759
5794
  me.__abortTransaction(q.req.__error);
5760
5795
  });
5761
5796
  me.__active = true;
@@ -5767,16 +5802,19 @@
5767
5802
  q.req.dispatchEvent(e);
5768
5803
  // Do not set __active or __handlerActive flags to false yet --
5769
5804
  // see the matching comment in `success`, above.
5770
- if (e.__legacyOutputDidListenersThrowError) {
5771
- 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
5772
- e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5773
- if (me.__committed) {
5774
- // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5775
- runContinuationSafely(advanceAfterDispatch);
5776
- return;
5777
- }
5778
- me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5805
+ /* 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. */
5806
+ if (!e.__legacyOutputDidListenersThrowError) {
5807
+ return;
5779
5808
  }
5809
+ 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
5810
+ e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5811
+ if (me.__committed) {
5812
+ // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5813
+ runContinuationSafely(advanceAfterDispatch);
5814
+ return;
5815
+ }
5816
+ me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5817
+ /* c8 ignore stop -- see comment above */
5780
5818
  }
5781
5819
 
5782
5820
  /**
@@ -5800,10 +5838,12 @@
5800
5838
  // (not reset here).
5801
5839
  return true;
5802
5840
  }
5841
+ /* 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. */
5803
5842
  if (q.req.__done) {
5804
5843
  // Avoid continuing with aborted requests
5805
5844
  return false;
5806
5845
  }
5846
+ /* c8 ignore stop -- see comment above */
5807
5847
  // We're now handing off to (possibly async) work for
5808
5848
  // this request, so the transaction is no longer active
5809
5849
  // until its own `success`/`error` dispatch (below)
@@ -5828,18 +5868,22 @@
5828
5868
  return;
5829
5869
  }
5830
5870
  q.op(tx, q.args, success, error, executeNextRequest);
5871
+ /* 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. */
5831
5872
  } catch (e) {
5832
5873
  error(/** @type {Error} */e);
5833
5874
  }
5875
+ /* c8 ignore stop -- see comment above */
5834
5876
  }
5835
5877
 
5836
5878
  /**
5837
5879
  * @returns {void}
5838
5880
  */
5839
5881
  function runQueuedRequest() {
5882
+ /* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
5840
5883
  if (!prepareNextRequest()) {
5841
5884
  return;
5842
5885
  }
5886
+ /* c8 ignore stop -- see comment above */
5843
5887
  launchQueuedOp();
5844
5888
  }
5845
5889
 
@@ -5870,9 +5914,11 @@
5870
5914
  * @returns {void}
5871
5915
  */
5872
5916
  function checkQueueEntry(attemptsLeft) {
5917
+ /* 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. */
5873
5918
  if (me.__errored || me.__requestsFinished) {
5874
5919
  return;
5875
5920
  }
5921
+ /* c8 ignore stop -- see comment above */
5876
5922
  if (i < me.__requests.length) {
5877
5923
  runQueuedRequest();
5878
5924
  return;
@@ -5894,10 +5940,12 @@
5894
5940
  * @returns {void}
5895
5941
  */
5896
5942
  function executeNextRequest() {
5943
+ /* 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. */
5897
5944
  if (me.__errored || me.__requestsFinished) {
5898
5945
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5899
5946
  return;
5900
5947
  }
5948
+ /* c8 ignore stop -- see comment above */
5901
5949
  i++;
5902
5950
  if (i >= me.__requests.length) {
5903
5951
  checkQueueEntry(keepAliveAttempts);
@@ -5932,31 +5980,34 @@
5932
5980
  * @returns {void}
5933
5981
  */
5934
5982
  function advanceAfterDispatch() {
5983
+ /* 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. */
5935
5984
  if (me.__errored || me.__requestsFinished) {
5936
5985
  return;
5937
5986
  }
5987
+ /* c8 ignore stop -- see comment above */
5938
5988
  i++;
5939
5989
  if (i >= me.__requests.length) {
5940
5990
  checkQueueEntry(keepAliveAttempts);
5941
5991
  return;
5942
5992
  }
5943
5993
  keepAliveAndWait(function () {
5944
- if (me.__errored || me.__requestsFinished) {
5945
- return;
5946
- }
5947
- if (!prepareNextRequest()) {
5994
+ /* 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. */
5995
+ if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
5948
5996
  return;
5949
5997
  }
5998
+ /* c8 ignore stop -- see comment above */
5950
5999
  launchQueuedOp();
5951
6000
  });
5952
6001
  }
5953
6002
  executeNextRequest();
5954
6003
  }, function webSQLError(webSQLErr) {
6004
+ /* 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. */
5955
6005
  // @ts-expect-error It's ok
5956
6006
  if (webSQLErr === true) {
5957
6007
  // Not a genuine SQL error
5958
6008
  return;
5959
6009
  }
6010
+ /* c8 ignore stop -- see comment above */
5960
6011
  var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
5961
6012
  me.__abortTransaction(err);
5962
6013
  }, function () {
@@ -5967,18 +6018,25 @@
5967
6018
  // Node
5968
6019
  return;
5969
6020
  }
6021
+ /* 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. */
5970
6022
  if (!me.__transactionEndCallback && !me.__requestsFinished) {
5971
6023
  me.__transactionFinished = true;
5972
6024
  return;
5973
6025
  }
5974
- if (me.__transactionEndCallback && !me.__completed && !me.__transFinishedCbFired) {
5975
- me.__transFinishedCbFired = true;
5976
- me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6026
+ /* c8 ignore stop -- see comment above */
6027
+ /* 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. */
6028
+ if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
6029
+ return;
5977
6030
  }
6031
+ me.__transFinishedCbFired = true;
6032
+ me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6033
+ /* c8 ignore stop -- see comment above */
5978
6034
  }, function (currentTask, err, done, rollback, commit) {
6035
+ /* 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. */
5979
6036
  if (err) {
5980
6037
  return true;
5981
6038
  }
6039
+ /* c8 ignore stop -- see comment above */
5982
6040
  // `readonly` transactions never hold a real SQL transaction open
5983
6041
  // (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
5984
6042
  // them), so there's no commit/rollback round trip to defer --
@@ -6027,6 +6085,7 @@
6027
6085
  */
6028
6086
  function complete() {
6029
6087
  me.__completed = true;
6088
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6030
6089
  if (CFG.DEBUG) {
6031
6090
  console.log('Transaction completed');
6032
6091
  }
@@ -6036,6 +6095,7 @@
6036
6095
  me.dispatchEvent(evt);
6037
6096
  me.__internal = false;
6038
6097
  me.dispatchEvent(createEvent('__complete'));
6098
+ /* 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. */
6039
6099
  } catch (e) {
6040
6100
  me.__internal = false;
6041
6101
  // An error occurred in the "oncomplete" handler.
@@ -6043,6 +6103,7 @@
6043
6103
  // (this may seem odd/bad, but it's how all native IndexedDB implementations work)
6044
6104
  me.__errored = true;
6045
6105
  throw e;
6106
+ /* c8 ignore stop -- see comment above */
6046
6107
  } finally {
6047
6108
  activeTransactions.delete(me);
6048
6109
  me.__storeHandles = {};
@@ -6050,10 +6111,12 @@
6050
6111
  }
6051
6112
  }
6052
6113
  if (me.mode === 'readwrite' || me.mode === 'readonly') {
6114
+ /* 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. */
6053
6115
  if (me.__transactionFinished) {
6054
6116
  complete();
6055
6117
  return;
6056
6118
  }
6119
+ /* c8 ignore stop -- see comment above */
6057
6120
  me.__transactionEndCallback = complete;
6058
6121
  // The underlying SQL driver's own "queue empty" check
6059
6122
  // (`nonstandardTransCb`, above) typically already ran and
@@ -6089,6 +6152,7 @@
6089
6152
  IDBTransaction.prototype.__createRequest = function (source) {
6090
6153
  var me = this;
6091
6154
  var request = IDBRequest.__createInstance();
6155
+ /* 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. */
6092
6156
  request.__source = source !== undefined ? source : me.db;
6093
6157
  request.__transaction = me;
6094
6158
  return request;
@@ -6158,9 +6222,11 @@
6158
6222
  * @returns {void}
6159
6223
  */
6160
6224
  IDBTransaction.prototype.__assertActive = function () {
6225
+ /* 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. */
6161
6226
  if (!this.__active || !this.__handlerActive || this.__committed) {
6162
6227
  throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
6163
6228
  }
6229
+ /* c8 ignore stop -- see comment above */
6164
6230
  };
6165
6231
 
6166
6232
  /**
@@ -6174,6 +6240,7 @@
6174
6240
  }
6175
6241
  };
6176
6242
 
6243
+ /* 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. */
6177
6244
  /**
6178
6245
  * @this {IDBTransactionFull}
6179
6246
  * @returns {void}
@@ -6181,6 +6248,7 @@
6181
6248
  IDBTransaction.prototype.__assertVersionChange = function () {
6182
6249
  IDBTransaction.__assertVersionChange(this);
6183
6250
  };
6251
+ /* c8 ignore stop -- see comment above */
6184
6252
 
6185
6253
  /**
6186
6254
  * Returns the specified object store.
@@ -6202,9 +6270,12 @@
6202
6270
  throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
6203
6271
  }
6204
6272
  var store = me.db.__objectStores[objectStoreName];
6273
+ /* 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. */
6205
6274
  if (!store) {
6206
6275
  throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
6207
6276
  }
6277
+ /* c8 ignore stop -- see comment above */
6278
+
6208
6279
  if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
6209
6280
  // These latter conditions are to allow store
6210
6281
  // recreation to create new clone object
@@ -6223,10 +6294,12 @@
6223
6294
  IDBTransaction.prototype.__abortTransaction = function (err) {
6224
6295
  var me = this;
6225
6296
  logError('Error', 'An error occurred in a transaction', err);
6297
+ /* 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. */
6226
6298
  if (me.__errored) {
6227
6299
  // We've already called "onerror", "onabort", or thrown, so don't do it again.
6228
6300
  return;
6229
6301
  }
6302
+ /* c8 ignore stop -- see comment above */
6230
6303
  me.__errored = true;
6231
6304
  if (me.mode === 'versionchange') {
6232
6305
  // Steps for aborting an upgrade transaction
@@ -6256,19 +6329,16 @@
6256
6329
  if (err !== null) {
6257
6330
  me.__error = err;
6258
6331
  }
6332
+
6333
+ /* 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. */
6259
6334
  if (me.__requestsFinished && err !== null) {
6260
6335
  // The transaction has already completed, so we can't call "onerror" or "onabort".
6261
- // So throw the error instead. `err` is only ever `null` here via
6262
- // `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
6263
- // call, which now checks `__requestsFinished` itself first and
6264
- // throws `InvalidStateError` synchronously before ever reaching
6265
- // this point -- so this guard is just defense in depth against
6266
- // `err` somehow being `null` some other way, not something this
6267
- // path should see in practice.
6336
+ // So throw the error instead.
6268
6337
  setTimeout(function () {
6269
6338
  throw err;
6270
6339
  }, 0);
6271
6340
  }
6341
+ /* c8 ignore stop -- see comment above */
6272
6342
 
6273
6343
  /**
6274
6344
  * @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
@@ -6277,13 +6347,17 @@
6277
6347
  */
6278
6348
  function abort(tx, errOrResult) {
6279
6349
  if (!tx) {
6350
+ /* 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. */
6280
6351
  if (CFG.DEBUG) {
6281
6352
  console.log('Rollback not possible due to missing transaction', me);
6282
6353
  }
6354
+ /* 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. */
6283
6355
  } else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
6284
6356
  if (CFG.DEBUG) {
6285
6357
  console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
6286
6358
  }
6359
+ /* c8 ignore stop -- see comment above */
6360
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6287
6361
  } else if (CFG.DEBUG) {
6288
6362
  console.log('Rollback succeeded', me);
6289
6363
  }
@@ -6299,10 +6373,11 @@
6299
6373
  // behaves first-in-first-out with the same timeout so we could
6300
6374
  // just use a `forEach`.
6301
6375
  return promises.then(function () {
6376
+ /* 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. */
6302
6377
  if (!q.req) {
6303
- // TS guard
6304
6378
  throw new Error('Missing request');
6305
6379
  }
6380
+ /* c8 ignore stop -- see comment above */
6306
6381
  q.req.__done = true;
6307
6382
  q.req.__result = undefined;
6308
6383
  q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
@@ -6313,10 +6388,11 @@
6313
6388
  return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
6314
6389
  function (resolve) {
6315
6390
  setTimeout(function () {
6391
+ /* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
6316
6392
  if (!q.req) {
6317
- // TS guard
6318
6393
  throw new Error('Missing request');
6319
6394
  }
6395
+ /* c8 ignore stop -- see comment above */
6320
6396
  q.req.dispatchEvent(reqEvt); // No need to catch errors
6321
6397
  resolve();
6322
6398
  }, 0);
@@ -6336,10 +6412,12 @@
6336
6412
  releaseFinishedTransaction(me);
6337
6413
  }, 0);
6338
6414
  return undefined;
6415
+ /* 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. */
6339
6416
  }).catch(function (err) {
6340
6417
  console.log('Abort error');
6341
6418
  throw err;
6342
6419
  });
6420
+ /* c8 ignore stop -- see comment above */
6343
6421
  }
6344
6422
  me.__transFinishedCb(true, function (rollback) {
6345
6423
  if (rollback && me.__tx) {
@@ -6347,20 +6425,24 @@
6347
6425
  // rollback automatically), but for Node.js, etc., we give chance for
6348
6426
  // manual aborts which would otherwise not work.
6349
6427
  if (me.mode === 'readwrite') {
6428
+ /* 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. */
6350
6429
  if (me.__transactionFinished) {
6351
6430
  abort();
6352
6431
  return;
6353
6432
  }
6433
+ /* c8 ignore stop -- see comment above */
6354
6434
  me.__transactionEndCallback = abort;
6355
6435
  return;
6356
6436
  }
6357
6437
  try {
6358
6438
  me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
6439
+ /* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
6359
6440
  } catch (err) {
6360
6441
  // Browser errs when transaction has ended and since it most likely already erred here,
6361
6442
  // we call to abort
6362
6443
  abort();
6363
6444
  }
6445
+ /* c8 ignore stop -- see comment above */
6364
6446
  } else {
6365
6447
  abort(null, {
6366
6448
  code: 0
@@ -6378,6 +6460,7 @@
6378
6460
  if (!(me instanceof IDBTransaction)) {
6379
6461
  throw new TypeError('Illegal invocation');
6380
6462
  }
6463
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6381
6464
  if (CFG.DEBUG) {
6382
6465
  console.log('The transaction was aborted', me);
6383
6466
  }
@@ -6409,6 +6492,7 @@
6409
6492
  if (!me.__active || !me.__handlerActive || me.__committed) {
6410
6493
  throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
6411
6494
  }
6495
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6412
6496
  if (CFG.DEBUG) {
6413
6497
  console.log('The transaction was explicitly committed', me);
6414
6498
  }
@@ -6451,6 +6535,7 @@
6451
6535
  };
6452
6536
 
6453
6537
  // object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
6538
+ /* 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. */
6454
6539
  /**
6455
6540
  *
6456
6541
  * @param {IDBTransactionFull} tx
@@ -6466,6 +6551,7 @@
6466
6551
  throw err;
6467
6552
  }
6468
6553
  };
6554
+ /* c8 ignore stop -- see comment above */
6469
6555
 
6470
6556
  /**
6471
6557
  *
@@ -7563,7 +7649,7 @@
7563
7649
  return Number.isNaN(t) ? "NaN" : t;
7564
7650
  },
7565
7651
  revive: function revive(e) {
7566
- return "NaN" === e ? new Date(NaN) : new Date(e);
7652
+ return new Date("NaN" === e ? NaN : e);
7567
7653
  }
7568
7654
  }
7569
7655
  },
@@ -8423,9 +8509,12 @@
8423
8509
  }).find(function (preset) {
8424
8510
  return preset && !Array.isArray(preset) && 'filelist' in preset;
8425
8511
  });
8426
- var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist : undefined;
8427
- var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test : undefined;
8428
- var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive : undefined;
8512
+ var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
8513
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8514
+ var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
8515
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
8516
+ var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
8517
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
8429
8518
  var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
8430
8519
  /**
8431
8520
  * @param {unknown} x
@@ -8433,10 +8522,7 @@
8433
8522
  * @returns {boolean}
8434
8523
  */
8435
8524
  test: function test(x, state) {
8436
- if (typeof FileList !== 'undefined') {
8437
- return x instanceof FileList;
8438
- }
8439
- return typeof origTest === 'function' ? origTest(x, state) : false;
8525
+ return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
8440
8526
  },
8441
8527
  /**
8442
8528
  * @param {unknown} x
@@ -8447,10 +8533,12 @@
8447
8533
  if (typeof FileList !== 'undefined') {
8448
8534
  return Reflect.construct(FileList, [x]);
8449
8535
  }
8536
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
8450
8537
  return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
8451
8538
  }
8452
- }) : undefined;
8453
- var typeson = new Typeson().register([fe, customFileList ? {
8539
+ }) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8540
+ var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
8541
+ customFileList ? {
8454
8542
  filelist: customFileList
8455
8543
  } : {}]);
8456
8544
 
@@ -8606,7 +8694,6 @@
8606
8694
  * __unique: boolean,
8607
8695
  * __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
8608
8696
  * __keyPath: import('./Key.js').KeyPath,
8609
- * __recreated?: boolean,
8610
8697
  * __fetchIndexData: (
8611
8698
  * range: Query,
8612
8699
  * opType: "value"|"key"|"count",
@@ -8700,6 +8787,7 @@
8700
8787
  storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
8701
8788
  me.__pendingName = oldName;
8702
8789
  var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
8790
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
8703
8791
  // @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
8704
8792
  _toConsumableArray(objectStore.indexNames).filter(function (indexName) {
8705
8793
  return indexName !== newName;
@@ -8751,7 +8839,7 @@
8751
8839
  }
8752
8840
  });
8753
8841
  /** @type {const} */
8754
- ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName', '__recreated'].forEach(function (p) {
8842
+ ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
8755
8843
  // @ts-expect-error Why is this type "never"?
8756
8844
  idx[p] = index[p];
8757
8845
  });
@@ -8783,11 +8871,12 @@
8783
8871
  var transaction = store.transaction;
8784
8872
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8785
8873
  transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
8786
- var columnExists = idx && (idx.__deleted || idx.__recreated); // This check must occur here rather than earlier as properties may not have been set yet otherwise
8874
+ var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
8787
8875
 
8788
8876
  /** @type {{[key: string]: boolean}} */
8789
8877
  var indexValues = {};
8790
8878
 
8879
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8791
8880
  /**
8792
8881
  * @param {WebSQLTransaction} tx
8793
8882
  * @param {(Error & {code?: number})} err
@@ -8796,6 +8885,7 @@
8796
8885
  function error(tx, err) {
8797
8886
  failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
8798
8887
  }
8888
+ /* c8 ignore stop -- see comment above */
8799
8889
 
8800
8890
  /**
8801
8891
  * @param {WebSQLTransaction} tx
@@ -8845,12 +8935,6 @@
8845
8935
  } else {
8846
8936
  delete index.__pendingCreate;
8847
8937
  delete indexHandle.__pendingCreate;
8848
- if (index.__deleted) {
8849
- delete index.__deleted;
8850
- delete indexHandle.__deleted;
8851
- index.__recreated = true;
8852
- indexHandle.__recreated = true;
8853
- }
8854
8938
  indexValues = {};
8855
8939
  success(store);
8856
8940
  }
@@ -8859,7 +8943,7 @@
8859
8943
  }, /** @type {SqlErrorCallback} */error);
8860
8944
  }
8861
8945
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
8862
- var escapedIndexNameSQL = escapeIndexNameForSQL(index.name);
8946
+ var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
8863
8947
 
8864
8948
  /**
8865
8949
  * @param {WebSQLTransaction} tx
@@ -8911,6 +8995,7 @@
8911
8995
  var transaction = store.transaction;
8912
8996
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8913
8997
  transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
8998
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8914
8999
  /**
8915
9000
  * @param {WebSQLTransaction} tx
8916
9001
  * @param {(Error & {code?: number})} err
@@ -8919,6 +9004,7 @@
8919
9004
  function error(tx, err) {
8920
9005
  failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
8921
9006
  }
9007
+ /* c8 ignore stop -- see comment above */
8922
9008
 
8923
9009
  /**
8924
9010
  * @returns {void}
@@ -8927,7 +9013,6 @@
8927
9013
  // Update the object store's index list
8928
9014
  IDBIndex.__updateIndexList(store, tx, function (store) {
8929
9015
  delete index.__pendingDelete;
8930
- delete index.__recreated;
8931
9016
  index.__deleted = true;
8932
9017
  if (indexHandle) {
8933
9018
  indexHandle.__deleted = true;
@@ -8988,20 +9073,18 @@
8988
9073
  * @param {Query} range
8989
9074
  * @param {"value"|"key"|"count"} opType
8990
9075
  * @param {boolean} nullDisallowed
8991
- * @param {number} [count]
8992
9076
  * @this {IDBIndexFull}
8993
9077
  * @returns {import('./IDBRequest.js').IDBRequestFull}
8994
9078
  */
8995
- IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, count) {
9079
+ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
8996
9080
  var me = this;
8997
- if (count !== undefined) {
8998
- count = enforceRange(count, 'unsigned long');
8999
- }
9000
9081
  IDBIndex.__invalidStateIfDeleted(me);
9001
9082
  IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
9083
+ /* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
9002
9084
  if (me.objectStore.__deleted) {
9003
9085
  throw createDOMException('InvalidStateError', "This index's object store has been deleted");
9004
9086
  }
9087
+ /* c8 ignore stop -- see comment above */
9005
9088
  IDBTransaction.__assertActive(me.objectStore.transaction);
9006
9089
  if (nullDisallowed && isNullish(range)) {
9007
9090
  throw createDOMException('DataError', 'No key or range was specified');
@@ -9011,7 +9094,7 @@
9011
9094
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
9012
9095
  args[_key] = arguments[_key];
9013
9096
  }
9014
- executeFetchIndexData.apply(void 0, [count].concat(_toConsumableArray(fetchArgs), args));
9097
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
9015
9098
  }, undefined, me);
9016
9099
  };
9017
9100
 
@@ -9170,13 +9253,16 @@
9170
9253
  var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
9171
9254
  return colInfo.join(' ');
9172
9255
  });
9256
+ /* 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. */
9173
9257
  var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
9258
+ /* c8 ignore next -- Defensive: see comment above. */
9174
9259
  var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
9175
9260
 
9176
9261
  // We could adapt the approach at https://stackoverflow.com/a/8430746/271577
9177
9262
  // to make the approach reusable without passing column names, but it is a bit fragile
9178
9263
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
9179
9264
  store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
9265
+ /* 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. */
9180
9266
  /**
9181
9267
  * @param {WebSQLTransaction} tx
9182
9268
  * @param {(Error & {code?: number})} err
@@ -9185,6 +9271,7 @@
9185
9271
  function sqlError(tx, err) {
9186
9272
  error(err);
9187
9273
  }
9274
+ /* c8 ignore stop -- see comment above */
9188
9275
  /**
9189
9276
  * @returns {void}
9190
9277
  */
@@ -9193,8 +9280,14 @@
9193
9280
  cb(tx, success);
9194
9281
  return;
9195
9282
  }
9283
+ /* 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. */
9196
9284
  success();
9197
9285
  }
9286
+ /* c8 ignore stop -- see comment above */
9287
+ if (!CFG.useSQLiteIndexes) {
9288
+ finish();
9289
+ return;
9290
+ }
9198
9291
  // See https://www.sqlite.org/lang_altertable.html#otheralter
9199
9292
  // We don't query for indexes as we already have the info
9200
9293
  // This approach has the advantage of auto-deleting indexes via the DROP TABLE
@@ -9218,10 +9311,6 @@
9218
9311
  console.log(sql);
9219
9312
  }
9220
9313
  tx.executeSql(sql, [], function (tx) {
9221
- if (!CFG.useSQLiteIndexes) {
9222
- finish();
9223
- return;
9224
- }
9225
9314
  var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
9226
9315
  .map(function (escapedIndexNameSQL) {
9227
9316
  return new SyncPromise(function (resolve, reject) {
@@ -9230,13 +9319,16 @@
9230
9319
  // if (CFG.DEBUG) { console.log(sql); }
9231
9320
  // tx.executeSql(sql, [], function () {
9232
9321
  var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
9322
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
9233
9323
  if (CFG.DEBUG) {
9234
9324
  console.log(sql);
9235
9325
  }
9236
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9326
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9327
+ /** @type {SqlErrorCallback} */
9237
9328
  function (tx, err) {
9238
9329
  reject(err);
9239
- });
9330
+ }
9331
+ /* c8 ignore stop -- see comment above */);
9240
9332
  // }, function (tx, err) {
9241
9333
  // reject(err);
9242
9334
  // });
@@ -9254,19 +9346,25 @@
9254
9346
  if (CFG.DEBUG) {
9255
9347
  console.log(sql);
9256
9348
  }
9257
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9349
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9350
+ /** @type {SqlErrorCallback} */
9258
9351
  function (tx, err) {
9259
9352
  reject(err);
9260
- });
9261
- }, /** @type {SqlErrorCallback} */
9353
+ }
9354
+ /* c8 ignore stop -- see comment above */);
9355
+ }, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9356
+ /** @type {SqlErrorCallback} */
9262
9357
  function (tx, err) {
9263
9358
  reject(err);
9264
- });
9359
+ }
9360
+ /* c8 ignore stop -- see comment above */);
9265
9361
  }));
9266
9362
  SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
9267
9363
  error).catch(function (err) {
9364
+ /* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
9268
9365
  console.log('Index rename error');
9269
9366
  throw err;
9367
+ /* c8 ignore stop -- see comment above */
9270
9368
  });
9271
9369
  }, /** @type {SqlErrorCallback} */sqlError);
9272
9370
  }, /** @type {SqlErrorCallback} */sqlError);
@@ -9295,7 +9393,6 @@
9295
9393
  /* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
9296
9394
 
9297
9395
  /**
9298
- * @param {number|null} count
9299
9396
  * @param {boolean} unboundedDisallowed
9300
9397
  * @param {IDBIndexFull} index
9301
9398
  * @param {boolean} hasKey
@@ -9312,12 +9409,9 @@
9312
9409
  * @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
9313
9410
  * @returns {void}
9314
9411
  */
9315
- function executeFetchIndexData(count, unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9412
+ function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9316
9413
  if (unboundedDisallowed) {
9317
- count = 1;
9318
- }
9319
- if (count) {
9320
- sql.push('LIMIT', String(count));
9414
+ sql.push('LIMIT', '1');
9321
9415
  }
9322
9416
  var isCount = opType === 'count';
9323
9417
  if (CFG.DEBUG) {
@@ -9355,41 +9449,48 @@
9355
9449
  var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
9356
9450
  var encodedKey = _encode(range, index.multiEntry);
9357
9451
  var _loop = function _loop() {
9358
- var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9359
- var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9360
- _decode(row[escapedIndexNameForKeyCol]);
9361
- var record;
9362
- if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9363
- /**
9364
- * @param {import('./Key.js').ValueType} check
9365
- * @returns {boolean}
9366
- */
9367
- function (check) {
9368
- return rowKey.includes(check);
9369
- }) ||
9370
- // More precise than our SQL
9371
- isMultiEntryMatch(
9372
- // Added `JSON.stringify` as was having problems with
9373
- // `JSON.stringify` encoding added to nested
9374
- // array keys
9375
- JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9376
- recordCount++;
9377
- record = row;
9378
- } else if (!hasKey && !multiChecks) {
9379
- if (rowKey !== undefined) {
9380
- recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9452
+ var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9453
+ var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9454
+ _decode(row[escapedIndexNameForKeyCol]);
9455
+ var record;
9456
+ if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9457
+ /**
9458
+ * @param {import('./Key.js').ValueType} check
9459
+ * @returns {boolean}
9460
+ */
9461
+ function (check) {
9462
+ return rowKey.includes(check);
9463
+ }) ||
9464
+ // More precise than our SQL
9465
+ isMultiEntryMatch(
9466
+ // Added `JSON.stringify` as was having problems with
9467
+ // `JSON.stringify` encoding added to nested
9468
+ // array keys
9469
+ JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9470
+ recordCount++;
9381
9471
  record = row;
9472
+ } else if (!hasKey && !multiChecks) {
9473
+ if (rowKey !== undefined) {
9474
+ recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9475
+ record = row;
9476
+ }
9382
9477
  }
9383
- }
9384
- if (record) {
9478
+ /* 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. */
9479
+ if (!record) {
9480
+ return 0; // continue
9481
+ }
9482
+ /* c8 ignore stop -- see comment above */
9483
+
9385
9484
  records.push(decode$1(record));
9386
9485
  if (unboundedDisallowed) {
9387
9486
  return 1; // break
9388
9487
  }
9389
- }
9390
- };
9488
+ },
9489
+ _ret;
9391
9490
  for (var i = 0; i < data.rows.length; i++) {
9392
- if (_loop()) break;
9491
+ _ret = _loop();
9492
+ if (_ret === 0) continue;
9493
+ if (_ret === 1) break;
9393
9494
  }
9394
9495
  } else {
9395
9496
  for (var _i = 0; _i < data.rows.length; _i++) {
@@ -9403,8 +9504,16 @@
9403
9504
  if (isCount) {
9404
9505
  success(recordCount);
9405
9506
  } else if (recordCount === 0) {
9507
+ // `unboundedDisallowed` is always `true` here: this function is only reached (for
9508
+ // non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
9509
+ // through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
9510
+ // different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
9511
+ // (returning `[]` here) is unreachable given current callers.
9512
+ /* c8 ignore next -- see comment above */
9406
9513
  success(unboundedDisallowed ? undefined : []);
9407
9514
  } else {
9515
+ // `unboundedDisallowed` is always `true` here; see comment above.
9516
+ /* c8 ignore next -- see comment above */
9408
9517
  success(unboundedDisallowed ? records[0] : records);
9409
9518
  }
9410
9519
  }, /** @type {SqlErrorCallback} */error);
@@ -9648,6 +9757,7 @@
9648
9757
  tx.executeSql(sql, sqlValues, function (tx) {
9649
9758
  // This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
9650
9759
  var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
9760
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
9651
9761
  if (CFG.DEBUG) {
9652
9762
  console.log(sql);
9653
9763
  }
@@ -9656,8 +9766,10 @@
9656
9766
  success();
9657
9767
  });
9658
9768
  }, function (tx, err) {
9769
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9659
9770
  error(err);
9660
9771
  return false;
9772
+ /* c8 ignore stop -- see comment above */
9661
9773
  });
9662
9774
  });
9663
9775
  }
@@ -9731,6 +9843,7 @@
9731
9843
  storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
9732
9844
  }
9733
9845
  transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
9846
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9734
9847
  /**
9735
9848
  * @param {WebSQLTransaction} tx
9736
9849
  * @param {(Error & {code?: number})} [err]
@@ -9743,6 +9856,8 @@
9743
9856
  failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
9744
9857
  return false;
9745
9858
  }
9859
+ /* c8 ignore stop -- see comment above */
9860
+
9746
9861
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
9747
9862
  // key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
9748
9863
  var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
@@ -9797,6 +9912,7 @@
9797
9912
 
9798
9913
  // Remove the object store from WebSQL
9799
9914
  transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
9915
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9800
9916
  /**
9801
9917
  * @param {WebSQLTransaction} tx
9802
9918
  * @param {(Error & {code?: number})} [err]
@@ -9809,6 +9925,8 @@
9809
9925
  failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
9810
9926
  return false;
9811
9927
  }
9928
+ /* c8 ignore stop -- see comment above */
9929
+
9812
9930
  tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
9813
9931
  if (data.rows.length > 0) {
9814
9932
  tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
@@ -9988,13 +10106,15 @@
9988
10106
  return;
9989
10107
  }
9990
10108
  var indexKeyValue = indexKey.value;
10109
+ /* 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. */
9991
10110
  if (indexKeyValue === undefined) {
9992
10111
  resolve(undefined);
9993
10112
  return;
9994
10113
  }
10114
+ /* c8 ignore stop -- see comment above */
9995
10115
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
9996
10116
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
9997
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10117
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
9998
10118
  if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
9999
10119
  resolve(undefined);
10000
10120
  return;
@@ -10074,16 +10194,18 @@
10074
10194
  * @returns {void}
10075
10195
  */
10076
10196
  function setIndexInfo(index) {
10197
+ /* 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. */
10077
10198
  if (indexKeyValue === undefined) {
10078
10199
  return;
10079
10200
  }
10201
+ /* c8 ignore stop -- see comment above */
10080
10202
  paramMap[index.__currentName] = /** @type {string} */
10081
10203
  _encode(indexKeyValue, index.multiEntry);
10082
10204
  }
10083
10205
  if (index.unique) {
10084
10206
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
10085
10207
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
10086
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10208
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
10087
10209
  if (key === undefined) {
10088
10210
  setIndexInfo(index);
10089
10211
  resolve(undefined);
@@ -10174,6 +10296,7 @@
10174
10296
  _me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
10175
10297
  ky = _me$__validateKeyAndV2[0],
10176
10298
  clonedValue = _me$__validateKeyAndV2[1];
10299
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10177
10300
  // @ts-ignore -- Private API
10178
10301
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
10179
10302
  return request;
@@ -10205,6 +10328,7 @@
10205
10328
  _me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
10206
10329
  ky = _me$__validateKeyAndV4[0],
10207
10330
  clonedValue = _me$__validateKeyAndV4[1];
10331
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10208
10332
  // @ts-ignore -- Private API
10209
10333
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
10210
10334
  return request;
@@ -10231,8 +10355,10 @@
10231
10355
  }
10232
10356
  cb(tx);
10233
10357
  }, function (tx, err) {
10358
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10234
10359
  error(err);
10235
10360
  return false;
10361
+ /* c8 ignore stop -- see comment above */
10236
10362
  });
10237
10363
  };
10238
10364
 
@@ -10341,16 +10467,20 @@
10341
10467
  return;
10342
10468
  }
10343
10469
  ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
10470
+ /* 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. */
10344
10471
  } catch (e) {
10345
10472
  // If no result is returned, or error occurs when parsing JSON
10346
10473
  if (CFG.DEBUG) {
10347
10474
  console.log(e);
10348
10475
  }
10349
10476
  }
10477
+ /* c8 ignore stop -- see comment above */
10350
10478
  success(ret);
10351
10479
  }, function (tx, err) {
10480
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10352
10481
  error(err);
10353
10482
  return false;
10483
+ /* c8 ignore stop -- see comment above */
10354
10484
  });
10355
10485
  }, undefined, me);
10356
10486
  };
@@ -10462,8 +10592,10 @@
10462
10592
  });
10463
10593
  success();
10464
10594
  }, function (tx, err) {
10595
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10465
10596
  error(err);
10466
10597
  return false;
10598
+ /* c8 ignore stop -- see comment above */
10467
10599
  });
10468
10600
  }, undefined, me);
10469
10601
  };
@@ -10491,8 +10623,10 @@
10491
10623
  });
10492
10624
  success();
10493
10625
  }, function (tx, err) {
10626
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10494
10627
  error(err);
10495
10628
  return false;
10629
+ /* c8 ignore stop -- see comment above */
10496
10630
  });
10497
10631
  }, undefined, me);
10498
10632
  };
@@ -10827,7 +10961,7 @@
10827
10961
  if (keyPath !== null && !isValidKeyPath(keyPath)) {
10828
10962
  throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
10829
10963
  }
10830
- if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
10964
+ if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
10831
10965
  throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
10832
10966
  }
10833
10967
  var autoInc = createOptions.autoIncrement;
@@ -10976,7 +11110,6 @@
10976
11110
  }
10977
11111
  };
10978
11112
 
10979
- // Todo __forceClose: Add tests for `__forceClose`
10980
11113
  /**
10981
11114
  *
10982
11115
  * @param {string} msg
@@ -10985,23 +11118,39 @@
10985
11118
  */
10986
11119
  IDBDatabase.prototype.__forceClose = function (msg) {
10987
11120
  var me = this;
11121
+ // `close()` (below) resets `me.__transactions` to `[]`, so the
11122
+ // transactions to abort -- and the total count the completion check
11123
+ // below needs -- must be captured before calling it, not read back off
11124
+ // `me.__transactions` afterward.
11125
+ var transactions = me.__transactions;
10988
11126
  me.close();
11127
+
11128
+ /**
11129
+ * @returns {void}
11130
+ */
11131
+ function dispatchClose() {
11132
+ // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
11133
+ var evt = createEvent('close');
11134
+ setTimeout(function () {
11135
+ me.dispatchEvent(evt);
11136
+ }, 0);
11137
+ }
11138
+ if (!transactions.length) {
11139
+ dispatchClose();
11140
+ return;
11141
+ }
10989
11142
  var ct = 0;
10990
- me.__transactions.forEach(function (trans) {
11143
+ transactions.forEach(function (trans) {
10991
11144
  // eslint-disable-next-line camelcase -- Clear API
10992
11145
  trans.on__abort = function () {
10993
11146
  ct++;
10994
- if (ct === me.__transactions.length) {
10995
- // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
10996
- var evt = createEvent('close');
10997
- setTimeout(function () {
10998
- me.dispatchEvent(evt);
10999
- }, 0);
11147
+ if (ct !== transactions.length) {
11148
+ return;
11000
11149
  }
11150
+ dispatchClose();
11001
11151
  };
11002
11152
  trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
11003
11153
  });
11004
- me.__transactions = [];
11005
11154
  };
11006
11155
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
11007
11156
  defineOuterInterface(IDBDatabase.prototype, listeners);
@@ -11168,6 +11317,7 @@
11168
11317
  return undefined;
11169
11318
  }
11170
11319
  var e = /** @type {Event & IDBVersionChangeEvent} */
11320
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11171
11321
  // @ts-ignore It's ok; needed under some TS versions
11172
11322
  new IDBVersionChangeEvent('versionchange', {
11173
11323
  oldVersion: oldVersion,
@@ -11215,6 +11365,7 @@
11215
11365
  }
11216
11366
  };
11217
11367
  var e = /** @type {Event & IDBVersionChangeEvent} */
11368
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11218
11369
  // @ts-ignore It's ok; needed under some TS versions
11219
11370
  new IDBVersionChangeEvent('blocked', {
11220
11371
  oldVersion: oldVersion,
@@ -11275,6 +11426,13 @@
11275
11426
 
11276
11427
  /** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
11277
11428
  var sysdb;
11429
+ // Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
11430
+ // later change to that config (e.g. toggling in-memory mode on and back
11431
+ // off) causes `sysdb` to be recreated for the new setting rather than
11432
+ // staying pinned, forever, to whatever it was the first time any database
11433
+ // was created in the process.
11434
+ /** @type {string|null|undefined} */
11435
+ var sysdbMemoryDatabaseSetting;
11278
11436
  var nameCounter = 0;
11279
11437
 
11280
11438
  /**
@@ -11356,12 +11514,20 @@
11356
11514
  function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
11357
11515
  var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
11358
11516
  if (useMemoryDatabase) {
11517
+ /* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
11518
+ was initialized as an empty placeholder by `open()`'s connection-queue
11519
+ setup (`addRequestToConnectionQueue`, above `openDB`) but never
11520
+ populated with an actual instance -- e.g. `__openDatabase` throwing
11521
+ after a `dbVersions` row already existed for `name` from an earlier,
11522
+ successful `open()` -- or if `name` was never added to the cache at
11523
+ all. Not reachable via normal, non-tampered API usage. */
11359
11524
  var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
11360
11525
  if (!latestSQLiteDBCached) {
11361
11526
  console.warn('Could not find a memory database instance to delete.');
11362
11527
  databaseDeleted();
11363
11528
  return;
11364
11529
  }
11530
+ /* c8 ignore stop -- see comment above */
11365
11531
  var _sqliteDB = latestSQLiteDBCached._db;
11366
11532
  if (!_sqliteDB || !_sqliteDB.close) {
11367
11533
  console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
@@ -11415,15 +11581,24 @@
11415
11581
  tables.item(i).name)), [], function () {
11416
11582
  deleteTables(i + 1);
11417
11583
  }, function () {
11584
+ /* c8 ignore start -- Defensive: continues deleting the rest
11585
+ even if this specific store's table is already gone (e.g.
11586
+ duplicate `__sys__` rows for the same escaped table name, or
11587
+ external tampering); not reachable via normal API usage. */
11418
11588
  deleteTables(i + 1);
11419
11589
  return false;
11590
+ /* c8 ignore stop -- see comment above */
11420
11591
  });
11421
11592
  }
11422
11593
  })(0);
11423
11594
  }, function () {
11424
- // __sys__ table does not exist, but that does not mean delete did not happen
11595
+ /* c8 ignore start -- `__sys__` is always created by `openDB` before this
11596
+ database's `dbVersions` row (a prerequisite for reaching this code at
11597
+ all) is ever inserted; only reachable if the file was tampered with/
11598
+ removed externally afterward. */
11425
11599
  databaseDeleted();
11426
11600
  return false;
11601
+ /* c8 ignore stop -- see comment above */
11427
11602
  });
11428
11603
  });
11429
11604
  }
@@ -11454,9 +11629,11 @@
11454
11629
  }
11455
11630
  failure(er);
11456
11631
  }
11457
- if (sysdb) {
11632
+ if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
11458
11633
  success();
11459
11634
  } else {
11635
+ // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
11636
+ sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
11460
11637
  // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
11461
11638
  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);
11462
11639
  sysdb.transaction(function (systx) {
@@ -11636,6 +11813,17 @@
11636
11813
  * @returns {void}
11637
11814
  */
11638
11815
  var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11816
+ /* c8 ignore start -- This initial definition is always
11817
+ superseded before ever being invoked: the `sysdb.transaction(...)`
11818
+ call below always reaches its `nonstandardTransCb` (4th arg)
11819
+ after this same SQL batch finishes running (since `dbCreateError`
11820
+ always reports errors as "handled" and this call site is never
11821
+ a `readTransaction`), which unconditionally reassigns
11822
+ `sysdbFinishedCb` to a version using the library's own
11823
+ `rollback`/`commit` -- well before any real invocation from
11824
+ `on__beforecomplete`/`on__preabort`/`on__abort` below (those only
11825
+ fire once the upgrade transaction itself later completes/aborts).
11826
+ Kept as a defensive fallback in case that invariant ever changes. */
11639
11827
  if (err) {
11640
11828
  /**
11641
11829
  * @param {unknown} [errorToShow]
@@ -11684,6 +11872,7 @@
11684
11872
  }
11685
11873
  // In browser, should auto-commit
11686
11874
  cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11875
+ /* c8 ignore stop -- see comment above */
11687
11876
  };
11688
11877
  sysdb.transaction(function (systx) {
11689
11878
  /**
@@ -11691,6 +11880,7 @@
11691
11880
  */
11692
11881
  function versionSet() {
11693
11882
  var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
11883
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11694
11884
  // @ts-ignore It's ok; needed under some TS versions
11695
11885
  new IDBVersionChangeEvent('upgradeneeded', {
11696
11886
  oldVersion: oldVersion,
@@ -11816,9 +12006,17 @@
11816
12006
  // eslint-disable-next-line camelcase -- Clear API
11817
12007
  req.transaction.on__complete = function () {
11818
12008
  var pos = connection.__transactions.indexOf(req.transaction);
12009
+ // `req.transaction` (the versionchange transaction) is created
12010
+ // directly via `IDBTransaction.__createInstance` above, never
12011
+ // via `IDBDatabase.prototype.transaction()` (the only place
12012
+ // that pushes onto `connection.__transactions`), so `pos` is
12013
+ // always -1 here.
12014
+ /* c8 ignore start -- see comment above */
11819
12015
  if (pos !== -1) {
11820
12016
  connection.__transactions.splice(pos, 1);
11821
12017
  }
12018
+ /* c8 ignore stop -- see comment above */
12019
+
11822
12020
  if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
11823
12021
  req.__transaction = null;
11824
12022
  var err = createDOMException('AbortError', 'The connection has been closed.');
@@ -11854,9 +12052,16 @@
11854
12052
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
11855
12053
  }
11856
12054
  }, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
12055
+ // Defensive fallback, not reachable in practice: same reasoning
12056
+ // as `deleteDatabase`'s own `nonstandardTransCb` below
12057
+ // (`currentTask.readOnly` is always false here, and
12058
+ // `dbCreateError` always returns `false`, so `err` is never
12059
+ // truthy either).
12060
+ /* c8 ignore start -- see comment above */
11857
12061
  if (currentTask.readOnly || err) {
11858
12062
  return true;
11859
12063
  }
12064
+ /* c8 ignore stop -- see comment above */
11860
12065
  sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11861
12066
  if (err) {
11862
12067
  rollback(err,
@@ -11871,7 +12076,17 @@
11871
12076
  } else {
11872
12077
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
11873
12078
  }
11874
- }, function (sqlErr) {
12079
+ },
12080
+ // Deeply-nested defensive path: only reached if
12081
+ // the *revert* SQL (undoing the `dbVersions`
12082
+ // INSERT/UPDATE after the original version-
12083
+ // upgrade itself already failed) fails a
12084
+ // *second* time. Not feasibly triggerable
12085
+ // without fault-injecting the underlying SQL
12086
+ // driver on this specific, already-failing
12087
+ // revert statement.
12088
+ function (sqlErr) {
12089
+ /* c8 ignore next 2 -- see comment above */
11875
12090
  isRevertingSysdb = false;
11876
12091
  cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11877
12092
  }, function () {
@@ -11887,8 +12102,20 @@
11887
12102
  });
11888
12103
  return undefined;
11889
12104
  }).catch(function (err) {
12105
+ /* c8 ignore start -- Purely defensive: nothing in
12106
+ `triggerAnyVersionChangeAndBlockedEvents`'s promise chain
12107
+ (or this `.then()` continuation above) ever rejects/throws
12108
+ under any reachable application-level condition -- all of
12109
+ its continuations resolve cleanly, and its `dispatchEvent`
12110
+ calls are deliberately fire-and-forget ("No need to catch
12111
+ errors"), running inside a `setTimeout` where a listener
12112
+ throwing becomes an uncaught exception in that macrotask
12113
+ rather than a promise rejection here. This exists solely
12114
+ to surface a truly-unexpected internal bug via the console
12115
+ before rethrowing, not to handle a real, testable error path. */
11890
12116
  console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
11891
12117
  throw err;
12118
+ /* c8 ignore stop -- see comment above */
11892
12119
  });
11893
12120
  } else {
11894
12121
  finishRequest();
@@ -11916,11 +12143,19 @@
11916
12143
  if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
11917
12144
  db = websqlDBCache[name][version];
11918
12145
  } else {
11919
- db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
12146
+ db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
11920
12147
  if (useDatabaseCache) {
12148
+ /* c8 ignore start -- Defensive: by the time `openDB` runs,
12149
+ `websqlDBCache[name]` has always already been created by
12150
+ `addRequestToConnectionQueue`'s own callback above (guarded
12151
+ by this same `useDatabaseCache` condition), which always
12152
+ runs first and unconditionally ensures the entry exists
12153
+ before ever calling `openDB`. Kept as a safety net in case
12154
+ that invariant ever changes. */
11921
12155
  if (!Object.hasOwn(websqlDBCache, name)) {
11922
12156
  websqlDBCache[name] = {};
11923
12157
  }
12158
+ /* c8 ignore stop -- see comment above */
11924
12159
  websqlDBCache[name][version] = db;
11925
12160
  }
11926
12161
  }
@@ -12071,6 +12306,7 @@
12071
12306
  req.__result = undefined;
12072
12307
  req.__done = true;
12073
12308
  var e = /** @type {Event & IDBVersionChangeEvent} */
12309
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12074
12310
  // @ts-ignore It's ok; needed under some TS versions
12075
12311
  new IDBVersionChangeEvent('success', {
12076
12312
  oldVersion: version,
@@ -12113,9 +12349,23 @@
12113
12349
  cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
12114
12350
  }, dbError);
12115
12351
  }, dbError, undefined, function (currentTask, err, done, rollback, commit) {
12352
+ /* c8 ignore start -- Defensive fallback, not reachable in
12353
+ practice: `currentTask.readOnly` is always `false` here
12354
+ (this callback is only ever attached to the writable
12355
+ `sysdb.transaction(...)` call above, never to a
12356
+ `sysdb.readTransaction(...)`), and `err` can only be
12357
+ truthy if the `DELETE FROM dbVersions` statement's own
12358
+ error callback (`dbError`) reports the failure back to
12359
+ `websql-configurable` as unhandled -- but `dbError`
12360
+ deliberately always `return`s `false`, which tells the
12361
+ library the error was already handled (and to keep
12362
+ `err` falsy here), precisely so this custom
12363
+ `sysdbFinishedCbDelete` rollback/commit path below is
12364
+ used instead of the library's own default rollback. */
12116
12365
  if (currentTask.readOnly || err) {
12117
12366
  return true;
12118
12367
  }
12368
+ /* c8 ignore stop -- see comment above */
12119
12369
  sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
12120
12370
  if (err) {
12121
12371
  rollback(err, cb);
@@ -12241,10 +12491,9 @@
12241
12491
  };
12242
12492
 
12243
12493
  /**
12244
- * @todo forceClose: Test
12245
12494
  * This is provided to facilitate unit-testing of the
12246
12495
  * closing of a database connection with a forced flag:
12247
- * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>
12496
+ * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
12248
12497
  * @param {string} dbName
12249
12498
  * @param {Integer} connIdx
12250
12499
  * @param {string} msg
@@ -12345,6 +12594,7 @@
12345
12594
  * @this {IDBRecordFull}
12346
12595
  */
12347
12596
  function IDBRecord() {
12597
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12348
12598
  // @ts-ignore Should be ok
12349
12599
  this[Symbol.toStringTag] = 'IDBRecord';
12350
12600
  this.__key = key;
@@ -12381,6 +12631,7 @@
12381
12631
  if (!(this instanceof IDBRecordAlias)) {
12382
12632
  throw new TypeError('Illegal invocation');
12383
12633
  }
12634
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12384
12635
  // @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
12385
12636
  return this['__' + prop];
12386
12637
  });
@@ -12723,6 +12974,7 @@
12723
12974
  success(undefined, undefined, undefined);
12724
12975
  }
12725
12976
  }, function (tx, err) {
12977
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
12726
12978
  if (CFG.DEBUG) {
12727
12979
  console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
12728
12980
  }
@@ -12906,7 +13158,16 @@
12906
13158
  if (a.key > b.key) {
12907
13159
  return me.direction === 'prev' ? -1 : 1;
12908
13160
  }
13161
+ /* c8 ignore start -- Defensive: only reachable if two matches
13162
+ in the same batch shared both the same `matchingKey` and
13163
+ the same primary `key`, which would require the same
13164
+ record's multi-entry array to contain a duplicate value.
13165
+ `Key.js`'s array-to-key conversion already drops duplicate
13166
+ values when a multi-entry index entry is built, so this
13167
+ can never happen in practice; kept only to satisfy the
13168
+ `Array.prototype.sort` comparator contract. */
12909
13169
  return 0;
13170
+ /* c8 ignore stop -- see comment above */
12910
13171
  });
12911
13172
  me.__prefetchedIndex = 0;
12912
13173
  me.__prefetchedData = {
@@ -12925,13 +13186,19 @@
12925
13186
  console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
12926
13187
  }
12927
13188
  me.__decode(rows[0], success);
12928
- }, function (tx, err) {
13189
+ },
13190
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13191
+ execution error (e.g. I/O error, corruption) while querying for
13192
+ multi-entry cursor matches; not reliably reproducible without
13193
+ mocking the SQL layer. */
13194
+ function (tx, err) {
12929
13195
  if (CFG.DEBUG) {
12930
13196
  console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
12931
13197
  }
12932
13198
  error(err);
12933
13199
  return false;
12934
13200
  });
13201
+ /* c8 ignore stop -- see comment above */
12935
13202
  }
12936
13203
  runQuery();
12937
13204
  };
@@ -13040,6 +13307,7 @@
13040
13307
  * @returns {void}
13041
13308
  */
13042
13309
  IDBCursor.prototype.__invalidateCache = function () {
13310
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13043
13311
  // @ts-ignore Why is this not being found?; needed under some TS versions
13044
13312
  this.__prefetchedData = null;
13045
13313
  this.__multiEntryExhausted = false;
@@ -13064,7 +13332,7 @@
13064
13332
  convertValueToKeyRethrowingAndIfInvalid(key);
13065
13333
  var cmpResult = cmp(key, me.key);
13066
13334
  if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
13067
- throw createDOMException('DataError', 'Cannot ' + (advanceState ? 'advance' : 'continue') + ' the cursor in an unexpected direction');
13335
+ throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
13068
13336
  }
13069
13337
  }
13070
13338
  this.__continueFinish(key, undefined, advanceState);
@@ -13321,6 +13589,7 @@
13321
13589
  // continuation logic in `__findBasic` to see this update's
13322
13590
  // effect on ordering (see "Modify records during cursor
13323
13591
  // iteration" in idbcursor_update_index.any.js).
13592
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13324
13593
  // @ts-ignore -- API (not erring in TS 6)
13325
13594
  IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
13326
13595
  }
@@ -13370,14 +13639,33 @@
13370
13639
  // We don't invalidate the cache (as we don't access it anymore
13371
13640
  // and it will set the index off)
13372
13641
  success(undefined);
13642
+ /* c8 ignore start -- Defensive: `__find` (invoked just above) has
13643
+ already confirmed a row exists for this primary key within the
13644
+ same transaction queue, so `rowsAffected` should always be 1 in
13645
+ normal usage. This branch would only be reached if the underlying
13646
+ row were removed by another request queued in the same
13647
+ transaction between `__find`'s check and this DELETE actually
13648
+ running (e.g. deleting the same record directly via the object
13649
+ store while a cursor over it is mid-iteration); attempts to
13650
+ construct such a scenario instead trigger a transaction abort
13651
+ (`AbortError`) before this callback ever runs, since the default
13652
+ action of an unhandled request error is to abort the
13653
+ transaction. */
13373
13654
  } else {
13374
13655
  // @ts-expect-error Apparently ok
13375
13656
  error('No rows with key found' + key);
13376
13657
  }
13377
- }, function (tx, data) {
13658
+ /* c8 ignore stop -- see comment above */
13659
+ },
13660
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13661
+ execution error (e.g. I/O error, corruption) while deleting the
13662
+ current row; not reliably reproducible without mocking the SQL
13663
+ layer. */
13664
+ function (tx, data) {
13378
13665
  error(data);
13379
13666
  return false;
13380
13667
  });
13668
+ /* c8 ignore stop -- see comment above */
13381
13669
  }, error);
13382
13670
  }, undefined, me);
13383
13671
  };
@@ -13785,7 +14073,7 @@
13785
14073
  */
13786
14074
  function setGlobalVars(idb, initialConfig) {
13787
14075
  var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
13788
- /** @type {unknown} */globalThis || {};
14076
+ /** @type {unknown} */globalThis;
13789
14077
  /**
13790
14078
  * @param {string} name
13791
14079
  * @param {unknown} value
@@ -13876,80 +14164,87 @@
13876
14164
  });
13877
14165
  }
13878
14166
  var shimIDBFactory = IDBFactory;
13879
- if (CFG.win.openDatabase !== undefined) {
13880
- 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
13881
- // Polyfill ALL of IndexedDB, using WebSQL
13882
- shim('indexedDB', shimIndexedDB, {
13883
- enumerable: true,
13884
- configurable: true,
13885
- get: function get() {
13886
- if (this !== IDB && !isNullish(this) && !this.shimNS) {
13887
- // Latter is hack for test environment
13888
- throw new TypeError('Illegal invocation');
13889
- }
13890
- return shimIndexedDB;
14167
+ if (CFG.win.openDatabase === undefined) {
14168
+ return;
14169
+ }
14170
+ 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
14171
+ // Polyfill ALL of IndexedDB, using WebSQL
14172
+ shim('indexedDB', shimIndexedDB, {
14173
+ enumerable: true,
14174
+ configurable: true,
14175
+ get: function get() {
14176
+ if (this !== IDB && !isNullish(this) && !this.shimNS) {
14177
+ // Latter is hack for test environment
14178
+ throw new TypeError('Illegal invocation');
13891
14179
  }
13892
- });
13893
- /** @type {[string, unknown][]} */
13894
- [['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) {
13895
- var _ref4 = _slicedToArray(_ref3, 2),
13896
- prop = _ref4[0],
13897
- obj = _ref4[1];
13898
- shim(prop, obj, {
13899
- enumerable: false,
13900
- configurable: true
13901
- });
13902
- });
13903
- // For Node environments
13904
- if (CFG.fs) {
13905
- setFS(CFG.fs);
14180
+ return shimIndexedDB;
13906
14181
  }
13907
- if (CFG.fullIDLSupport) {
13908
- // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
13909
-
13910
- Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
13911
- Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
13912
- Object.setPrototypeOf(IDBDatabase, EventTarget);
13913
- Object.setPrototypeOf(IDBRequest, EventTarget);
13914
- Object.setPrototypeOf(IDBTransaction, EventTarget);
13915
- Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
13916
- // `ShimDOMException` is the real native `DOMException` when one
13917
- // is available (see `DOMException.js`'s `useNativeDOMException`)
13918
- // -- which, unlike the shim classes above, is a single,
13919
- // process-wide singleton shared by reference across every
13920
- // sandbox this library gets installed into (see
13921
- // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
13922
- // already has the correct prototype chain out of the box
13923
- // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
13924
- // not `Error`), so forcing it here isn't just unneeded but
13925
- // actively wrong -- and, because it's shared, permanently
13926
- // wrong for every later use of `DOMException` in the same
13927
- // process (e.g. a later WPT test file's own idlharness-style
13928
- // check that `DOMException` does *not* inherit from `Error`
13929
- // on the class side), not just this one shim install.
13930
- if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
13931
- Object.setPrototypeOf(ShimDOMException, Error);
13932
- Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13933
- }
14182
+ });
14183
+ /** @type {[string, unknown][]} */
14184
+ [['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) {
14185
+ var _ref4 = _slicedToArray(_ref3, 2),
14186
+ prop = _ref4[0],
14187
+ obj = _ref4[1];
14188
+ shim(prop, obj, {
14189
+ enumerable: false,
14190
+ configurable: true
14191
+ });
14192
+ });
14193
+ // For Node environments
14194
+ if (CFG.fs) {
14195
+ setFS(CFG.fs);
14196
+ }
14197
+ if (CFG.fullIDLSupport) {
14198
+ // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
14199
+
14200
+ Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
14201
+ Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
14202
+ Object.setPrototypeOf(IDBDatabase, EventTarget);
14203
+ Object.setPrototypeOf(IDBRequest, EventTarget);
14204
+ Object.setPrototypeOf(IDBTransaction, EventTarget);
14205
+ Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
14206
+ // `ShimDOMException` is the real native `DOMException` when one
14207
+ // is available (see `DOMException.js`'s `useNativeDOMException`)
14208
+ // -- which, unlike the shim classes above, is a single,
14209
+ // process-wide singleton shared by reference across every
14210
+ // sandbox this library gets installed into (see
14211
+ // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
14212
+ // already has the correct prototype chain out of the box
14213
+ // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
14214
+ // not `Error`), so forcing it here isn't just unneeded but
14215
+ // actively wrong -- and, because it's shared, permanently
14216
+ // wrong for every later use of `DOMException` in the same
14217
+ // process (e.g. a later WPT test file's own idlharness-style
14218
+ // check that `DOMException` does *not* inherit from `Error`
14219
+ // on the class side), not just this one shim install.
14220
+ if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
14221
+ Object.setPrototypeOf(ShimDOMException, Error);
14222
+ Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13934
14223
  }
13935
- if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
13936
- if (CFG.addNonIDBGlobals) {
13937
- // As `DOMStringList` exists per IDL (and Chrome) in the global
13938
- // thread (but not in workers), we prefix the name to avoid
13939
- // shadowing or conflicts
13940
- setNonIDBGlobals('Shim');
13941
- }
13942
- if (CFG.replaceNonIDBGlobals) {
13943
- setNonIDBGlobals();
13944
- }
14224
+ }
14225
+ if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
14226
+ if (CFG.addNonIDBGlobals) {
14227
+ // As `DOMStringList` exists per IDL (and Chrome) in the global
14228
+ // thread (but not in workers), we prefix the name to avoid
14229
+ // shadowing or conflicts
14230
+ setNonIDBGlobals('Shim');
13945
14231
  }
13946
- /* c8 ignore start -- TS guard */
13947
- if (!IDB.shimIndexedDB) {
13948
- return;
14232
+ if (CFG.replaceNonIDBGlobals) {
14233
+ setNonIDBGlobals();
13949
14234
  }
13950
- /* c8 ignore stop -- TS guard */
13951
- IDB.shimIndexedDB.__setConnectionQueueOrigin();
13952
14235
  }
14236
+ /* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
14237
+ confirmed truthy just before this function (`__useShim`) was
14238
+ defined and immediately invoked (see the `if ('shimIndexedDB'
14239
+ in IDB && IDB.shimIndexedDB)` guard above), and nothing in
14240
+ this function's body reassigns or deletes it. Only reachable
14241
+ if `IDB` is some unusual object (e.g. a Proxy) whose
14242
+ `shimIndexedDB` property value changes between reads. */
14243
+ if (!IDB.shimIndexedDB) {
14244
+ return;
14245
+ }
14246
+ /* c8 ignore stop -- see comment above */
14247
+ IDB.shimIndexedDB.__setConnectionQueueOrigin();
13953
14248
  };
13954
14249
  IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
13955
14250
  CFG.DEBUG = val;