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) :
@@ -486,6 +486,7 @@
486
486
  var ShimDOMException$1 = typeof DOMException === 'undefined'
487
487
  // Todo: Better polyfill (if even needed here)
488
488
  /* eslint-disable no-shadow -- Polyfill */
489
+ /* 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) */
489
490
  // eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
490
491
  ?
491
492
  /**
@@ -503,9 +504,10 @@
503
504
  configurable: true
504
505
  });
505
506
  return err;
506
- } : DOMException;
507
+ }
508
+ /* c8 ignore stop */ : DOMException;
507
509
 
508
- /** @type {WeakMap<object, any>} */
510
+ /** @type {WeakMap<object, EventWithProps>} */
509
511
  var ev = new WeakMap();
510
512
  /** @type {WeakMap<object, EventWithProps>} */
511
513
  var evCfg = new WeakMap();
@@ -551,11 +553,12 @@
551
553
  obj[prop] = {
552
554
  configurable: true,
553
555
  get: function get() {
554
- return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false : undefined;
556
+ return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
557
+ /* 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;
555
558
  }
556
559
  };
557
560
  return obj;
558
- }, /** @type {{[key: string]: any}} */{}));
561
+ }, /** @type {PropertyDescriptorMap} */{}));
559
562
  }
560
563
 
561
564
  /**
@@ -578,8 +581,9 @@
578
581
  throw new TypeError('Illegal invocation');
579
582
  }
580
583
  var _evCfg = getEvCfg(this);
581
- var _ev = ev.get(this);
582
- return Boolean(Object.hasOwn(_evCfg, 'isTrusted') ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
584
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
585
+ return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
586
+ /* 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);
583
587
  }
584
588
 
585
589
  /**
@@ -730,15 +734,15 @@
730
734
  // this untyped alias, rather than `ShimEvent.prototype` directly, keeps
731
735
  // that dynamic-augmentation pattern working without a `@ts-expect-error`
732
736
  // on every single line below.
733
- /** @type {any} */
734
- var ShimEventProto = ShimEvent.prototype;
737
+
738
+ var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
735
739
 
736
740
  /** @this {EventWithProps} */
737
741
  ShimEventProto.preventDefault = function preventDefault() {
738
742
  if (!(this instanceof ShimEvent)) {
739
743
  throw new TypeError('Illegal invocation');
740
744
  }
741
- var _ev = ev.get(this);
745
+ var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
742
746
  var _evCfg = getEvCfg(this);
743
747
  if (this.cancelable && !_evCfg._passive) {
744
748
  _evCfg.defaultPrevented = true;
@@ -936,13 +940,12 @@
936
940
  return _createClass(CustomEvent);
937
941
  }(Event);
938
942
  var ShimCustomEvent = CustomEvent;
939
- /** @type {any} */
940
- var ShimCustomEventProto = ShimCustomEvent.prototype;
943
+ var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
941
944
  /**
942
945
  * @param {string} type
943
946
  * @param {boolean} [bubbles]
944
947
  * @param {boolean} [cancelable]
945
- * @param {any} [detail]
948
+ * @param {unknown} [detail]
946
949
  * @this {EventWithProps}
947
950
  */
948
951
  ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
@@ -954,6 +957,10 @@
954
957
  throw new TypeError('Illegal invocation');
955
958
  }
956
959
  var _evCfg = getEvCfg(this);
960
+ if (_evCfg._dispatched) {
961
+ return;
962
+ }
963
+
957
964
  // @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
958
965
  // eslint-disable-next-line prefer-rest-params -- Keep signature
959
966
  initEventInternal(this, type, {
@@ -961,16 +968,13 @@
961
968
  cancelable: cancelable,
962
969
  detail: detail
963
970
  }, arguments[4]);
964
- if (_evCfg._dispatched) {
965
- return;
966
- }
967
971
  if (detail !== undefined) {
968
972
  _evCfg.detail = detail;
969
973
  }
970
974
  // `initCustomEvent` deliberately excluded -- see the matching comment
971
975
  // in `initEventInternal` for `initEvent`, above; the same reasoning
972
976
  // applies here.
973
- definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
977
+ definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
974
978
  };
975
979
  // @ts-expect-error Not part of the class body itself
976
980
  ShimCustomEvent[Symbol.toStringTag] = 'Function';
@@ -1377,7 +1381,7 @@
1377
1381
  /** @type {string[]} */
1378
1382
  this._extraProperties.forEach(function (prop) {
1379
1383
  if (Reflect.has(e, prop)) {
1380
- /** @type {{[key: string]: any}} */eventCopy[prop] = /** @type {{[key: string]: any}} */e[prop]; // Todo: Put internal to `ShimEvent`?
1384
+ /** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
1381
1385
  }
1382
1386
  });
1383
1387
  }
@@ -1456,6 +1460,7 @@
1456
1460
  if (child) {
1457
1461
  child._defaultSync = this._defaultSync;
1458
1462
  }
1463
+ /* 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 */
1459
1464
  return (child || this)._dispatchEvent(eventCopy, false);
1460
1465
  }
1461
1466
  case phases.AT_TARGET:
@@ -1753,7 +1758,7 @@
1753
1758
  * databaseNameLengthLimit: number|false,
1754
1759
  * escapeNFDForDatabaseNames: boolean,
1755
1760
  * addSQLiteExtension: boolean,
1756
- * memoryDatabase: string,
1761
+ * memoryDatabase: string|null|undefined,
1757
1762
  * deleteDatabaseFiles: boolean,
1758
1763
  * databaseBasePath: string,
1759
1764
  * sysDatabaseBasePath: string,
@@ -1896,13 +1901,27 @@
1896
1901
  // Various types of in-memory databases that can auto-delete
1897
1902
  ['memoryDatabase',
1898
1903
  /**
1899
- * @param {string} val
1904
+ * `null`/`undefined` are accepted (and left unvalidated against the
1905
+ * regex below) specifically so this can be reset back to its
1906
+ * unset/disabled state after being set: unlike other `CFG`
1907
+ * boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
1908
+ * with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
1909
+ * usage sites check `typeof CFG.memoryDatabase === 'string'`, so
1910
+ * even the empty string counts as "on" (it's a distinct, valid
1911
+ * in-memory mode of its own -- an unnamed private temporary
1912
+ * database -- not an "off" state). Without this, once set to any
1913
+ * string there would be no value passable back through this same
1914
+ * validator that turns `useMemoryDatabase` false again.
1915
+ * @param {string|null|undefined} val
1900
1916
  * @throws {TypeError}
1901
1917
  * @returns {void}
1902
1918
  */
1903
1919
  function (val) {
1920
+ if (val === null || val === undefined) {
1921
+ return;
1922
+ }
1904
1923
  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)) {
1905
- throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a ' + '"file::memory:[?queryString][#hash] URL".');
1924
+ throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
1906
1925
  }
1907
1926
  }],
1908
1927
  // NODE-SPECIFIC CONFIG
@@ -1956,10 +1975,7 @@
1956
1975
  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) {
1957
1976
  // Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
1958
1977
  // but Chrome having problems
1959
- if (unmatchedHighSurrogate) {
1960
- return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
1961
- }
1962
- return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1978
+ return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
1963
1979
  });
1964
1980
  }
1965
1981
 
@@ -2626,7 +2642,8 @@
2626
2642
  function createNativeDOMException(name, message) {
2627
2643
  // @ts-expect-error It's ok
2628
2644
  // eslint-disable-next-line new-cap -- Ok
2629
- return new DOMException.prototype.constructor(message, name || 'DOMException');
2645
+ return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
2646
+ name || 'DOMException');
2630
2647
  }
2631
2648
 
2632
2649
  // From web-platform-tests testharness.js name_code_map (though not in new spec)
@@ -2790,8 +2807,10 @@
2790
2807
  */
2791
2808
  get: function get() {
2792
2809
  if (!(this instanceof DOMException ||
2810
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2793
2811
  // @ts-ignore Just checking; needed under some TS versions
2794
2812
  this instanceof DummyDOMException ||
2813
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2795
2814
  // @ts-ignore Just checking; needed under some TS versions
2796
2815
  this instanceof Error)) {
2797
2816
  throw new TypeError('Illegal invocation');
@@ -2850,6 +2869,7 @@
2850
2869
  value: DOMException
2851
2870
  });
2852
2871
 
2872
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2853
2873
  // @ts-ignore We don't need all its properties; needed under some TS versions
2854
2874
  return DOMException;
2855
2875
  }
@@ -2862,6 +2882,7 @@
2862
2882
  * @returns {Error}
2863
2883
  */
2864
2884
  function createNonNativeDOMException(name, message) {
2885
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
2865
2886
  // @ts-ignore It's ok; needed under some TS versions
2866
2887
  return new ShimNonNativeDOMException(message, name);
2867
2888
  }
@@ -2884,6 +2905,8 @@
2884
2905
  return;
2885
2906
  }
2886
2907
  var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
2908
+
2909
+ /* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
2887
2910
  var method = typeof console.error === 'function' ? 'error' : 'log';
2888
2911
  console[method](name + ': ' + message + '. ' + (msg || ''));
2889
2912
  if (console.trace) {
@@ -3069,8 +3092,10 @@
3069
3092
  */
3070
3093
  IDBRequest.__super = function IDBRequest() {
3071
3094
  var _this = this;
3095
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3072
3096
  // @ts-ignore It's ok
3073
3097
  this[Symbol.toStringTag] = 'IDBRequest';
3098
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3074
3099
  // @ts-ignore Part of `ShimEventTarget`
3075
3100
  this.__setOptions({
3076
3101
  legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
@@ -3128,10 +3153,7 @@
3128
3153
  * @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
3129
3154
  */
3130
3155
  IDBRequest.prototype.__getParent = function () {
3131
- if (this.toString() === '[object IDBOpenDBRequest]') {
3132
- return null;
3133
- }
3134
- return this.__transaction;
3156
+ return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
3135
3157
  };
3136
3158
 
3137
3159
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
@@ -3190,8 +3212,10 @@
3190
3212
  function IDBOpenDBRequest() {
3191
3213
  IDBRequest.__super.call(this);
3192
3214
 
3215
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3193
3216
  // @ts-ignore It's ok
3194
3217
  this[Symbol.toStringTag] = 'IDBOpenDBRequest';
3218
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
3195
3219
  // @ts-ignore It's ok
3196
3220
  this.__setOptions({
3197
3221
  legacyOutputDidListenersThrowFlag: true,
@@ -4202,8 +4226,14 @@
4202
4226
  }
4203
4227
  if (!multiEntry || !fullKeys && keys.every(function (k) {
4204
4228
  return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
4205
- }) || fullKeys && keys.every(function (k) {
4206
- return cmp(/** @type {Key} */k, /** @type {Key} */ /** @type {unknown} */key) !== 0;
4229
+ }) ||
4230
+ // `keys` holds full `{type, value}` objects here (see
4231
+ // `safePush` below), so -- like the sibling branch
4232
+ // above -- `cmp` (which expects raw `Value`s, not
4233
+ // decoded key objects) must compare their `.value`s,
4234
+ // not the wrapper objects themselves.
4235
+ fullKeys && keys.every(function (k) {
4236
+ return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
4207
4237
  })) {
4208
4238
  safePush(keys, fullKeys ? key : key.value);
4209
4239
  }
@@ -4228,12 +4258,9 @@
4228
4258
  {
4229
4259
  var date = /** @type {Date} */input;
4230
4260
  if (!Number.isNaN(date.getTime())) {
4231
- return fullKeys ? {
4232
- type: type,
4233
- value: date.getTime()
4234
- } : {
4261
+ return {
4235
4262
  type: type,
4236
- value: new Date(date)
4263
+ value: fullKeys ? date.getTime() : new Date(date)
4237
4264
  };
4238
4265
  }
4239
4266
  return {
@@ -4321,10 +4348,7 @@
4321
4348
  if (r.failure) {
4322
4349
  return r;
4323
4350
  }
4324
- if (!multiEntry) {
4325
- return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
4326
- }
4327
- return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4351
+ return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
4328
4352
  }
4329
4353
 
4330
4354
  /**
@@ -4505,10 +4529,7 @@
4505
4529
  */
4506
4530
  function isMultiEntryMatch(encodedEntry, encodedKey) {
4507
4531
  var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
4508
- if (keyType === 'array') {
4509
- return encodedKey.indexOf(encodedEntry) > 1;
4510
- }
4511
- return encodedKey === encodedEntry;
4532
+ return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
4512
4533
  }
4513
4534
 
4514
4535
  /**
@@ -4626,10 +4647,7 @@
4626
4647
  * @returns {undefined|ValueType}
4627
4648
  */
4628
4649
  function _decode(key, inArray) {
4629
- if (typeof key !== 'string') {
4630
- return undefined;
4631
- }
4632
- return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4650
+ return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
4633
4651
  }
4634
4652
 
4635
4653
  /**
@@ -5035,10 +5053,11 @@
5035
5053
  if (hasLower && hasUpper) {
5036
5054
  sql.push('AND');
5037
5055
  }
5038
- if (hasUpper) {
5039
- sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5040
- sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5056
+ if (!hasUpper) {
5057
+ return;
5041
5058
  }
5059
+ sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
5060
+ sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
5042
5061
  }
5043
5062
 
5044
5063
  /**
@@ -5051,10 +5070,7 @@
5051
5070
  if (instanceOf(value, IDBKeyRange)) {
5052
5071
  // We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
5053
5072
  var range = /** @type {IDBKeyRangeFull} */value;
5054
- if (range.toString() !== '[object IDBKeyRange]') {
5055
- return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
5056
- }
5057
- return range;
5073
+ return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
5058
5074
  }
5059
5075
  if (isNullish(value)) {
5060
5076
  if (nullDisallowed) {
@@ -5099,9 +5115,11 @@
5099
5115
  if (testObject.test) {
5100
5116
  cleanInterface = true;
5101
5117
  }
5118
+ /* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5102
5119
  } catch (err) {
5103
5120
  // Object.defineProperty does not work as intended.
5104
5121
  }
5122
+ /* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
5105
5123
  }
5106
5124
 
5107
5125
  /**
@@ -5302,6 +5320,7 @@
5302
5320
  this._length = 0;
5303
5321
  };
5304
5322
  DOMStringList.prototype = DOMStringListAlias.prototype;
5323
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
5305
5324
  // @ts-ignore It's ok; needed under some TS versions
5306
5325
  return /** @type {DOMStringListFull} */new DOMStringList();
5307
5326
  }
@@ -5601,12 +5620,14 @@
5601
5620
  */
5602
5621
  IDBTransaction.prototype.__executeRequests = function () {
5603
5622
  var me = this;
5623
+ /* 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. */
5604
5624
  if (me.__running) {
5605
5625
  if (CFG.DEBUG) {
5606
5626
  console.log('Looks like the request set is already running', me.mode);
5607
5627
  }
5608
5628
  return;
5609
5629
  }
5630
+ /* c8 ignore stop -- see comment above */
5610
5631
 
5611
5632
  // The synchronous script that created this transaction (and
5612
5633
  // synchronously queued whatever requests it wanted to) has now
@@ -5656,6 +5677,7 @@
5656
5677
  queueMicrotask(cb);
5657
5678
  return;
5658
5679
  }
5680
+ /* 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. */
5659
5681
  try {
5660
5682
  tx.executeSql('SELECT 1', [], function () {
5661
5683
  cb();
@@ -5669,6 +5691,7 @@
5669
5691
  // abort the transaction here.
5670
5692
  me.__abortTransaction(/** @type {Error|DOMException} */err);
5671
5693
  }
5694
+ /* c8 ignore stop -- see comment above */
5672
5695
  }
5673
5696
 
5674
5697
  /**
@@ -5681,21 +5704,26 @@
5681
5704
  * @returns {void}
5682
5705
  */
5683
5706
  function success(result, req) {
5707
+ /* 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. */
5684
5708
  if (me.__errored || me.__requestsFinished) {
5685
5709
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5686
5710
  return;
5687
5711
  }
5712
+ /* c8 ignore stop -- see comment above */
5688
5713
  if (req) {
5689
5714
  q.req = req; // Need to do this in case of cursors
5690
5715
  }
5716
+ /* 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. */
5691
5717
  if (!q.req) {
5692
- // TS guard
5693
5718
  return;
5694
5719
  }
5720
+ /* c8 ignore stop -- see comment above */
5721
+ /* 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. */
5695
5722
  if (q.req.__done) {
5696
5723
  // Avoid continuing with aborted requests
5697
5724
  return;
5698
5725
  }
5726
+ /* c8 ignore stop -- see comment above */
5699
5727
  q.req.__done = true;
5700
5728
  q.req.__result = result;
5701
5729
  q.req.__error = null;
@@ -5712,6 +5740,7 @@
5712
5740
  // is what actually resets `__handlerActive`, once it's
5713
5741
  // confirmed (across its own bounded microtask wait) that no
5714
5742
  // such continuation queued anything.
5743
+ /* 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. */
5715
5744
  if (e.__legacyOutputDidListenersThrowError) {
5716
5745
  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
5717
5746
  if (!me.__committed) {
@@ -5721,6 +5750,7 @@
5721
5750
  return;
5722
5751
  }
5723
5752
  }
5753
+ /* c8 ignore stop -- see comment above */
5724
5754
  runContinuationSafely(advanceAfterDispatch);
5725
5755
  }
5726
5756
 
@@ -5732,15 +5762,19 @@
5732
5762
  * @returns {void}
5733
5763
  */
5734
5764
  function error() {
5765
+ /* 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. */
5735
5766
  if (me.__errored || me.__requestsFinished) {
5736
5767
  // We've already called "onerror", "onabort", or thrown within
5737
5768
  // the transaction, so don't do it again.
5738
5769
  return;
5739
5770
  }
5771
+ /* c8 ignore stop -- see comment above */
5772
+ /* 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. */
5740
5773
  if (q.req && q.req.__done) {
5741
5774
  // Avoid continuing with aborted requests
5742
5775
  return;
5743
5776
  }
5777
+ /* c8 ignore stop -- see comment above */
5744
5778
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
5745
5779
  args[_key] = arguments[_key];
5746
5780
  }
@@ -5765,10 +5799,11 @@
5765
5799
  }
5766
5800
  });
5767
5801
  q.req.addDefaultEventListener('error', function () {
5802
+ /* 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. */
5768
5803
  if (!q.req) {
5769
- // TS guard
5770
5804
  return;
5771
5805
  }
5806
+ /* c8 ignore stop -- see comment above */
5772
5807
  me.__abortTransaction(q.req.__error);
5773
5808
  });
5774
5809
  me.__active = true;
@@ -5780,16 +5815,19 @@
5780
5815
  q.req.dispatchEvent(e);
5781
5816
  // Do not set __active or __handlerActive flags to false yet --
5782
5817
  // see the matching comment in `success`, above.
5783
- if (e.__legacyOutputDidListenersThrowError) {
5784
- 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
5785
- e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5786
- if (me.__committed) {
5787
- // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5788
- runContinuationSafely(advanceAfterDispatch);
5789
- return;
5790
- }
5791
- me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5818
+ /* 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. */
5819
+ if (!e.__legacyOutputDidListenersThrowError) {
5820
+ return;
5792
5821
  }
5822
+ 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
5823
+ e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
5824
+ if (me.__committed) {
5825
+ // An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
5826
+ runContinuationSafely(advanceAfterDispatch);
5827
+ return;
5828
+ }
5829
+ me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
5830
+ /* c8 ignore stop -- see comment above */
5793
5831
  }
5794
5832
 
5795
5833
  /**
@@ -5813,10 +5851,12 @@
5813
5851
  // (not reset here).
5814
5852
  return true;
5815
5853
  }
5854
+ /* 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. */
5816
5855
  if (q.req.__done) {
5817
5856
  // Avoid continuing with aborted requests
5818
5857
  return false;
5819
5858
  }
5859
+ /* c8 ignore stop -- see comment above */
5820
5860
  // We're now handing off to (possibly async) work for
5821
5861
  // this request, so the transaction is no longer active
5822
5862
  // until its own `success`/`error` dispatch (below)
@@ -5841,18 +5881,22 @@
5841
5881
  return;
5842
5882
  }
5843
5883
  q.op(tx, q.args, success, error, executeNextRequest);
5884
+ /* 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. */
5844
5885
  } catch (e) {
5845
5886
  error(/** @type {Error} */e);
5846
5887
  }
5888
+ /* c8 ignore stop -- see comment above */
5847
5889
  }
5848
5890
 
5849
5891
  /**
5850
5892
  * @returns {void}
5851
5893
  */
5852
5894
  function runQueuedRequest() {
5895
+ /* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
5853
5896
  if (!prepareNextRequest()) {
5854
5897
  return;
5855
5898
  }
5899
+ /* c8 ignore stop -- see comment above */
5856
5900
  launchQueuedOp();
5857
5901
  }
5858
5902
 
@@ -5883,9 +5927,11 @@
5883
5927
  * @returns {void}
5884
5928
  */
5885
5929
  function checkQueueEntry(attemptsLeft) {
5930
+ /* 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. */
5886
5931
  if (me.__errored || me.__requestsFinished) {
5887
5932
  return;
5888
5933
  }
5934
+ /* c8 ignore stop -- see comment above */
5889
5935
  if (i < me.__requests.length) {
5890
5936
  runQueuedRequest();
5891
5937
  return;
@@ -5907,10 +5953,12 @@
5907
5953
  * @returns {void}
5908
5954
  */
5909
5955
  function executeNextRequest() {
5956
+ /* 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. */
5910
5957
  if (me.__errored || me.__requestsFinished) {
5911
5958
  // We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
5912
5959
  return;
5913
5960
  }
5961
+ /* c8 ignore stop -- see comment above */
5914
5962
  i++;
5915
5963
  if (i >= me.__requests.length) {
5916
5964
  checkQueueEntry(keepAliveAttempts);
@@ -5945,31 +5993,34 @@
5945
5993
  * @returns {void}
5946
5994
  */
5947
5995
  function advanceAfterDispatch() {
5996
+ /* 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. */
5948
5997
  if (me.__errored || me.__requestsFinished) {
5949
5998
  return;
5950
5999
  }
6000
+ /* c8 ignore stop -- see comment above */
5951
6001
  i++;
5952
6002
  if (i >= me.__requests.length) {
5953
6003
  checkQueueEntry(keepAliveAttempts);
5954
6004
  return;
5955
6005
  }
5956
6006
  keepAliveAndWait(function () {
5957
- if (me.__errored || me.__requestsFinished) {
5958
- return;
5959
- }
5960
- if (!prepareNextRequest()) {
6007
+ /* 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. */
6008
+ if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
5961
6009
  return;
5962
6010
  }
6011
+ /* c8 ignore stop -- see comment above */
5963
6012
  launchQueuedOp();
5964
6013
  });
5965
6014
  }
5966
6015
  executeNextRequest();
5967
6016
  }, function webSQLError(webSQLErr) {
6017
+ /* 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. */
5968
6018
  // @ts-expect-error It's ok
5969
6019
  if (webSQLErr === true) {
5970
6020
  // Not a genuine SQL error
5971
6021
  return;
5972
6022
  }
6023
+ /* c8 ignore stop -- see comment above */
5973
6024
  var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
5974
6025
  me.__abortTransaction(err);
5975
6026
  }, function () {
@@ -5980,18 +6031,25 @@
5980
6031
  // Node
5981
6032
  return;
5982
6033
  }
6034
+ /* 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. */
5983
6035
  if (!me.__transactionEndCallback && !me.__requestsFinished) {
5984
6036
  me.__transactionFinished = true;
5985
6037
  return;
5986
6038
  }
5987
- if (me.__transactionEndCallback && !me.__completed && !me.__transFinishedCbFired) {
5988
- me.__transFinishedCbFired = true;
5989
- me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6039
+ /* c8 ignore stop -- see comment above */
6040
+ /* 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. */
6041
+ if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
6042
+ return;
5990
6043
  }
6044
+ me.__transFinishedCbFired = true;
6045
+ me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
6046
+ /* c8 ignore stop -- see comment above */
5991
6047
  }, function (currentTask, err, done, rollback, commit) {
6048
+ /* 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. */
5992
6049
  if (err) {
5993
6050
  return true;
5994
6051
  }
6052
+ /* c8 ignore stop -- see comment above */
5995
6053
  // `readonly` transactions never hold a real SQL transaction open
5996
6054
  // (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
5997
6055
  // them), so there's no commit/rollback round trip to defer --
@@ -6040,6 +6098,7 @@
6040
6098
  */
6041
6099
  function complete() {
6042
6100
  me.__completed = true;
6101
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6043
6102
  if (CFG.DEBUG) {
6044
6103
  console.log('Transaction completed');
6045
6104
  }
@@ -6049,6 +6108,7 @@
6049
6108
  me.dispatchEvent(evt);
6050
6109
  me.__internal = false;
6051
6110
  me.dispatchEvent(createEvent('__complete'));
6111
+ /* 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. */
6052
6112
  } catch (e) {
6053
6113
  me.__internal = false;
6054
6114
  // An error occurred in the "oncomplete" handler.
@@ -6056,6 +6116,7 @@
6056
6116
  // (this may seem odd/bad, but it's how all native IndexedDB implementations work)
6057
6117
  me.__errored = true;
6058
6118
  throw e;
6119
+ /* c8 ignore stop -- see comment above */
6059
6120
  } finally {
6060
6121
  activeTransactions.delete(me);
6061
6122
  me.__storeHandles = {};
@@ -6063,10 +6124,12 @@
6063
6124
  }
6064
6125
  }
6065
6126
  if (me.mode === 'readwrite' || me.mode === 'readonly') {
6127
+ /* 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. */
6066
6128
  if (me.__transactionFinished) {
6067
6129
  complete();
6068
6130
  return;
6069
6131
  }
6132
+ /* c8 ignore stop -- see comment above */
6070
6133
  me.__transactionEndCallback = complete;
6071
6134
  // The underlying SQL driver's own "queue empty" check
6072
6135
  // (`nonstandardTransCb`, above) typically already ran and
@@ -6102,6 +6165,7 @@
6102
6165
  IDBTransaction.prototype.__createRequest = function (source) {
6103
6166
  var me = this;
6104
6167
  var request = IDBRequest.__createInstance();
6168
+ /* 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. */
6105
6169
  request.__source = source !== undefined ? source : me.db;
6106
6170
  request.__transaction = me;
6107
6171
  return request;
@@ -6171,9 +6235,11 @@
6171
6235
  * @returns {void}
6172
6236
  */
6173
6237
  IDBTransaction.prototype.__assertActive = function () {
6238
+ /* 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. */
6174
6239
  if (!this.__active || !this.__handlerActive || this.__committed) {
6175
6240
  throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
6176
6241
  }
6242
+ /* c8 ignore stop -- see comment above */
6177
6243
  };
6178
6244
 
6179
6245
  /**
@@ -6187,6 +6253,7 @@
6187
6253
  }
6188
6254
  };
6189
6255
 
6256
+ /* 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. */
6190
6257
  /**
6191
6258
  * @this {IDBTransactionFull}
6192
6259
  * @returns {void}
@@ -6194,6 +6261,7 @@
6194
6261
  IDBTransaction.prototype.__assertVersionChange = function () {
6195
6262
  IDBTransaction.__assertVersionChange(this);
6196
6263
  };
6264
+ /* c8 ignore stop -- see comment above */
6197
6265
 
6198
6266
  /**
6199
6267
  * Returns the specified object store.
@@ -6215,9 +6283,12 @@
6215
6283
  throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
6216
6284
  }
6217
6285
  var store = me.db.__objectStores[objectStoreName];
6286
+ /* 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. */
6218
6287
  if (!store) {
6219
6288
  throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
6220
6289
  }
6290
+ /* c8 ignore stop -- see comment above */
6291
+
6221
6292
  if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
6222
6293
  // These latter conditions are to allow store
6223
6294
  // recreation to create new clone object
@@ -6236,10 +6307,12 @@
6236
6307
  IDBTransaction.prototype.__abortTransaction = function (err) {
6237
6308
  var me = this;
6238
6309
  logError('Error', 'An error occurred in a transaction', err);
6310
+ /* 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. */
6239
6311
  if (me.__errored) {
6240
6312
  // We've already called "onerror", "onabort", or thrown, so don't do it again.
6241
6313
  return;
6242
6314
  }
6315
+ /* c8 ignore stop -- see comment above */
6243
6316
  me.__errored = true;
6244
6317
  if (me.mode === 'versionchange') {
6245
6318
  // Steps for aborting an upgrade transaction
@@ -6269,19 +6342,16 @@
6269
6342
  if (err !== null) {
6270
6343
  me.__error = err;
6271
6344
  }
6345
+
6346
+ /* 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. */
6272
6347
  if (me.__requestsFinished && err !== null) {
6273
6348
  // The transaction has already completed, so we can't call "onerror" or "onabort".
6274
- // So throw the error instead. `err` is only ever `null` here via
6275
- // `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
6276
- // call, which now checks `__requestsFinished` itself first and
6277
- // throws `InvalidStateError` synchronously before ever reaching
6278
- // this point -- so this guard is just defense in depth against
6279
- // `err` somehow being `null` some other way, not something this
6280
- // path should see in practice.
6349
+ // So throw the error instead.
6281
6350
  setTimeout(function () {
6282
6351
  throw err;
6283
6352
  }, 0);
6284
6353
  }
6354
+ /* c8 ignore stop -- see comment above */
6285
6355
 
6286
6356
  /**
6287
6357
  * @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
@@ -6290,13 +6360,17 @@
6290
6360
  */
6291
6361
  function abort(tx, errOrResult) {
6292
6362
  if (!tx) {
6363
+ /* 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. */
6293
6364
  if (CFG.DEBUG) {
6294
6365
  console.log('Rollback not possible due to missing transaction', me);
6295
6366
  }
6367
+ /* 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. */
6296
6368
  } else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
6297
6369
  if (CFG.DEBUG) {
6298
6370
  console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
6299
6371
  }
6372
+ /* c8 ignore stop -- see comment above */
6373
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6300
6374
  } else if (CFG.DEBUG) {
6301
6375
  console.log('Rollback succeeded', me);
6302
6376
  }
@@ -6312,10 +6386,11 @@
6312
6386
  // behaves first-in-first-out with the same timeout so we could
6313
6387
  // just use a `forEach`.
6314
6388
  return promises.then(function () {
6389
+ /* 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. */
6315
6390
  if (!q.req) {
6316
- // TS guard
6317
6391
  throw new Error('Missing request');
6318
6392
  }
6393
+ /* c8 ignore stop -- see comment above */
6319
6394
  q.req.__done = true;
6320
6395
  q.req.__result = undefined;
6321
6396
  q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
@@ -6326,10 +6401,11 @@
6326
6401
  return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
6327
6402
  function (resolve) {
6328
6403
  setTimeout(function () {
6404
+ /* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
6329
6405
  if (!q.req) {
6330
- // TS guard
6331
6406
  throw new Error('Missing request');
6332
6407
  }
6408
+ /* c8 ignore stop -- see comment above */
6333
6409
  q.req.dispatchEvent(reqEvt); // No need to catch errors
6334
6410
  resolve();
6335
6411
  }, 0);
@@ -6349,10 +6425,12 @@
6349
6425
  releaseFinishedTransaction(me);
6350
6426
  }, 0);
6351
6427
  return undefined;
6428
+ /* 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. */
6352
6429
  }).catch(function (err) {
6353
6430
  console.log('Abort error');
6354
6431
  throw err;
6355
6432
  });
6433
+ /* c8 ignore stop -- see comment above */
6356
6434
  }
6357
6435
  me.__transFinishedCb(true, function (rollback) {
6358
6436
  if (rollback && me.__tx) {
@@ -6360,20 +6438,24 @@
6360
6438
  // rollback automatically), but for Node.js, etc., we give chance for
6361
6439
  // manual aborts which would otherwise not work.
6362
6440
  if (me.mode === 'readwrite') {
6441
+ /* 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. */
6363
6442
  if (me.__transactionFinished) {
6364
6443
  abort();
6365
6444
  return;
6366
6445
  }
6446
+ /* c8 ignore stop -- see comment above */
6367
6447
  me.__transactionEndCallback = abort;
6368
6448
  return;
6369
6449
  }
6370
6450
  try {
6371
6451
  me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
6452
+ /* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
6372
6453
  } catch (err) {
6373
6454
  // Browser errs when transaction has ended and since it most likely already erred here,
6374
6455
  // we call to abort
6375
6456
  abort();
6376
6457
  }
6458
+ /* c8 ignore stop -- see comment above */
6377
6459
  } else {
6378
6460
  abort(null, {
6379
6461
  code: 0
@@ -6391,6 +6473,7 @@
6391
6473
  if (!(me instanceof IDBTransaction)) {
6392
6474
  throw new TypeError('Illegal invocation');
6393
6475
  }
6476
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6394
6477
  if (CFG.DEBUG) {
6395
6478
  console.log('The transaction was aborted', me);
6396
6479
  }
@@ -6422,6 +6505,7 @@
6422
6505
  if (!me.__active || !me.__handlerActive || me.__committed) {
6423
6506
  throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
6424
6507
  }
6508
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
6425
6509
  if (CFG.DEBUG) {
6426
6510
  console.log('The transaction was explicitly committed', me);
6427
6511
  }
@@ -6464,6 +6548,7 @@
6464
6548
  };
6465
6549
 
6466
6550
  // object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
6551
+ /* 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. */
6467
6552
  /**
6468
6553
  *
6469
6554
  * @param {IDBTransactionFull} tx
@@ -6479,6 +6564,7 @@
6479
6564
  throw err;
6480
6565
  }
6481
6566
  };
6567
+ /* c8 ignore stop -- see comment above */
6482
6568
 
6483
6569
  /**
6484
6570
  *
@@ -7576,7 +7662,7 @@
7576
7662
  return Number.isNaN(t) ? "NaN" : t;
7577
7663
  },
7578
7664
  revive: function revive(e) {
7579
- return "NaN" === e ? new Date(NaN) : new Date(e);
7665
+ return new Date("NaN" === e ? NaN : e);
7580
7666
  }
7581
7667
  }
7582
7668
  },
@@ -8436,9 +8522,12 @@
8436
8522
  }).find(function (preset) {
8437
8523
  return preset && !Array.isArray(preset) && 'filelist' in preset;
8438
8524
  });
8439
- var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist : undefined;
8440
- var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test : undefined;
8441
- var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive : undefined;
8525
+ var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
8526
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8527
+ var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
8528
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
8529
+ var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
8530
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
8442
8531
  var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
8443
8532
  /**
8444
8533
  * @param {unknown} x
@@ -8446,10 +8535,7 @@
8446
8535
  * @returns {boolean}
8447
8536
  */
8448
8537
  test: function test(x, state) {
8449
- if (typeof FileList !== 'undefined') {
8450
- return x instanceof FileList;
8451
- }
8452
- return typeof origTest === 'function' ? origTest(x, state) : false;
8538
+ return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
8453
8539
  },
8454
8540
  /**
8455
8541
  * @param {unknown} x
@@ -8460,10 +8546,12 @@
8460
8546
  if (typeof FileList !== 'undefined') {
8461
8547
  return Reflect.construct(FileList, [x]);
8462
8548
  }
8549
+ /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
8463
8550
  return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
8464
8551
  }
8465
- }) : undefined;
8466
- var typeson = new Typeson().register([fe, customFileList ? {
8552
+ }) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
8553
+ var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
8554
+ customFileList ? {
8467
8555
  filelist: customFileList
8468
8556
  } : {}]);
8469
8557
 
@@ -8619,7 +8707,6 @@
8619
8707
  * __unique: boolean,
8620
8708
  * __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
8621
8709
  * __keyPath: import('./Key.js').KeyPath,
8622
- * __recreated?: boolean,
8623
8710
  * __fetchIndexData: (
8624
8711
  * range: Query,
8625
8712
  * opType: "value"|"key"|"count",
@@ -8713,6 +8800,7 @@
8713
8800
  storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
8714
8801
  me.__pendingName = oldName;
8715
8802
  var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
8803
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
8716
8804
  // @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
8717
8805
  _toConsumableArray(objectStore.indexNames).filter(function (indexName) {
8718
8806
  return indexName !== newName;
@@ -8764,7 +8852,7 @@
8764
8852
  }
8765
8853
  });
8766
8854
  /** @type {const} */
8767
- ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName', '__recreated'].forEach(function (p) {
8855
+ ['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
8768
8856
  // @ts-expect-error Why is this type "never"?
8769
8857
  idx[p] = index[p];
8770
8858
  });
@@ -8796,11 +8884,12 @@
8796
8884
  var transaction = store.transaction;
8797
8885
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8798
8886
  transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
8799
- var columnExists = idx && (idx.__deleted || idx.__recreated); // This check must occur here rather than earlier as properties may not have been set yet otherwise
8887
+ var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
8800
8888
 
8801
8889
  /** @type {{[key: string]: boolean}} */
8802
8890
  var indexValues = {};
8803
8891
 
8892
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8804
8893
  /**
8805
8894
  * @param {WebSQLTransaction} tx
8806
8895
  * @param {(Error & {code?: number})} err
@@ -8809,6 +8898,7 @@
8809
8898
  function error(tx, err) {
8810
8899
  failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
8811
8900
  }
8901
+ /* c8 ignore stop -- see comment above */
8812
8902
 
8813
8903
  /**
8814
8904
  * @param {WebSQLTransaction} tx
@@ -8858,12 +8948,6 @@
8858
8948
  } else {
8859
8949
  delete index.__pendingCreate;
8860
8950
  delete indexHandle.__pendingCreate;
8861
- if (index.__deleted) {
8862
- delete index.__deleted;
8863
- delete indexHandle.__deleted;
8864
- index.__recreated = true;
8865
- indexHandle.__recreated = true;
8866
- }
8867
8951
  indexValues = {};
8868
8952
  success(store);
8869
8953
  }
@@ -8872,7 +8956,7 @@
8872
8956
  }, /** @type {SqlErrorCallback} */error);
8873
8957
  }
8874
8958
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
8875
- var escapedIndexNameSQL = escapeIndexNameForSQL(index.name);
8959
+ var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
8876
8960
 
8877
8961
  /**
8878
8962
  * @param {WebSQLTransaction} tx
@@ -8924,6 +9008,7 @@
8924
9008
  var transaction = store.transaction;
8925
9009
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
8926
9010
  transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
9011
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
8927
9012
  /**
8928
9013
  * @param {WebSQLTransaction} tx
8929
9014
  * @param {(Error & {code?: number})} err
@@ -8932,6 +9017,7 @@
8932
9017
  function error(tx, err) {
8933
9018
  failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
8934
9019
  }
9020
+ /* c8 ignore stop -- see comment above */
8935
9021
 
8936
9022
  /**
8937
9023
  * @returns {void}
@@ -8940,7 +9026,6 @@
8940
9026
  // Update the object store's index list
8941
9027
  IDBIndex.__updateIndexList(store, tx, function (store) {
8942
9028
  delete index.__pendingDelete;
8943
- delete index.__recreated;
8944
9029
  index.__deleted = true;
8945
9030
  if (indexHandle) {
8946
9031
  indexHandle.__deleted = true;
@@ -9001,20 +9086,18 @@
9001
9086
  * @param {Query} range
9002
9087
  * @param {"value"|"key"|"count"} opType
9003
9088
  * @param {boolean} nullDisallowed
9004
- * @param {number} [count]
9005
9089
  * @this {IDBIndexFull}
9006
9090
  * @returns {import('./IDBRequest.js').IDBRequestFull}
9007
9091
  */
9008
- IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, count) {
9092
+ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
9009
9093
  var me = this;
9010
- if (count !== undefined) {
9011
- count = enforceRange(count, 'unsigned long');
9012
- }
9013
9094
  IDBIndex.__invalidStateIfDeleted(me);
9014
9095
  IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
9096
+ /* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
9015
9097
  if (me.objectStore.__deleted) {
9016
9098
  throw createDOMException('InvalidStateError', "This index's object store has been deleted");
9017
9099
  }
9100
+ /* c8 ignore stop -- see comment above */
9018
9101
  IDBTransaction.__assertActive(me.objectStore.transaction);
9019
9102
  if (nullDisallowed && isNullish(range)) {
9020
9103
  throw createDOMException('DataError', 'No key or range was specified');
@@ -9024,7 +9107,7 @@
9024
9107
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
9025
9108
  args[_key] = arguments[_key];
9026
9109
  }
9027
- executeFetchIndexData.apply(void 0, [count].concat(_toConsumableArray(fetchArgs), args));
9110
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
9028
9111
  }, undefined, me);
9029
9112
  };
9030
9113
 
@@ -9183,13 +9266,16 @@
9183
9266
  var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
9184
9267
  return colInfo.join(' ');
9185
9268
  });
9269
+ /* 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. */
9186
9270
  var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
9271
+ /* c8 ignore next -- Defensive: see comment above. */
9187
9272
  var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
9188
9273
 
9189
9274
  // We could adapt the approach at https://stackoverflow.com/a/8430746/271577
9190
9275
  // to make the approach reusable without passing column names, but it is a bit fragile
9191
9276
  /** @type {import('./IDBTransaction.js').IDBTransactionFull} */
9192
9277
  store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
9278
+ /* 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. */
9193
9279
  /**
9194
9280
  * @param {WebSQLTransaction} tx
9195
9281
  * @param {(Error & {code?: number})} err
@@ -9198,6 +9284,7 @@
9198
9284
  function sqlError(tx, err) {
9199
9285
  error(err);
9200
9286
  }
9287
+ /* c8 ignore stop -- see comment above */
9201
9288
  /**
9202
9289
  * @returns {void}
9203
9290
  */
@@ -9206,8 +9293,14 @@
9206
9293
  cb(tx, success);
9207
9294
  return;
9208
9295
  }
9296
+ /* 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. */
9209
9297
  success();
9210
9298
  }
9299
+ /* c8 ignore stop -- see comment above */
9300
+ if (!CFG.useSQLiteIndexes) {
9301
+ finish();
9302
+ return;
9303
+ }
9211
9304
  // See https://www.sqlite.org/lang_altertable.html#otheralter
9212
9305
  // We don't query for indexes as we already have the info
9213
9306
  // This approach has the advantage of auto-deleting indexes via the DROP TABLE
@@ -9231,10 +9324,6 @@
9231
9324
  console.log(sql);
9232
9325
  }
9233
9326
  tx.executeSql(sql, [], function (tx) {
9234
- if (!CFG.useSQLiteIndexes) {
9235
- finish();
9236
- return;
9237
- }
9238
9327
  var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
9239
9328
  .map(function (escapedIndexNameSQL) {
9240
9329
  return new SyncPromise(function (resolve, reject) {
@@ -9243,13 +9332,16 @@
9243
9332
  // if (CFG.DEBUG) { console.log(sql); }
9244
9333
  // tx.executeSql(sql, [], function () {
9245
9334
  var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
9335
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
9246
9336
  if (CFG.DEBUG) {
9247
9337
  console.log(sql);
9248
9338
  }
9249
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9339
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9340
+ /** @type {SqlErrorCallback} */
9250
9341
  function (tx, err) {
9251
9342
  reject(err);
9252
- });
9343
+ }
9344
+ /* c8 ignore stop -- see comment above */);
9253
9345
  // }, function (tx, err) {
9254
9346
  // reject(err);
9255
9347
  // });
@@ -9267,19 +9359,25 @@
9267
9359
  if (CFG.DEBUG) {
9268
9360
  console.log(sql);
9269
9361
  }
9270
- tx.executeSql(sql, [], resolve, /** @type {SqlErrorCallback} */
9362
+ tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9363
+ /** @type {SqlErrorCallback} */
9271
9364
  function (tx, err) {
9272
9365
  reject(err);
9273
- });
9274
- }, /** @type {SqlErrorCallback} */
9366
+ }
9367
+ /* c8 ignore stop -- see comment above */);
9368
+ }, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9369
+ /** @type {SqlErrorCallback} */
9275
9370
  function (tx, err) {
9276
9371
  reject(err);
9277
- });
9372
+ }
9373
+ /* c8 ignore stop -- see comment above */);
9278
9374
  }));
9279
9375
  SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
9280
9376
  error).catch(function (err) {
9377
+ /* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
9281
9378
  console.log('Index rename error');
9282
9379
  throw err;
9380
+ /* c8 ignore stop -- see comment above */
9283
9381
  });
9284
9382
  }, /** @type {SqlErrorCallback} */sqlError);
9285
9383
  }, /** @type {SqlErrorCallback} */sqlError);
@@ -9308,7 +9406,6 @@
9308
9406
  /* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
9309
9407
 
9310
9408
  /**
9311
- * @param {number|null} count
9312
9409
  * @param {boolean} unboundedDisallowed
9313
9410
  * @param {IDBIndexFull} index
9314
9411
  * @param {boolean} hasKey
@@ -9325,12 +9422,9 @@
9325
9422
  * @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
9326
9423
  * @returns {void}
9327
9424
  */
9328
- function executeFetchIndexData(count, unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9425
+ function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
9329
9426
  if (unboundedDisallowed) {
9330
- count = 1;
9331
- }
9332
- if (count) {
9333
- sql.push('LIMIT', String(count));
9427
+ sql.push('LIMIT', '1');
9334
9428
  }
9335
9429
  var isCount = opType === 'count';
9336
9430
  if (CFG.DEBUG) {
@@ -9368,41 +9462,48 @@
9368
9462
  var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
9369
9463
  var encodedKey = _encode(range, index.multiEntry);
9370
9464
  var _loop = function _loop() {
9371
- var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9372
- var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9373
- _decode(row[escapedIndexNameForKeyCol]);
9374
- var record;
9375
- if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9376
- /**
9377
- * @param {import('./Key.js').ValueType} check
9378
- * @returns {boolean}
9379
- */
9380
- function (check) {
9381
- return rowKey.includes(check);
9382
- }) ||
9383
- // More precise than our SQL
9384
- isMultiEntryMatch(
9385
- // Added `JSON.stringify` as was having problems with
9386
- // `JSON.stringify` encoding added to nested
9387
- // array keys
9388
- JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9389
- recordCount++;
9390
- record = row;
9391
- } else if (!hasKey && !multiChecks) {
9392
- if (rowKey !== undefined) {
9393
- recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9465
+ var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
9466
+ var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
9467
+ _decode(row[escapedIndexNameForKeyCol]);
9468
+ var record;
9469
+ if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
9470
+ /**
9471
+ * @param {import('./Key.js').ValueType} check
9472
+ * @returns {boolean}
9473
+ */
9474
+ function (check) {
9475
+ return rowKey.includes(check);
9476
+ }) ||
9477
+ // More precise than our SQL
9478
+ isMultiEntryMatch(
9479
+ // Added `JSON.stringify` as was having problems with
9480
+ // `JSON.stringify` encoding added to nested
9481
+ // array keys
9482
+ JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
9483
+ recordCount++;
9394
9484
  record = row;
9485
+ } else if (!hasKey && !multiChecks) {
9486
+ if (rowKey !== undefined) {
9487
+ recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
9488
+ record = row;
9489
+ }
9395
9490
  }
9396
- }
9397
- if (record) {
9491
+ /* 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. */
9492
+ if (!record) {
9493
+ return 0; // continue
9494
+ }
9495
+ /* c8 ignore stop -- see comment above */
9496
+
9398
9497
  records.push(decode$1(record));
9399
9498
  if (unboundedDisallowed) {
9400
9499
  return 1; // break
9401
9500
  }
9402
- }
9403
- };
9501
+ },
9502
+ _ret;
9404
9503
  for (var i = 0; i < data.rows.length; i++) {
9405
- if (_loop()) break;
9504
+ _ret = _loop();
9505
+ if (_ret === 0) continue;
9506
+ if (_ret === 1) break;
9406
9507
  }
9407
9508
  } else {
9408
9509
  for (var _i = 0; _i < data.rows.length; _i++) {
@@ -9416,8 +9517,16 @@
9416
9517
  if (isCount) {
9417
9518
  success(recordCount);
9418
9519
  } else if (recordCount === 0) {
9520
+ // `unboundedDisallowed` is always `true` here: this function is only reached (for
9521
+ // non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
9522
+ // through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
9523
+ // different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
9524
+ // (returning `[]` here) is unreachable given current callers.
9525
+ /* c8 ignore next -- see comment above */
9419
9526
  success(unboundedDisallowed ? undefined : []);
9420
9527
  } else {
9528
+ // `unboundedDisallowed` is always `true` here; see comment above.
9529
+ /* c8 ignore next -- see comment above */
9421
9530
  success(unboundedDisallowed ? records[0] : records);
9422
9531
  }
9423
9532
  }, /** @type {SqlErrorCallback} */error);
@@ -9661,6 +9770,7 @@
9661
9770
  tx.executeSql(sql, sqlValues, function (tx) {
9662
9771
  // This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
9663
9772
  var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
9773
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
9664
9774
  if (CFG.DEBUG) {
9665
9775
  console.log(sql);
9666
9776
  }
@@ -9669,8 +9779,10 @@
9669
9779
  success();
9670
9780
  });
9671
9781
  }, function (tx, err) {
9782
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9672
9783
  error(err);
9673
9784
  return false;
9785
+ /* c8 ignore stop -- see comment above */
9674
9786
  });
9675
9787
  });
9676
9788
  }
@@ -9744,6 +9856,7 @@
9744
9856
  storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
9745
9857
  }
9746
9858
  transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
9859
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9747
9860
  /**
9748
9861
  * @param {WebSQLTransaction} tx
9749
9862
  * @param {(Error & {code?: number})} [err]
@@ -9756,6 +9869,8 @@
9756
9869
  failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
9757
9870
  return false;
9758
9871
  }
9872
+ /* c8 ignore stop -- see comment above */
9873
+
9759
9874
  var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
9760
9875
  // key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
9761
9876
  var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
@@ -9810,6 +9925,7 @@
9810
9925
 
9811
9926
  // Remove the object store from WebSQL
9812
9927
  transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
9928
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
9813
9929
  /**
9814
9930
  * @param {WebSQLTransaction} tx
9815
9931
  * @param {(Error & {code?: number})} [err]
@@ -9822,6 +9938,8 @@
9822
9938
  failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
9823
9939
  return false;
9824
9940
  }
9941
+ /* c8 ignore stop -- see comment above */
9942
+
9825
9943
  tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
9826
9944
  if (data.rows.length > 0) {
9827
9945
  tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
@@ -10001,13 +10119,15 @@
10001
10119
  return;
10002
10120
  }
10003
10121
  var indexKeyValue = indexKey.value;
10122
+ /* 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. */
10004
10123
  if (indexKeyValue === undefined) {
10005
10124
  resolve(undefined);
10006
10125
  return;
10007
10126
  }
10127
+ /* c8 ignore stop -- see comment above */
10008
10128
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
10009
10129
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
10010
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10130
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
10011
10131
  if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
10012
10132
  resolve(undefined);
10013
10133
  return;
@@ -10087,16 +10207,18 @@
10087
10207
  * @returns {void}
10088
10208
  */
10089
10209
  function setIndexInfo(index) {
10210
+ /* 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. */
10090
10211
  if (indexKeyValue === undefined) {
10091
10212
  return;
10092
10213
  }
10214
+ /* c8 ignore stop -- see comment above */
10093
10215
  paramMap[index.__currentName] = /** @type {string} */
10094
10216
  _encode(indexKeyValue, index.multiEntry);
10095
10217
  }
10096
10218
  if (index.unique) {
10097
10219
  var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
10098
10220
  var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
10099
- executeFetchIndexData.apply(void 0, [null].concat(_toConsumableArray(fetchArgs), [tx, null, function success(key) {
10221
+ executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
10100
10222
  if (key === undefined) {
10101
10223
  setIndexInfo(index);
10102
10224
  resolve(undefined);
@@ -10187,6 +10309,7 @@
10187
10309
  _me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
10188
10310
  ky = _me$__validateKeyAndV2[0],
10189
10311
  clonedValue = _me$__validateKeyAndV2[1];
10312
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10190
10313
  // @ts-ignore -- Private API
10191
10314
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
10192
10315
  return request;
@@ -10218,6 +10341,7 @@
10218
10341
  _me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
10219
10342
  ky = _me$__validateKeyAndV4[0],
10220
10343
  clonedValue = _me$__validateKeyAndV4[1];
10344
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
10221
10345
  // @ts-ignore -- Private API
10222
10346
  IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
10223
10347
  return request;
@@ -10244,8 +10368,10 @@
10244
10368
  }
10245
10369
  cb(tx);
10246
10370
  }, function (tx, err) {
10371
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10247
10372
  error(err);
10248
10373
  return false;
10374
+ /* c8 ignore stop -- see comment above */
10249
10375
  });
10250
10376
  };
10251
10377
 
@@ -10354,16 +10480,20 @@
10354
10480
  return;
10355
10481
  }
10356
10482
  ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
10483
+ /* 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. */
10357
10484
  } catch (e) {
10358
10485
  // If no result is returned, or error occurs when parsing JSON
10359
10486
  if (CFG.DEBUG) {
10360
10487
  console.log(e);
10361
10488
  }
10362
10489
  }
10490
+ /* c8 ignore stop -- see comment above */
10363
10491
  success(ret);
10364
10492
  }, function (tx, err) {
10493
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10365
10494
  error(err);
10366
10495
  return false;
10496
+ /* c8 ignore stop -- see comment above */
10367
10497
  });
10368
10498
  }, undefined, me);
10369
10499
  };
@@ -10475,8 +10605,10 @@
10475
10605
  });
10476
10606
  success();
10477
10607
  }, function (tx, err) {
10608
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10478
10609
  error(err);
10479
10610
  return false;
10611
+ /* c8 ignore stop -- see comment above */
10480
10612
  });
10481
10613
  }, undefined, me);
10482
10614
  };
@@ -10504,8 +10636,10 @@
10504
10636
  });
10505
10637
  success();
10506
10638
  }, function (tx, err) {
10639
+ /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
10507
10640
  error(err);
10508
10641
  return false;
10642
+ /* c8 ignore stop -- see comment above */
10509
10643
  });
10510
10644
  }, undefined, me);
10511
10645
  };
@@ -10840,7 +10974,7 @@
10840
10974
  if (keyPath !== null && !isValidKeyPath(keyPath)) {
10841
10975
  throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
10842
10976
  }
10843
- if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
10977
+ if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
10844
10978
  throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
10845
10979
  }
10846
10980
  var autoInc = createOptions.autoIncrement;
@@ -10989,7 +11123,6 @@
10989
11123
  }
10990
11124
  };
10991
11125
 
10992
- // Todo __forceClose: Add tests for `__forceClose`
10993
11126
  /**
10994
11127
  *
10995
11128
  * @param {string} msg
@@ -10998,23 +11131,39 @@
10998
11131
  */
10999
11132
  IDBDatabase.prototype.__forceClose = function (msg) {
11000
11133
  var me = this;
11134
+ // `close()` (below) resets `me.__transactions` to `[]`, so the
11135
+ // transactions to abort -- and the total count the completion check
11136
+ // below needs -- must be captured before calling it, not read back off
11137
+ // `me.__transactions` afterward.
11138
+ var transactions = me.__transactions;
11001
11139
  me.close();
11140
+
11141
+ /**
11142
+ * @returns {void}
11143
+ */
11144
+ function dispatchClose() {
11145
+ // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
11146
+ var evt = createEvent('close');
11147
+ setTimeout(function () {
11148
+ me.dispatchEvent(evt);
11149
+ }, 0);
11150
+ }
11151
+ if (!transactions.length) {
11152
+ dispatchClose();
11153
+ return;
11154
+ }
11002
11155
  var ct = 0;
11003
- me.__transactions.forEach(function (trans) {
11156
+ transactions.forEach(function (trans) {
11004
11157
  // eslint-disable-next-line camelcase -- Clear API
11005
11158
  trans.on__abort = function () {
11006
11159
  ct++;
11007
- if (ct === me.__transactions.length) {
11008
- // Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
11009
- var evt = createEvent('close');
11010
- setTimeout(function () {
11011
- me.dispatchEvent(evt);
11012
- }, 0);
11160
+ if (ct !== transactions.length) {
11161
+ return;
11013
11162
  }
11163
+ dispatchClose();
11014
11164
  };
11015
11165
  trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
11016
11166
  });
11017
- me.__transactions = [];
11018
11167
  };
11019
11168
  /* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
11020
11169
  defineOuterInterface(IDBDatabase.prototype, listeners);
@@ -11181,6 +11330,7 @@
11181
11330
  return undefined;
11182
11331
  }
11183
11332
  var e = /** @type {Event & IDBVersionChangeEvent} */
11333
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11184
11334
  // @ts-ignore It's ok; needed under some TS versions
11185
11335
  new IDBVersionChangeEvent('versionchange', {
11186
11336
  oldVersion: oldVersion,
@@ -11228,6 +11378,7 @@
11228
11378
  }
11229
11379
  };
11230
11380
  var e = /** @type {Event & IDBVersionChangeEvent} */
11381
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11231
11382
  // @ts-ignore It's ok; needed under some TS versions
11232
11383
  new IDBVersionChangeEvent('blocked', {
11233
11384
  oldVersion: oldVersion,
@@ -11288,6 +11439,13 @@
11288
11439
 
11289
11440
  /** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
11290
11441
  var sysdb;
11442
+ // Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
11443
+ // later change to that config (e.g. toggling in-memory mode on and back
11444
+ // off) causes `sysdb` to be recreated for the new setting rather than
11445
+ // staying pinned, forever, to whatever it was the first time any database
11446
+ // was created in the process.
11447
+ /** @type {string|null|undefined} */
11448
+ var sysdbMemoryDatabaseSetting;
11291
11449
  var nameCounter = 0;
11292
11450
 
11293
11451
  /**
@@ -11369,12 +11527,20 @@
11369
11527
  function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
11370
11528
  var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
11371
11529
  if (useMemoryDatabase) {
11530
+ /* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
11531
+ was initialized as an empty placeholder by `open()`'s connection-queue
11532
+ setup (`addRequestToConnectionQueue`, above `openDB`) but never
11533
+ populated with an actual instance -- e.g. `__openDatabase` throwing
11534
+ after a `dbVersions` row already existed for `name` from an earlier,
11535
+ successful `open()` -- or if `name` was never added to the cache at
11536
+ all. Not reachable via normal, non-tampered API usage. */
11372
11537
  var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
11373
11538
  if (!latestSQLiteDBCached) {
11374
11539
  console.warn('Could not find a memory database instance to delete.');
11375
11540
  databaseDeleted();
11376
11541
  return;
11377
11542
  }
11543
+ /* c8 ignore stop -- see comment above */
11378
11544
  var _sqliteDB = latestSQLiteDBCached._db;
11379
11545
  if (!_sqliteDB || !_sqliteDB.close) {
11380
11546
  console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
@@ -11428,15 +11594,24 @@
11428
11594
  tables.item(i).name)), [], function () {
11429
11595
  deleteTables(i + 1);
11430
11596
  }, function () {
11597
+ /* c8 ignore start -- Defensive: continues deleting the rest
11598
+ even if this specific store's table is already gone (e.g.
11599
+ duplicate `__sys__` rows for the same escaped table name, or
11600
+ external tampering); not reachable via normal API usage. */
11431
11601
  deleteTables(i + 1);
11432
11602
  return false;
11603
+ /* c8 ignore stop -- see comment above */
11433
11604
  });
11434
11605
  }
11435
11606
  })(0);
11436
11607
  }, function () {
11437
- // __sys__ table does not exist, but that does not mean delete did not happen
11608
+ /* c8 ignore start -- `__sys__` is always created by `openDB` before this
11609
+ database's `dbVersions` row (a prerequisite for reaching this code at
11610
+ all) is ever inserted; only reachable if the file was tampered with/
11611
+ removed externally afterward. */
11438
11612
  databaseDeleted();
11439
11613
  return false;
11614
+ /* c8 ignore stop -- see comment above */
11440
11615
  });
11441
11616
  });
11442
11617
  }
@@ -11467,9 +11642,11 @@
11467
11642
  }
11468
11643
  failure(er);
11469
11644
  }
11470
- if (sysdb) {
11645
+ if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
11471
11646
  success();
11472
11647
  } else {
11648
+ // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
11649
+ sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
11473
11650
  // eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
11474
11651
  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);
11475
11652
  sysdb.transaction(function (systx) {
@@ -11649,6 +11826,17 @@
11649
11826
  * @returns {void}
11650
11827
  */
11651
11828
  var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11829
+ /* c8 ignore start -- This initial definition is always
11830
+ superseded before ever being invoked: the `sysdb.transaction(...)`
11831
+ call below always reaches its `nonstandardTransCb` (4th arg)
11832
+ after this same SQL batch finishes running (since `dbCreateError`
11833
+ always reports errors as "handled" and this call site is never
11834
+ a `readTransaction`), which unconditionally reassigns
11835
+ `sysdbFinishedCb` to a version using the library's own
11836
+ `rollback`/`commit` -- well before any real invocation from
11837
+ `on__beforecomplete`/`on__preabort`/`on__abort` below (those only
11838
+ fire once the upgrade transaction itself later completes/aborts).
11839
+ Kept as a defensive fallback in case that invariant ever changes. */
11652
11840
  if (err) {
11653
11841
  /**
11654
11842
  * @param {unknown} [errorToShow]
@@ -11697,6 +11885,7 @@
11697
11885
  }
11698
11886
  // In browser, should auto-commit
11699
11887
  cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11888
+ /* c8 ignore stop -- see comment above */
11700
11889
  };
11701
11890
  sysdb.transaction(function (systx) {
11702
11891
  /**
@@ -11704,6 +11893,7 @@
11704
11893
  */
11705
11894
  function versionSet() {
11706
11895
  var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
11896
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
11707
11897
  // @ts-ignore It's ok; needed under some TS versions
11708
11898
  new IDBVersionChangeEvent('upgradeneeded', {
11709
11899
  oldVersion: oldVersion,
@@ -11829,9 +12019,17 @@
11829
12019
  // eslint-disable-next-line camelcase -- Clear API
11830
12020
  req.transaction.on__complete = function () {
11831
12021
  var pos = connection.__transactions.indexOf(req.transaction);
12022
+ // `req.transaction` (the versionchange transaction) is created
12023
+ // directly via `IDBTransaction.__createInstance` above, never
12024
+ // via `IDBDatabase.prototype.transaction()` (the only place
12025
+ // that pushes onto `connection.__transactions`), so `pos` is
12026
+ // always -1 here.
12027
+ /* c8 ignore start -- see comment above */
11832
12028
  if (pos !== -1) {
11833
12029
  connection.__transactions.splice(pos, 1);
11834
12030
  }
12031
+ /* c8 ignore stop -- see comment above */
12032
+
11835
12033
  if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
11836
12034
  req.__transaction = null;
11837
12035
  var err = createDOMException('AbortError', 'The connection has been closed.');
@@ -11867,9 +12065,16 @@
11867
12065
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
11868
12066
  }
11869
12067
  }, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
12068
+ // Defensive fallback, not reachable in practice: same reasoning
12069
+ // as `deleteDatabase`'s own `nonstandardTransCb` below
12070
+ // (`currentTask.readOnly` is always false here, and
12071
+ // `dbCreateError` always returns `false`, so `err` is never
12072
+ // truthy either).
12073
+ /* c8 ignore start -- see comment above */
11870
12074
  if (currentTask.readOnly || err) {
11871
12075
  return true;
11872
12076
  }
12077
+ /* c8 ignore stop -- see comment above */
11873
12078
  sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
11874
12079
  if (err) {
11875
12080
  rollback(err,
@@ -11884,7 +12089,17 @@
11884
12089
  } else {
11885
12090
  systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
11886
12091
  }
11887
- }, function (sqlErr) {
12092
+ },
12093
+ // Deeply-nested defensive path: only reached if
12094
+ // the *revert* SQL (undoing the `dbVersions`
12095
+ // INSERT/UPDATE after the original version-
12096
+ // upgrade itself already failed) fails a
12097
+ // *second* time. Not feasibly triggerable
12098
+ // without fault-injecting the underlying SQL
12099
+ // driver on this specific, already-failing
12100
+ // revert statement.
12101
+ function (sqlErr) {
12102
+ /* c8 ignore next 2 -- see comment above */
11888
12103
  isRevertingSysdb = false;
11889
12104
  cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
11890
12105
  }, function () {
@@ -11900,8 +12115,20 @@
11900
12115
  });
11901
12116
  return undefined;
11902
12117
  }).catch(function (err) {
12118
+ /* c8 ignore start -- Purely defensive: nothing in
12119
+ `triggerAnyVersionChangeAndBlockedEvents`'s promise chain
12120
+ (or this `.then()` continuation above) ever rejects/throws
12121
+ under any reachable application-level condition -- all of
12122
+ its continuations resolve cleanly, and its `dispatchEvent`
12123
+ calls are deliberately fire-and-forget ("No need to catch
12124
+ errors"), running inside a `setTimeout` where a listener
12125
+ throwing becomes an uncaught exception in that macrotask
12126
+ rather than a promise rejection here. This exists solely
12127
+ to surface a truly-unexpected internal bug via the console
12128
+ before rethrowing, not to handle a real, testable error path. */
11903
12129
  console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
11904
12130
  throw err;
12131
+ /* c8 ignore stop -- see comment above */
11905
12132
  });
11906
12133
  } else {
11907
12134
  finishRequest();
@@ -11929,11 +12156,19 @@
11929
12156
  if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
11930
12157
  db = websqlDBCache[name][version];
11931
12158
  } else {
11932
- db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
12159
+ db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
11933
12160
  if (useDatabaseCache) {
12161
+ /* c8 ignore start -- Defensive: by the time `openDB` runs,
12162
+ `websqlDBCache[name]` has always already been created by
12163
+ `addRequestToConnectionQueue`'s own callback above (guarded
12164
+ by this same `useDatabaseCache` condition), which always
12165
+ runs first and unconditionally ensures the entry exists
12166
+ before ever calling `openDB`. Kept as a safety net in case
12167
+ that invariant ever changes. */
11934
12168
  if (!Object.hasOwn(websqlDBCache, name)) {
11935
12169
  websqlDBCache[name] = {};
11936
12170
  }
12171
+ /* c8 ignore stop -- see comment above */
11937
12172
  websqlDBCache[name][version] = db;
11938
12173
  }
11939
12174
  }
@@ -12084,6 +12319,7 @@
12084
12319
  req.__result = undefined;
12085
12320
  req.__done = true;
12086
12321
  var e = /** @type {Event & IDBVersionChangeEvent} */
12322
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12087
12323
  // @ts-ignore It's ok; needed under some TS versions
12088
12324
  new IDBVersionChangeEvent('success', {
12089
12325
  oldVersion: version,
@@ -12126,9 +12362,23 @@
12126
12362
  cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
12127
12363
  }, dbError);
12128
12364
  }, dbError, undefined, function (currentTask, err, done, rollback, commit) {
12365
+ /* c8 ignore start -- Defensive fallback, not reachable in
12366
+ practice: `currentTask.readOnly` is always `false` here
12367
+ (this callback is only ever attached to the writable
12368
+ `sysdb.transaction(...)` call above, never to a
12369
+ `sysdb.readTransaction(...)`), and `err` can only be
12370
+ truthy if the `DELETE FROM dbVersions` statement's own
12371
+ error callback (`dbError`) reports the failure back to
12372
+ `websql-configurable` as unhandled -- but `dbError`
12373
+ deliberately always `return`s `false`, which tells the
12374
+ library the error was already handled (and to keep
12375
+ `err` falsy here), precisely so this custom
12376
+ `sysdbFinishedCbDelete` rollback/commit path below is
12377
+ used instead of the library's own default rollback. */
12129
12378
  if (currentTask.readOnly || err) {
12130
12379
  return true;
12131
12380
  }
12381
+ /* c8 ignore stop -- see comment above */
12132
12382
  sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
12133
12383
  if (err) {
12134
12384
  rollback(err, cb);
@@ -12254,10 +12504,9 @@
12254
12504
  };
12255
12505
 
12256
12506
  /**
12257
- * @todo forceClose: Test
12258
12507
  * This is provided to facilitate unit-testing of the
12259
12508
  * closing of a database connection with a forced flag:
12260
- * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>
12509
+ * <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
12261
12510
  * @param {string} dbName
12262
12511
  * @param {Integer} connIdx
12263
12512
  * @param {string} msg
@@ -12358,6 +12607,7 @@
12358
12607
  * @this {IDBRecordFull}
12359
12608
  */
12360
12609
  function IDBRecord() {
12610
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12361
12611
  // @ts-ignore Should be ok
12362
12612
  this[Symbol.toStringTag] = 'IDBRecord';
12363
12613
  this.__key = key;
@@ -12394,6 +12644,7 @@
12394
12644
  if (!(this instanceof IDBRecordAlias)) {
12395
12645
  throw new TypeError('Illegal invocation');
12396
12646
  }
12647
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
12397
12648
  // @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
12398
12649
  return this['__' + prop];
12399
12650
  });
@@ -12736,6 +12987,7 @@
12736
12987
  success(undefined, undefined, undefined);
12737
12988
  }
12738
12989
  }, function (tx, err) {
12990
+ /* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
12739
12991
  if (CFG.DEBUG) {
12740
12992
  console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
12741
12993
  }
@@ -12919,7 +13171,16 @@
12919
13171
  if (a.key > b.key) {
12920
13172
  return me.direction === 'prev' ? -1 : 1;
12921
13173
  }
13174
+ /* c8 ignore start -- Defensive: only reachable if two matches
13175
+ in the same batch shared both the same `matchingKey` and
13176
+ the same primary `key`, which would require the same
13177
+ record's multi-entry array to contain a duplicate value.
13178
+ `Key.js`'s array-to-key conversion already drops duplicate
13179
+ values when a multi-entry index entry is built, so this
13180
+ can never happen in practice; kept only to satisfy the
13181
+ `Array.prototype.sort` comparator contract. */
12922
13182
  return 0;
13183
+ /* c8 ignore stop -- see comment above */
12923
13184
  });
12924
13185
  me.__prefetchedIndex = 0;
12925
13186
  me.__prefetchedData = {
@@ -12938,13 +13199,19 @@
12938
13199
  console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
12939
13200
  }
12940
13201
  me.__decode(rows[0], success);
12941
- }, function (tx, err) {
13202
+ },
13203
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13204
+ execution error (e.g. I/O error, corruption) while querying for
13205
+ multi-entry cursor matches; not reliably reproducible without
13206
+ mocking the SQL layer. */
13207
+ function (tx, err) {
12942
13208
  if (CFG.DEBUG) {
12943
13209
  console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
12944
13210
  }
12945
13211
  error(err);
12946
13212
  return false;
12947
13213
  });
13214
+ /* c8 ignore stop -- see comment above */
12948
13215
  }
12949
13216
  runQuery();
12950
13217
  };
@@ -13053,6 +13320,7 @@
13053
13320
  * @returns {void}
13054
13321
  */
13055
13322
  IDBCursor.prototype.__invalidateCache = function () {
13323
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13056
13324
  // @ts-ignore Why is this not being found?; needed under some TS versions
13057
13325
  this.__prefetchedData = null;
13058
13326
  this.__multiEntryExhausted = false;
@@ -13077,7 +13345,7 @@
13077
13345
  convertValueToKeyRethrowingAndIfInvalid(key);
13078
13346
  var cmpResult = cmp(key, me.key);
13079
13347
  if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
13080
- throw createDOMException('DataError', 'Cannot ' + (advanceState ? 'advance' : 'continue') + ' the cursor in an unexpected direction');
13348
+ throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
13081
13349
  }
13082
13350
  }
13083
13351
  this.__continueFinish(key, undefined, advanceState);
@@ -13334,6 +13602,7 @@
13334
13602
  // continuation logic in `__findBasic` to see this update's
13335
13603
  // effect on ordering (see "Modify records during cursor
13336
13604
  // iteration" in idbcursor_update_index.any.js).
13605
+ // eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
13337
13606
  // @ts-ignore -- API (not erring in TS 6)
13338
13607
  IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
13339
13608
  }
@@ -13383,14 +13652,33 @@
13383
13652
  // We don't invalidate the cache (as we don't access it anymore
13384
13653
  // and it will set the index off)
13385
13654
  success(undefined);
13655
+ /* c8 ignore start -- Defensive: `__find` (invoked just above) has
13656
+ already confirmed a row exists for this primary key within the
13657
+ same transaction queue, so `rowsAffected` should always be 1 in
13658
+ normal usage. This branch would only be reached if the underlying
13659
+ row were removed by another request queued in the same
13660
+ transaction between `__find`'s check and this DELETE actually
13661
+ running (e.g. deleting the same record directly via the object
13662
+ store while a cursor over it is mid-iteration); attempts to
13663
+ construct such a scenario instead trigger a transaction abort
13664
+ (`AbortError`) before this callback ever runs, since the default
13665
+ action of an unhandled request error is to abort the
13666
+ transaction. */
13386
13667
  } else {
13387
13668
  // @ts-expect-error Apparently ok
13388
13669
  error('No rows with key found' + key);
13389
13670
  }
13390
- }, function (tx, data) {
13671
+ /* c8 ignore stop -- see comment above */
13672
+ },
13673
+ /* c8 ignore start -- Defensive: guards against an unexpected SQLite
13674
+ execution error (e.g. I/O error, corruption) while deleting the
13675
+ current row; not reliably reproducible without mocking the SQL
13676
+ layer. */
13677
+ function (tx, data) {
13391
13678
  error(data);
13392
13679
  return false;
13393
13680
  });
13681
+ /* c8 ignore stop -- see comment above */
13394
13682
  }, error);
13395
13683
  }, undefined, me);
13396
13684
  };
@@ -13798,7 +14086,7 @@
13798
14086
  */
13799
14087
  function setGlobalVars(idb, initialConfig) {
13800
14088
  var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
13801
- /** @type {unknown} */globalThis || {};
14089
+ /** @type {unknown} */globalThis;
13802
14090
  /**
13803
14091
  * @param {string} name
13804
14092
  * @param {unknown} value
@@ -13889,80 +14177,87 @@
13889
14177
  });
13890
14178
  }
13891
14179
  var shimIDBFactory = IDBFactory;
13892
- if (CFG.win.openDatabase !== undefined) {
13893
- shimIndexedDB$1.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
13894
- // Polyfill ALL of IndexedDB, using WebSQL
13895
- shim('indexedDB', shimIndexedDB$1, {
13896
- enumerable: true,
13897
- configurable: true,
13898
- get: function get() {
13899
- if (this !== IDB && !isNullish(this) && !this.shimNS) {
13900
- // Latter is hack for test environment
13901
- throw new TypeError('Illegal invocation');
13902
- }
13903
- return shimIndexedDB$1;
14180
+ if (CFG.win.openDatabase === undefined) {
14181
+ return;
14182
+ }
14183
+ shimIndexedDB$1.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
14184
+ // Polyfill ALL of IndexedDB, using WebSQL
14185
+ shim('indexedDB', shimIndexedDB$1, {
14186
+ enumerable: true,
14187
+ configurable: true,
14188
+ get: function get() {
14189
+ if (this !== IDB && !isNullish(this) && !this.shimNS) {
14190
+ // Latter is hack for test environment
14191
+ throw new TypeError('Illegal invocation');
13904
14192
  }
13905
- });
13906
- /** @type {[string, unknown][]} */
13907
- [['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) {
13908
- var _ref4 = _slicedToArray(_ref3, 2),
13909
- prop = _ref4[0],
13910
- obj = _ref4[1];
13911
- shim(prop, obj, {
13912
- enumerable: false,
13913
- configurable: true
13914
- });
13915
- });
13916
- // For Node environments
13917
- if (CFG.fs) {
13918
- setFS(CFG.fs);
14193
+ return shimIndexedDB$1;
13919
14194
  }
13920
- if (CFG.fullIDLSupport) {
13921
- // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
13922
-
13923
- Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
13924
- Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
13925
- Object.setPrototypeOf(IDBDatabase, EventTarget);
13926
- Object.setPrototypeOf(IDBRequest, EventTarget);
13927
- Object.setPrototypeOf(IDBTransaction, EventTarget);
13928
- Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
13929
- // `ShimDOMException` is the real native `DOMException` when one
13930
- // is available (see `DOMException.js`'s `useNativeDOMException`)
13931
- // -- which, unlike the shim classes above, is a single,
13932
- // process-wide singleton shared by reference across every
13933
- // sandbox this library gets installed into (see
13934
- // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
13935
- // already has the correct prototype chain out of the box
13936
- // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
13937
- // not `Error`), so forcing it here isn't just unneeded but
13938
- // actively wrong -- and, because it's shared, permanently
13939
- // wrong for every later use of `DOMException` in the same
13940
- // process (e.g. a later WPT test file's own idlharness-style
13941
- // check that `DOMException` does *not* inherit from `Error`
13942
- // on the class side), not just this one shim install.
13943
- if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
13944
- Object.setPrototypeOf(ShimDOMException, Error);
13945
- Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13946
- }
14195
+ });
14196
+ /** @type {[string, unknown][]} */
14197
+ [['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) {
14198
+ var _ref4 = _slicedToArray(_ref3, 2),
14199
+ prop = _ref4[0],
14200
+ obj = _ref4[1];
14201
+ shim(prop, obj, {
14202
+ enumerable: false,
14203
+ configurable: true
14204
+ });
14205
+ });
14206
+ // For Node environments
14207
+ if (CFG.fs) {
14208
+ setFS(CFG.fs);
14209
+ }
14210
+ if (CFG.fullIDLSupport) {
14211
+ // Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
14212
+
14213
+ Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
14214
+ Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
14215
+ Object.setPrototypeOf(IDBDatabase, EventTarget);
14216
+ Object.setPrototypeOf(IDBRequest, EventTarget);
14217
+ Object.setPrototypeOf(IDBTransaction, EventTarget);
14218
+ Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
14219
+ // `ShimDOMException` is the real native `DOMException` when one
14220
+ // is available (see `DOMException.js`'s `useNativeDOMException`)
14221
+ // -- which, unlike the shim classes above, is a single,
14222
+ // process-wide singleton shared by reference across every
14223
+ // sandbox this library gets installed into (see
14224
+ // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
14225
+ // already has the correct prototype chain out of the box
14226
+ // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
14227
+ // not `Error`), so forcing it here isn't just unneeded but
14228
+ // actively wrong -- and, because it's shared, permanently
14229
+ // wrong for every later use of `DOMException` in the same
14230
+ // process (e.g. a later WPT test file's own idlharness-style
14231
+ // check that `DOMException` does *not* inherit from `Error`
14232
+ // on the class side), not just this one shim install.
14233
+ if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
14234
+ Object.setPrototypeOf(ShimDOMException, Error);
14235
+ Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
13947
14236
  }
13948
- if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
13949
- if (CFG.addNonIDBGlobals) {
13950
- // As `DOMStringList` exists per IDL (and Chrome) in the global
13951
- // thread (but not in workers), we prefix the name to avoid
13952
- // shadowing or conflicts
13953
- setNonIDBGlobals('Shim');
13954
- }
13955
- if (CFG.replaceNonIDBGlobals) {
13956
- setNonIDBGlobals();
13957
- }
14237
+ }
14238
+ if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
14239
+ if (CFG.addNonIDBGlobals) {
14240
+ // As `DOMStringList` exists per IDL (and Chrome) in the global
14241
+ // thread (but not in workers), we prefix the name to avoid
14242
+ // shadowing or conflicts
14243
+ setNonIDBGlobals('Shim');
13958
14244
  }
13959
- /* c8 ignore start -- TS guard */
13960
- if (!IDB.shimIndexedDB) {
13961
- return;
14245
+ if (CFG.replaceNonIDBGlobals) {
14246
+ setNonIDBGlobals();
13962
14247
  }
13963
- /* c8 ignore stop -- TS guard */
13964
- IDB.shimIndexedDB.__setConnectionQueueOrigin();
13965
14248
  }
14249
+ /* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
14250
+ confirmed truthy just before this function (`__useShim`) was
14251
+ defined and immediately invoked (see the `if ('shimIndexedDB'
14252
+ in IDB && IDB.shimIndexedDB)` guard above), and nothing in
14253
+ this function's body reassigns or deletes it. Only reachable
14254
+ if `IDB` is some unusual object (e.g. a Proxy) whose
14255
+ `shimIndexedDB` property value changes between reads. */
14256
+ if (!IDB.shimIndexedDB) {
14257
+ return;
14258
+ }
14259
+ /* c8 ignore stop -- see comment above */
14260
+ IDB.shimIndexedDB.__setConnectionQueueOrigin();
13966
14261
  };
13967
14262
  IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
13968
14263
  CFG.DEBUG = val;