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.
- package/badges/coverage-badge.svg +1 -1
- package/badges/tests-badge.svg +1 -1
- package/dist/CFG.d.ts +1 -1
- package/dist/CFG.d.ts.map +1 -1
- package/dist/DOMException.d.ts.map +1 -1
- package/dist/IDBCursor.d.ts.map +1 -1
- package/dist/IDBDatabase.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts +1 -2
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBIndex.d.ts +2 -6
- package/dist/IDBIndex.d.ts.map +1 -1
- package/dist/IDBKeyRange.d.ts.map +1 -1
- package/dist/IDBObjectStore.d.ts.map +1 -1
- package/dist/IDBRecord.d.ts.map +1 -1
- package/dist/IDBRequest.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts.map +1 -1
- package/dist/Key.d.ts.map +1 -1
- package/dist/Sca.d.ts.map +1 -1
- package/dist/indexeddbshim-Key.js +40 -28
- package/dist/indexeddbshim-Key.js.map +1 -1
- package/dist/indexeddbshim-Key.min.js +2 -2
- package/dist/indexeddbshim-Key.min.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +511 -217
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +539 -244
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +3 -3
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +511 -217
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +539 -244
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +3 -3
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +539 -244
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +3 -3
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/dist/setGlobalVars.d.ts +1 -1
- package/dist/setGlobalVars.d.ts.map +1 -1
- package/dist/util.d.ts.map +1 -1
- package/package.json +22 -17
- package/src/CFG.js +18 -4
- package/src/DOMException.js +6 -0
- package/src/DOMStringList.js +3 -0
- package/src/IDBCursor.js +36 -3
- package/src/IDBDatabase.js +26 -10
- package/src/IDBFactory.js +105 -5
- package/src/IDBIndex.js +49 -32
- package/src/IDBKeyRange.js +8 -7
- package/src/IDBObjectStore.js +25 -2
- package/src/IDBRecord.js +2 -0
- package/src/IDBRequest.js +7 -4
- package/src/IDBTransaction.js +97 -26
- package/src/Key.js +17 -16
- package/src/Sca.js +9 -4
- package/src/nodeWebSQL.js +1 -0
- package/src/setGlobalVars.js +86 -77
- package/src/util.js +5 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! indexeddbshim - v19.0.
|
|
1
|
+
/*! indexeddbshim - v19.0.6 - 9/22/2026 */
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -110,6 +110,7 @@ const phases = {
|
|
|
110
110
|
const ShimDOMException$1 = typeof DOMException === 'undefined'
|
|
111
111
|
// Todo: Better polyfill (if even needed here)
|
|
112
112
|
/* eslint-disable no-shadow -- Polyfill */
|
|
113
|
+
/* 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) */
|
|
113
114
|
// eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
|
|
114
115
|
?
|
|
115
116
|
/**
|
|
@@ -127,9 +128,10 @@ function DOMException(msg, name) {
|
|
|
127
128
|
configurable: true
|
|
128
129
|
});
|
|
129
130
|
return err;
|
|
130
|
-
}
|
|
131
|
+
}
|
|
132
|
+
/* c8 ignore stop */ : DOMException;
|
|
131
133
|
|
|
132
|
-
/** @type {WeakMap<object,
|
|
134
|
+
/** @type {WeakMap<object, EventWithProps>} */
|
|
133
135
|
const ev = new WeakMap();
|
|
134
136
|
/** @type {WeakMap<object, EventWithProps>} */
|
|
135
137
|
const evCfg = new WeakMap();
|
|
@@ -175,11 +177,12 @@ function definePassthroughProps(instance, props, _evCfg, _ev) {
|
|
|
175
177
|
obj[prop] = {
|
|
176
178
|
configurable: true,
|
|
177
179
|
get() {
|
|
178
|
-
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
180
|
+
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
181
|
+
/* 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;
|
|
179
182
|
}
|
|
180
183
|
};
|
|
181
184
|
return obj;
|
|
182
|
-
}, /** @type {
|
|
185
|
+
}, /** @type {PropertyDescriptorMap} */{}));
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
/**
|
|
@@ -202,8 +205,9 @@ function getIsTrusted() {
|
|
|
202
205
|
throw new TypeError('Illegal invocation');
|
|
203
206
|
}
|
|
204
207
|
const _evCfg = getEvCfg(this);
|
|
205
|
-
const _ev = ev.get(this);
|
|
206
|
-
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
208
|
+
const _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
209
|
+
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
210
|
+
/* 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);
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
/**
|
|
@@ -353,15 +357,15 @@ const ShimEvent = Event;
|
|
|
353
357
|
// this untyped alias, rather than `ShimEvent.prototype` directly, keeps
|
|
354
358
|
// that dynamic-augmentation pattern working without a `@ts-expect-error`
|
|
355
359
|
// on every single line below.
|
|
356
|
-
|
|
357
|
-
const ShimEventProto = ShimEvent.prototype;
|
|
360
|
+
|
|
361
|
+
const ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
|
|
358
362
|
|
|
359
363
|
/** @this {EventWithProps} */
|
|
360
364
|
ShimEventProto.preventDefault = function preventDefault() {
|
|
361
365
|
if (!(this instanceof ShimEvent)) {
|
|
362
366
|
throw new TypeError('Illegal invocation');
|
|
363
367
|
}
|
|
364
|
-
const _ev = ev.get(this);
|
|
368
|
+
const _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
365
369
|
const _evCfg = getEvCfg(this);
|
|
366
370
|
if (this.cancelable && !_evCfg._passive) {
|
|
367
371
|
_evCfg.defaultPrevented = true;
|
|
@@ -547,13 +551,12 @@ class CustomEvent extends Event {
|
|
|
547
551
|
}
|
|
548
552
|
}
|
|
549
553
|
const ShimCustomEvent = CustomEvent;
|
|
550
|
-
/** @type {
|
|
551
|
-
const ShimCustomEventProto = ShimCustomEvent.prototype;
|
|
554
|
+
const ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
|
|
552
555
|
/**
|
|
553
556
|
* @param {string} type
|
|
554
557
|
* @param {boolean} [bubbles]
|
|
555
558
|
* @param {boolean} [cancelable]
|
|
556
|
-
* @param {
|
|
559
|
+
* @param {unknown} [detail]
|
|
557
560
|
* @this {EventWithProps}
|
|
558
561
|
*/
|
|
559
562
|
ShimCustomEventProto.initCustomEvent = function initCustomEvent(type, bubbles = false, cancelable = false, detail = null) {
|
|
@@ -562,6 +565,10 @@ ShimCustomEventProto.initCustomEvent = function initCustomEvent(type, bubbles =
|
|
|
562
565
|
throw new TypeError('Illegal invocation');
|
|
563
566
|
}
|
|
564
567
|
const _evCfg = getEvCfg(this);
|
|
568
|
+
if (_evCfg._dispatched) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
565
572
|
// @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
|
|
566
573
|
// eslint-disable-next-line prefer-rest-params -- Keep signature
|
|
567
574
|
initEventInternal(this, type, {
|
|
@@ -569,16 +576,13 @@ ShimCustomEventProto.initCustomEvent = function initCustomEvent(type, bubbles =
|
|
|
569
576
|
cancelable,
|
|
570
577
|
detail
|
|
571
578
|
}, arguments[4]);
|
|
572
|
-
if (_evCfg._dispatched) {
|
|
573
|
-
return;
|
|
574
|
-
}
|
|
575
579
|
if (detail !== undefined) {
|
|
576
580
|
_evCfg.detail = detail;
|
|
577
581
|
}
|
|
578
582
|
// `initCustomEvent` deliberately excluded -- see the matching comment
|
|
579
583
|
// in `initEventInternal` for `initEvent`, above; the same reasoning
|
|
580
584
|
// applies here.
|
|
581
|
-
definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
|
|
585
|
+
definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
|
|
582
586
|
};
|
|
583
587
|
// @ts-expect-error Not part of the class body itself
|
|
584
588
|
ShimCustomEvent[Symbol.toStringTag] = 'Function';
|
|
@@ -998,7 +1002,7 @@ Object.assign(EventTarget.prototype, {
|
|
|
998
1002
|
/** @type {string[]} */
|
|
999
1003
|
this._extraProperties.forEach(prop => {
|
|
1000
1004
|
if (Reflect.has(e, prop)) {
|
|
1001
|
-
/** @type {
|
|
1005
|
+
/** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
|
|
1002
1006
|
}
|
|
1003
1007
|
});
|
|
1004
1008
|
}
|
|
@@ -1078,6 +1082,7 @@ Object.assign(EventTarget.prototype, {
|
|
|
1078
1082
|
if (child) {
|
|
1079
1083
|
child._defaultSync = this._defaultSync;
|
|
1080
1084
|
}
|
|
1085
|
+
/* 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 */
|
|
1081
1086
|
return (child || this)._dispatchEvent(eventCopy, false);
|
|
1082
1087
|
}
|
|
1083
1088
|
case phases.AT_TARGET:
|
|
@@ -1380,7 +1385,7 @@ EventTarget.EventTargetFactory = EventTargetFactory;
|
|
|
1380
1385
|
* databaseNameLengthLimit: number|false,
|
|
1381
1386
|
* escapeNFDForDatabaseNames: boolean,
|
|
1382
1387
|
* addSQLiteExtension: boolean,
|
|
1383
|
-
* memoryDatabase: string,
|
|
1388
|
+
* memoryDatabase: string|null|undefined,
|
|
1384
1389
|
* deleteDatabaseFiles: boolean,
|
|
1385
1390
|
* databaseBasePath: string,
|
|
1386
1391
|
* sysDatabaseBasePath: string,
|
|
@@ -1523,13 +1528,27 @@ const CFG = /** @type {ConfigValues} */{};
|
|
|
1523
1528
|
// Various types of in-memory databases that can auto-delete
|
|
1524
1529
|
['memoryDatabase',
|
|
1525
1530
|
/**
|
|
1526
|
-
*
|
|
1531
|
+
* `null`/`undefined` are accepted (and left unvalidated against the
|
|
1532
|
+
* regex below) specifically so this can be reset back to its
|
|
1533
|
+
* unset/disabled state after being set: unlike other `CFG`
|
|
1534
|
+
* boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
|
|
1535
|
+
* with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
|
|
1536
|
+
* usage sites check `typeof CFG.memoryDatabase === 'string'`, so
|
|
1537
|
+
* even the empty string counts as "on" (it's a distinct, valid
|
|
1538
|
+
* in-memory mode of its own -- an unnamed private temporary
|
|
1539
|
+
* database -- not an "off" state). Without this, once set to any
|
|
1540
|
+
* string there would be no value passable back through this same
|
|
1541
|
+
* validator that turns `useMemoryDatabase` false again.
|
|
1542
|
+
* @param {string|null|undefined} val
|
|
1527
1543
|
* @throws {TypeError}
|
|
1528
1544
|
* @returns {void}
|
|
1529
1545
|
*/
|
|
1530
1546
|
val => {
|
|
1547
|
+
if (val === null || val === undefined) {
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1531
1550
|
if (!/^(?::memory:|file::memory:(\?[^#]*)?(#.*)?)?$/u.test(/** @type {string} */val)) {
|
|
1532
|
-
throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a
|
|
1551
|
+
throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
|
|
1533
1552
|
}
|
|
1534
1553
|
}],
|
|
1535
1554
|
// NODE-SPECIFIC CONFIG
|
|
@@ -1582,10 +1601,7 @@ function escapeUnmatchedSurrogates(arg) {
|
|
|
1582
1601
|
return arg.replaceAll(/([\uD800-\uDBFF])(?![\uDC00-\uDFFF])|(^|[^\uD800-\uDBFF])([\uDC00-\uDFFF])/gu, function (_, unmatchedHighSurrogate, precedingLow, unmatchedLowSurrogate) {
|
|
1583
1602
|
// Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
|
|
1584
1603
|
// but Chrome having problems
|
|
1585
|
-
|
|
1586
|
-
return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1587
|
-
}
|
|
1588
|
-
return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1604
|
+
return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1589
1605
|
});
|
|
1590
1606
|
}
|
|
1591
1607
|
|
|
@@ -2260,7 +2276,8 @@ Object.defineProperty(IDBVersionChangeEvent, Symbol.hasInstance, {
|
|
|
2260
2276
|
function createNativeDOMException(name, message) {
|
|
2261
2277
|
// @ts-expect-error It's ok
|
|
2262
2278
|
// eslint-disable-next-line new-cap -- Ok
|
|
2263
|
-
return new DOMException.prototype.constructor(message,
|
|
2279
|
+
return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
|
|
2280
|
+
name || 'DOMException');
|
|
2264
2281
|
}
|
|
2265
2282
|
|
|
2266
2283
|
// From web-platform-tests testharness.js name_code_map (though not in new spec)
|
|
@@ -2424,8 +2441,10 @@ function createNonNativeDOMExceptionClass() {
|
|
|
2424
2441
|
*/
|
|
2425
2442
|
get() {
|
|
2426
2443
|
if (!(this instanceof DOMException ||
|
|
2444
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2427
2445
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2428
2446
|
this instanceof DummyDOMException ||
|
|
2447
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2429
2448
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2430
2449
|
this instanceof Error)) {
|
|
2431
2450
|
throw new TypeError('Illegal invocation');
|
|
@@ -2484,6 +2503,7 @@ function createNonNativeDOMExceptionClass() {
|
|
|
2484
2503
|
value: DOMException
|
|
2485
2504
|
});
|
|
2486
2505
|
|
|
2506
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2487
2507
|
// @ts-ignore We don't need all its properties; needed under some TS versions
|
|
2488
2508
|
return DOMException;
|
|
2489
2509
|
}
|
|
@@ -2496,6 +2516,7 @@ const ShimNonNativeDOMException = createNonNativeDOMExceptionClass();
|
|
|
2496
2516
|
* @returns {Error}
|
|
2497
2517
|
*/
|
|
2498
2518
|
function createNonNativeDOMException(name, message) {
|
|
2519
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2499
2520
|
// @ts-ignore It's ok; needed under some TS versions
|
|
2500
2521
|
return new ShimNonNativeDOMException(message, name);
|
|
2501
2522
|
}
|
|
@@ -2518,6 +2539,8 @@ function logError(name, message, error) {
|
|
|
2518
2539
|
return;
|
|
2519
2540
|
}
|
|
2520
2541
|
const msg = error && typeof error === 'object' && error.message ? error.message : (/** @type {string} */error);
|
|
2542
|
+
|
|
2543
|
+
/* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
|
|
2521
2544
|
const method = typeof console.error === 'function' ? 'error' : 'log';
|
|
2522
2545
|
console[method](name + ': ' + message + '. ' + (msg || ''));
|
|
2523
2546
|
if (console.trace) {
|
|
@@ -2693,8 +2716,10 @@ function IDBRequest() {
|
|
|
2693
2716
|
* @this {IDBRequestFull}
|
|
2694
2717
|
*/
|
|
2695
2718
|
IDBRequest.__super = function IDBRequest() {
|
|
2719
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2696
2720
|
// @ts-ignore It's ok
|
|
2697
2721
|
this[Symbol.toStringTag] = 'IDBRequest';
|
|
2722
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2698
2723
|
// @ts-ignore Part of `ShimEventTarget`
|
|
2699
2724
|
this.__setOptions({
|
|
2700
2725
|
legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
|
|
@@ -2755,10 +2780,7 @@ IDBRequest.prototype[Symbol.toStringTag] = 'IDBRequestPrototype';
|
|
|
2755
2780
|
* @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
|
|
2756
2781
|
*/
|
|
2757
2782
|
IDBRequest.prototype.__getParent = function () {
|
|
2758
|
-
|
|
2759
|
-
return null;
|
|
2760
|
-
}
|
|
2761
|
-
return this.__transaction;
|
|
2783
|
+
return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
|
|
2762
2784
|
};
|
|
2763
2785
|
|
|
2764
2786
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
@@ -2817,8 +2839,10 @@ IDBOpenDBRequest.__createInstance = function () {
|
|
|
2817
2839
|
function IDBOpenDBRequest() {
|
|
2818
2840
|
IDBRequest.__super.call(this);
|
|
2819
2841
|
|
|
2842
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2820
2843
|
// @ts-ignore It's ok
|
|
2821
2844
|
this[Symbol.toStringTag] = 'IDBOpenDBRequest';
|
|
2845
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2822
2846
|
// @ts-ignore It's ok
|
|
2823
2847
|
this.__setOptions({
|
|
2824
2848
|
legacyOutputDidListenersThrowFlag: true,
|
|
@@ -3781,7 +3805,13 @@ function convertValueToKeyValueDecoded(input, seen, multiEntry, fullKeys) {
|
|
|
3781
3805
|
message: 'Bad array entry value-to-key conversion'
|
|
3782
3806
|
};
|
|
3783
3807
|
}
|
|
3784
|
-
if (!multiEntry || !fullKeys && keys.every(k => cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0) ||
|
|
3808
|
+
if (!multiEntry || !fullKeys && keys.every(k => cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0) ||
|
|
3809
|
+
// `keys` holds full `{type, value}` objects here (see
|
|
3810
|
+
// `safePush` below), so -- like the sibling branch
|
|
3811
|
+
// above -- `cmp` (which expects raw `Value`s, not
|
|
3812
|
+
// decoded key objects) must compare their `.value`s,
|
|
3813
|
+
// not the wrapper objects themselves.
|
|
3814
|
+
fullKeys && keys.every(k => cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0)) {
|
|
3785
3815
|
safePush(keys, fullKeys ? key : key.value);
|
|
3786
3816
|
}
|
|
3787
3817
|
} catch (err) {
|
|
@@ -3799,12 +3829,9 @@ function convertValueToKeyValueDecoded(input, seen, multiEntry, fullKeys) {
|
|
|
3799
3829
|
{
|
|
3800
3830
|
const date = /** @type {Date} */input;
|
|
3801
3831
|
if (!Number.isNaN(date.getTime())) {
|
|
3802
|
-
return
|
|
3803
|
-
type,
|
|
3804
|
-
value: date.getTime()
|
|
3805
|
-
} : {
|
|
3832
|
+
return {
|
|
3806
3833
|
type,
|
|
3807
|
-
value: new Date(date)
|
|
3834
|
+
value: fullKeys ? date.getTime() : new Date(date)
|
|
3808
3835
|
};
|
|
3809
3836
|
}
|
|
3810
3837
|
return {
|
|
@@ -3892,10 +3919,7 @@ function extractKeyValueDecodedFromValueUsingKeyPath(value, keyPath, multiEntry,
|
|
|
3892
3919
|
if (r.failure) {
|
|
3893
3920
|
return r;
|
|
3894
3921
|
}
|
|
3895
|
-
|
|
3896
|
-
return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
|
|
3897
|
-
}
|
|
3898
|
-
return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
3922
|
+
return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
3899
3923
|
}
|
|
3900
3924
|
|
|
3901
3925
|
/**
|
|
@@ -4067,10 +4091,7 @@ function isKeyInRange(key, range, checkCached) {
|
|
|
4067
4091
|
*/
|
|
4068
4092
|
function isMultiEntryMatch(encodedEntry, encodedKey) {
|
|
4069
4093
|
const keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
|
|
4070
|
-
|
|
4071
|
-
return encodedKey.indexOf(encodedEntry) > 1;
|
|
4072
|
-
}
|
|
4073
|
-
return encodedKey === encodedEntry;
|
|
4094
|
+
return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
|
|
4074
4095
|
}
|
|
4075
4096
|
|
|
4076
4097
|
/**
|
|
@@ -4181,10 +4202,7 @@ function encode$1(key, inArray) {
|
|
|
4181
4202
|
* @returns {undefined|ValueType}
|
|
4182
4203
|
*/
|
|
4183
4204
|
function decode$1(key, inArray) {
|
|
4184
|
-
|
|
4185
|
-
return undefined;
|
|
4186
|
-
}
|
|
4187
|
-
return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4205
|
+
return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4188
4206
|
}
|
|
4189
4207
|
|
|
4190
4208
|
/**
|
|
@@ -4596,10 +4614,11 @@ function setSQLForKeyRange(range, quotedKeyColumnName, sql, sqlValues, addAnd, c
|
|
|
4596
4614
|
if (hasLower && hasUpper) {
|
|
4597
4615
|
sql.push('AND');
|
|
4598
4616
|
}
|
|
4599
|
-
if (hasUpper) {
|
|
4600
|
-
|
|
4601
|
-
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
4617
|
+
if (!hasUpper) {
|
|
4618
|
+
return;
|
|
4602
4619
|
}
|
|
4620
|
+
sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
|
|
4621
|
+
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
4603
4622
|
}
|
|
4604
4623
|
|
|
4605
4624
|
/**
|
|
@@ -4612,10 +4631,7 @@ function convertValueToKeyRange(value, nullDisallowed) {
|
|
|
4612
4631
|
if (instanceOf(value, IDBKeyRange)) {
|
|
4613
4632
|
// We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
|
|
4614
4633
|
const range = /** @type {IDBKeyRangeFull} */value;
|
|
4615
|
-
|
|
4616
|
-
return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
|
|
4617
|
-
}
|
|
4618
|
-
return range;
|
|
4634
|
+
return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
|
|
4619
4635
|
}
|
|
4620
4636
|
if (isNullish(value)) {
|
|
4621
4637
|
if (nullDisallowed) {
|
|
@@ -4660,9 +4676,11 @@ if (Object.defineProperty) {
|
|
|
4660
4676
|
if (testObject.test) {
|
|
4661
4677
|
cleanInterface = true;
|
|
4662
4678
|
}
|
|
4679
|
+
/* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
4663
4680
|
} catch (err) {
|
|
4664
4681
|
// Object.defineProperty does not work as intended.
|
|
4665
4682
|
}
|
|
4683
|
+
/* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
4666
4684
|
}
|
|
4667
4685
|
|
|
4668
4686
|
/**
|
|
@@ -4860,6 +4878,7 @@ Object.defineProperty(DOMStringList, '__createInstance', {
|
|
|
4860
4878
|
this._length = 0;
|
|
4861
4879
|
};
|
|
4862
4880
|
DOMStringList.prototype = DOMStringListAlias.prototype;
|
|
4881
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
4863
4882
|
// @ts-ignore It's ok; needed under some TS versions
|
|
4864
4883
|
return /** @type {DOMStringListFull} */new DOMStringList();
|
|
4865
4884
|
}
|
|
@@ -5157,12 +5176,14 @@ IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
|
|
|
5157
5176
|
*/
|
|
5158
5177
|
IDBTransaction.prototype.__executeRequests = function () {
|
|
5159
5178
|
const me = this;
|
|
5179
|
+
/* 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. */
|
|
5160
5180
|
if (me.__running) {
|
|
5161
5181
|
if (CFG.DEBUG) {
|
|
5162
5182
|
console.log('Looks like the request set is already running', me.mode);
|
|
5163
5183
|
}
|
|
5164
5184
|
return;
|
|
5165
5185
|
}
|
|
5186
|
+
/* c8 ignore stop -- see comment above */
|
|
5166
5187
|
|
|
5167
5188
|
// The synchronous script that created this transaction (and
|
|
5168
5189
|
// synchronously queued whatever requests it wanted to) has now
|
|
@@ -5212,6 +5233,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5212
5233
|
queueMicrotask(cb);
|
|
5213
5234
|
return;
|
|
5214
5235
|
}
|
|
5236
|
+
/* 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. */
|
|
5215
5237
|
try {
|
|
5216
5238
|
tx.executeSql('SELECT 1', [], function () {
|
|
5217
5239
|
cb();
|
|
@@ -5225,6 +5247,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5225
5247
|
// abort the transaction here.
|
|
5226
5248
|
me.__abortTransaction(/** @type {Error|DOMException} */err);
|
|
5227
5249
|
}
|
|
5250
|
+
/* c8 ignore stop -- see comment above */
|
|
5228
5251
|
}
|
|
5229
5252
|
|
|
5230
5253
|
/**
|
|
@@ -5237,21 +5260,26 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5237
5260
|
* @returns {void}
|
|
5238
5261
|
*/
|
|
5239
5262
|
function success(result, req) {
|
|
5263
|
+
/* 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. */
|
|
5240
5264
|
if (me.__errored || me.__requestsFinished) {
|
|
5241
5265
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5242
5266
|
return;
|
|
5243
5267
|
}
|
|
5268
|
+
/* c8 ignore stop -- see comment above */
|
|
5244
5269
|
if (req) {
|
|
5245
5270
|
q.req = req; // Need to do this in case of cursors
|
|
5246
5271
|
}
|
|
5272
|
+
/* 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. */
|
|
5247
5273
|
if (!q.req) {
|
|
5248
|
-
// TS guard
|
|
5249
5274
|
return;
|
|
5250
5275
|
}
|
|
5276
|
+
/* c8 ignore stop -- see comment above */
|
|
5277
|
+
/* 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. */
|
|
5251
5278
|
if (q.req.__done) {
|
|
5252
5279
|
// Avoid continuing with aborted requests
|
|
5253
5280
|
return;
|
|
5254
5281
|
}
|
|
5282
|
+
/* c8 ignore stop -- see comment above */
|
|
5255
5283
|
q.req.__done = true;
|
|
5256
5284
|
q.req.__result = result;
|
|
5257
5285
|
q.req.__error = null;
|
|
@@ -5268,6 +5296,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5268
5296
|
// is what actually resets `__handlerActive`, once it's
|
|
5269
5297
|
// confirmed (across its own bounded microtask wait) that no
|
|
5270
5298
|
// such continuation queued anything.
|
|
5299
|
+
/* 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. */
|
|
5271
5300
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
5272
5301
|
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
|
|
5273
5302
|
if (!me.__committed) {
|
|
@@ -5277,6 +5306,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5277
5306
|
return;
|
|
5278
5307
|
}
|
|
5279
5308
|
}
|
|
5309
|
+
/* c8 ignore stop -- see comment above */
|
|
5280
5310
|
runContinuationSafely(advanceAfterDispatch);
|
|
5281
5311
|
}
|
|
5282
5312
|
|
|
@@ -5288,15 +5318,19 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5288
5318
|
* @returns {void}
|
|
5289
5319
|
*/
|
|
5290
5320
|
function error(...args /* tx, err */) {
|
|
5321
|
+
/* 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. */
|
|
5291
5322
|
if (me.__errored || me.__requestsFinished) {
|
|
5292
5323
|
// We've already called "onerror", "onabort", or thrown within
|
|
5293
5324
|
// the transaction, so don't do it again.
|
|
5294
5325
|
return;
|
|
5295
5326
|
}
|
|
5327
|
+
/* c8 ignore stop -- see comment above */
|
|
5328
|
+
/* 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. */
|
|
5296
5329
|
if (q.req && q.req.__done) {
|
|
5297
5330
|
// Avoid continuing with aborted requests
|
|
5298
5331
|
return;
|
|
5299
5332
|
}
|
|
5333
|
+
/* c8 ignore stop -- see comment above */
|
|
5300
5334
|
const err = /** @type {Error|DOMException} */findError(args);
|
|
5301
5335
|
if (!q.req) {
|
|
5302
5336
|
me.__abortTransaction(err);
|
|
@@ -5318,10 +5352,11 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5318
5352
|
}
|
|
5319
5353
|
});
|
|
5320
5354
|
q.req.addDefaultEventListener('error', function () {
|
|
5355
|
+
/* 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. */
|
|
5321
5356
|
if (!q.req) {
|
|
5322
|
-
// TS guard
|
|
5323
5357
|
return;
|
|
5324
5358
|
}
|
|
5359
|
+
/* c8 ignore stop -- see comment above */
|
|
5325
5360
|
me.__abortTransaction(q.req.__error);
|
|
5326
5361
|
});
|
|
5327
5362
|
me.__active = true;
|
|
@@ -5333,16 +5368,19 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5333
5368
|
q.req.dispatchEvent(e);
|
|
5334
5369
|
// Do not set __active or __handlerActive flags to false yet --
|
|
5335
5370
|
// see the matching comment in `success`, above.
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
if (me.__committed) {
|
|
5340
|
-
// An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
|
|
5341
|
-
runContinuationSafely(advanceAfterDispatch);
|
|
5342
|
-
return;
|
|
5343
|
-
}
|
|
5344
|
-
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
|
|
5371
|
+
/* 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. */
|
|
5372
|
+
if (!e.__legacyOutputDidListenersThrowError) {
|
|
5373
|
+
return;
|
|
5345
5374
|
}
|
|
5375
|
+
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
|
|
5376
|
+
e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
|
|
5377
|
+
if (me.__committed) {
|
|
5378
|
+
// An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
|
|
5379
|
+
runContinuationSafely(advanceAfterDispatch);
|
|
5380
|
+
return;
|
|
5381
|
+
}
|
|
5382
|
+
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
|
|
5383
|
+
/* c8 ignore stop -- see comment above */
|
|
5346
5384
|
}
|
|
5347
5385
|
|
|
5348
5386
|
/**
|
|
@@ -5366,10 +5404,12 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5366
5404
|
// (not reset here).
|
|
5367
5405
|
return true;
|
|
5368
5406
|
}
|
|
5407
|
+
/* 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. */
|
|
5369
5408
|
if (q.req.__done) {
|
|
5370
5409
|
// Avoid continuing with aborted requests
|
|
5371
5410
|
return false;
|
|
5372
5411
|
}
|
|
5412
|
+
/* c8 ignore stop -- see comment above */
|
|
5373
5413
|
// We're now handing off to (possibly async) work for
|
|
5374
5414
|
// this request, so the transaction is no longer active
|
|
5375
5415
|
// until its own `success`/`error` dispatch (below)
|
|
@@ -5392,18 +5432,22 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5392
5432
|
return;
|
|
5393
5433
|
}
|
|
5394
5434
|
q.op(tx, q.args, success, error, executeNextRequest);
|
|
5435
|
+
/* 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. */
|
|
5395
5436
|
} catch (e) {
|
|
5396
5437
|
error(/** @type {Error} */e);
|
|
5397
5438
|
}
|
|
5439
|
+
/* c8 ignore stop -- see comment above */
|
|
5398
5440
|
}
|
|
5399
5441
|
|
|
5400
5442
|
/**
|
|
5401
5443
|
* @returns {void}
|
|
5402
5444
|
*/
|
|
5403
5445
|
function runQueuedRequest() {
|
|
5446
|
+
/* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
|
|
5404
5447
|
if (!prepareNextRequest()) {
|
|
5405
5448
|
return;
|
|
5406
5449
|
}
|
|
5450
|
+
/* c8 ignore stop -- see comment above */
|
|
5407
5451
|
launchQueuedOp();
|
|
5408
5452
|
}
|
|
5409
5453
|
|
|
@@ -5434,9 +5478,11 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5434
5478
|
* @returns {void}
|
|
5435
5479
|
*/
|
|
5436
5480
|
function checkQueueEntry(attemptsLeft) {
|
|
5481
|
+
/* 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. */
|
|
5437
5482
|
if (me.__errored || me.__requestsFinished) {
|
|
5438
5483
|
return;
|
|
5439
5484
|
}
|
|
5485
|
+
/* c8 ignore stop -- see comment above */
|
|
5440
5486
|
if (i < me.__requests.length) {
|
|
5441
5487
|
runQueuedRequest();
|
|
5442
5488
|
return;
|
|
@@ -5458,10 +5504,12 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5458
5504
|
* @returns {void}
|
|
5459
5505
|
*/
|
|
5460
5506
|
function executeNextRequest() {
|
|
5507
|
+
/* 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. */
|
|
5461
5508
|
if (me.__errored || me.__requestsFinished) {
|
|
5462
5509
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5463
5510
|
return;
|
|
5464
5511
|
}
|
|
5512
|
+
/* c8 ignore stop -- see comment above */
|
|
5465
5513
|
i++;
|
|
5466
5514
|
if (i >= me.__requests.length) {
|
|
5467
5515
|
checkQueueEntry(keepAliveAttempts);
|
|
@@ -5496,31 +5544,34 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5496
5544
|
* @returns {void}
|
|
5497
5545
|
*/
|
|
5498
5546
|
function advanceAfterDispatch() {
|
|
5547
|
+
/* 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. */
|
|
5499
5548
|
if (me.__errored || me.__requestsFinished) {
|
|
5500
5549
|
return;
|
|
5501
5550
|
}
|
|
5551
|
+
/* c8 ignore stop -- see comment above */
|
|
5502
5552
|
i++;
|
|
5503
5553
|
if (i >= me.__requests.length) {
|
|
5504
5554
|
checkQueueEntry(keepAliveAttempts);
|
|
5505
5555
|
return;
|
|
5506
5556
|
}
|
|
5507
5557
|
keepAliveAndWait(() => {
|
|
5508
|
-
if (
|
|
5509
|
-
|
|
5510
|
-
}
|
|
5511
|
-
if (!prepareNextRequest()) {
|
|
5558
|
+
/* 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. */
|
|
5559
|
+
if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
|
|
5512
5560
|
return;
|
|
5513
5561
|
}
|
|
5562
|
+
/* c8 ignore stop -- see comment above */
|
|
5514
5563
|
launchQueuedOp();
|
|
5515
5564
|
});
|
|
5516
5565
|
}
|
|
5517
5566
|
executeNextRequest();
|
|
5518
5567
|
}, function webSQLError(webSQLErr) {
|
|
5568
|
+
/* 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. */
|
|
5519
5569
|
// @ts-expect-error It's ok
|
|
5520
5570
|
if (webSQLErr === true) {
|
|
5521
5571
|
// Not a genuine SQL error
|
|
5522
5572
|
return;
|
|
5523
5573
|
}
|
|
5574
|
+
/* c8 ignore stop -- see comment above */
|
|
5524
5575
|
const err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
|
|
5525
5576
|
me.__abortTransaction(err);
|
|
5526
5577
|
}, function () {
|
|
@@ -5531,18 +5582,25 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5531
5582
|
// Node
|
|
5532
5583
|
return;
|
|
5533
5584
|
}
|
|
5585
|
+
/* 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. */
|
|
5534
5586
|
if (!me.__transactionEndCallback && !me.__requestsFinished) {
|
|
5535
5587
|
me.__transactionFinished = true;
|
|
5536
5588
|
return;
|
|
5537
5589
|
}
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5590
|
+
/* c8 ignore stop -- see comment above */
|
|
5591
|
+
/* 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. */
|
|
5592
|
+
if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
|
|
5593
|
+
return;
|
|
5541
5594
|
}
|
|
5595
|
+
me.__transFinishedCbFired = true;
|
|
5596
|
+
me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
|
|
5597
|
+
/* c8 ignore stop -- see comment above */
|
|
5542
5598
|
}, function (currentTask, err, done, rollback, commit) {
|
|
5599
|
+
/* 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. */
|
|
5543
5600
|
if (err) {
|
|
5544
5601
|
return true;
|
|
5545
5602
|
}
|
|
5603
|
+
/* c8 ignore stop -- see comment above */
|
|
5546
5604
|
// `readonly` transactions never hold a real SQL transaction open
|
|
5547
5605
|
// (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
|
|
5548
5606
|
// them), so there's no commit/rollback round trip to defer --
|
|
@@ -5591,6 +5649,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5591
5649
|
*/
|
|
5592
5650
|
function complete() {
|
|
5593
5651
|
me.__completed = true;
|
|
5652
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
5594
5653
|
if (CFG.DEBUG) {
|
|
5595
5654
|
console.log('Transaction completed');
|
|
5596
5655
|
}
|
|
@@ -5600,6 +5659,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5600
5659
|
me.dispatchEvent(evt);
|
|
5601
5660
|
me.__internal = false;
|
|
5602
5661
|
me.dispatchEvent(createEvent('__complete'));
|
|
5662
|
+
/* 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. */
|
|
5603
5663
|
} catch (e) {
|
|
5604
5664
|
me.__internal = false;
|
|
5605
5665
|
// An error occurred in the "oncomplete" handler.
|
|
@@ -5607,6 +5667,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5607
5667
|
// (this may seem odd/bad, but it's how all native IndexedDB implementations work)
|
|
5608
5668
|
me.__errored = true;
|
|
5609
5669
|
throw e;
|
|
5670
|
+
/* c8 ignore stop -- see comment above */
|
|
5610
5671
|
} finally {
|
|
5611
5672
|
activeTransactions.delete(me);
|
|
5612
5673
|
me.__storeHandles = {};
|
|
@@ -5614,10 +5675,12 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5614
5675
|
}
|
|
5615
5676
|
}
|
|
5616
5677
|
if (me.mode === 'readwrite' || me.mode === 'readonly') {
|
|
5678
|
+
/* 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. */
|
|
5617
5679
|
if (me.__transactionFinished) {
|
|
5618
5680
|
complete();
|
|
5619
5681
|
return;
|
|
5620
5682
|
}
|
|
5683
|
+
/* c8 ignore stop -- see comment above */
|
|
5621
5684
|
me.__transactionEndCallback = complete;
|
|
5622
5685
|
// The underlying SQL driver's own "queue empty" check
|
|
5623
5686
|
// (`nonstandardTransCb`, above) typically already ran and
|
|
@@ -5653,6 +5716,7 @@ IDBTransaction.prototype.__executeRequests = function () {
|
|
|
5653
5716
|
IDBTransaction.prototype.__createRequest = function (source) {
|
|
5654
5717
|
const me = this;
|
|
5655
5718
|
const request = IDBRequest.__createInstance();
|
|
5719
|
+
/* 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. */
|
|
5656
5720
|
request.__source = source !== undefined ? source : me.db;
|
|
5657
5721
|
request.__transaction = me;
|
|
5658
5722
|
return request;
|
|
@@ -5722,9 +5786,11 @@ IDBTransaction.prototype.__pushToQueue = function (request, callback, args) {
|
|
|
5722
5786
|
* @returns {void}
|
|
5723
5787
|
*/
|
|
5724
5788
|
IDBTransaction.prototype.__assertActive = function () {
|
|
5789
|
+
/* 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. */
|
|
5725
5790
|
if (!this.__active || !this.__handlerActive || this.__committed) {
|
|
5726
5791
|
throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
|
|
5727
5792
|
}
|
|
5793
|
+
/* c8 ignore stop -- see comment above */
|
|
5728
5794
|
};
|
|
5729
5795
|
|
|
5730
5796
|
/**
|
|
@@ -5738,6 +5804,7 @@ IDBTransaction.prototype.__assertWritable = function () {
|
|
|
5738
5804
|
}
|
|
5739
5805
|
};
|
|
5740
5806
|
|
|
5807
|
+
/* 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. */
|
|
5741
5808
|
/**
|
|
5742
5809
|
* @this {IDBTransactionFull}
|
|
5743
5810
|
* @returns {void}
|
|
@@ -5745,6 +5812,7 @@ IDBTransaction.prototype.__assertWritable = function () {
|
|
|
5745
5812
|
IDBTransaction.prototype.__assertVersionChange = function () {
|
|
5746
5813
|
IDBTransaction.__assertVersionChange(this);
|
|
5747
5814
|
};
|
|
5815
|
+
/* c8 ignore stop -- see comment above */
|
|
5748
5816
|
|
|
5749
5817
|
/**
|
|
5750
5818
|
* Returns the specified object store.
|
|
@@ -5766,9 +5834,12 @@ IDBTransaction.prototype.objectStore = function (objectStoreName) {
|
|
|
5766
5834
|
throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
|
|
5767
5835
|
}
|
|
5768
5836
|
const store = me.db.__objectStores[objectStoreName];
|
|
5837
|
+
/* 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. */
|
|
5769
5838
|
if (!store) {
|
|
5770
5839
|
throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
|
|
5771
5840
|
}
|
|
5841
|
+
/* c8 ignore stop -- see comment above */
|
|
5842
|
+
|
|
5772
5843
|
if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
|
|
5773
5844
|
// These latter conditions are to allow store
|
|
5774
5845
|
// recreation to create new clone object
|
|
@@ -5787,10 +5858,12 @@ IDBTransaction.prototype.objectStore = function (objectStoreName) {
|
|
|
5787
5858
|
IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
5788
5859
|
const me = this;
|
|
5789
5860
|
logError('Error', 'An error occurred in a transaction', err);
|
|
5861
|
+
/* 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. */
|
|
5790
5862
|
if (me.__errored) {
|
|
5791
5863
|
// We've already called "onerror", "onabort", or thrown, so don't do it again.
|
|
5792
5864
|
return;
|
|
5793
5865
|
}
|
|
5866
|
+
/* c8 ignore stop -- see comment above */
|
|
5794
5867
|
me.__errored = true;
|
|
5795
5868
|
if (me.mode === 'versionchange') {
|
|
5796
5869
|
// Steps for aborting an upgrade transaction
|
|
@@ -5820,19 +5893,16 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5820
5893
|
if (err !== null) {
|
|
5821
5894
|
me.__error = err;
|
|
5822
5895
|
}
|
|
5896
|
+
|
|
5897
|
+
/* 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. */
|
|
5823
5898
|
if (me.__requestsFinished && err !== null) {
|
|
5824
5899
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
5825
|
-
// So throw the error instead.
|
|
5826
|
-
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
5827
|
-
// call, which now checks `__requestsFinished` itself first and
|
|
5828
|
-
// throws `InvalidStateError` synchronously before ever reaching
|
|
5829
|
-
// this point -- so this guard is just defense in depth against
|
|
5830
|
-
// `err` somehow being `null` some other way, not something this
|
|
5831
|
-
// path should see in practice.
|
|
5900
|
+
// So throw the error instead.
|
|
5832
5901
|
setTimeout(() => {
|
|
5833
5902
|
throw err;
|
|
5834
5903
|
}, 0);
|
|
5835
5904
|
}
|
|
5905
|
+
/* c8 ignore stop -- see comment above */
|
|
5836
5906
|
|
|
5837
5907
|
/**
|
|
5838
5908
|
* @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
|
|
@@ -5841,13 +5911,17 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5841
5911
|
*/
|
|
5842
5912
|
function abort(tx, errOrResult) {
|
|
5843
5913
|
if (!tx) {
|
|
5914
|
+
/* 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. */
|
|
5844
5915
|
if (CFG.DEBUG) {
|
|
5845
5916
|
console.log('Rollback not possible due to missing transaction', me);
|
|
5846
5917
|
}
|
|
5918
|
+
/* 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. */
|
|
5847
5919
|
} else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
|
|
5848
5920
|
if (CFG.DEBUG) {
|
|
5849
5921
|
console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
|
|
5850
5922
|
}
|
|
5923
|
+
/* c8 ignore stop -- see comment above */
|
|
5924
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
5851
5925
|
} else if (CFG.DEBUG) {
|
|
5852
5926
|
console.log('Rollback succeeded', me);
|
|
5853
5927
|
}
|
|
@@ -5861,10 +5935,11 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5861
5935
|
// behaves first-in-first-out with the same timeout so we could
|
|
5862
5936
|
// just use a `forEach`.
|
|
5863
5937
|
return promises.then(function () {
|
|
5938
|
+
/* 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. */
|
|
5864
5939
|
if (!q.req) {
|
|
5865
|
-
// TS guard
|
|
5866
5940
|
throw new Error('Missing request');
|
|
5867
5941
|
}
|
|
5942
|
+
/* c8 ignore stop -- see comment above */
|
|
5868
5943
|
q.req.__done = true;
|
|
5869
5944
|
q.req.__result = undefined;
|
|
5870
5945
|
q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
|
|
@@ -5875,10 +5950,11 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5875
5950
|
return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
|
|
5876
5951
|
resolve => {
|
|
5877
5952
|
setTimeout(() => {
|
|
5953
|
+
/* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
|
|
5878
5954
|
if (!q.req) {
|
|
5879
|
-
// TS guard
|
|
5880
5955
|
throw new Error('Missing request');
|
|
5881
5956
|
}
|
|
5957
|
+
/* c8 ignore stop -- see comment above */
|
|
5882
5958
|
q.req.dispatchEvent(reqEvt); // No need to catch errors
|
|
5883
5959
|
resolve();
|
|
5884
5960
|
}, 0);
|
|
@@ -5898,10 +5974,12 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5898
5974
|
releaseFinishedTransaction(me);
|
|
5899
5975
|
}, 0);
|
|
5900
5976
|
return undefined;
|
|
5977
|
+
/* 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. */
|
|
5901
5978
|
}).catch(err => {
|
|
5902
5979
|
console.log('Abort error');
|
|
5903
5980
|
throw err;
|
|
5904
5981
|
});
|
|
5982
|
+
/* c8 ignore stop -- see comment above */
|
|
5905
5983
|
}
|
|
5906
5984
|
me.__transFinishedCb(true, function (rollback) {
|
|
5907
5985
|
if (rollback && me.__tx) {
|
|
@@ -5909,20 +5987,24 @@ IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
|
5909
5987
|
// rollback automatically), but for Node.js, etc., we give chance for
|
|
5910
5988
|
// manual aborts which would otherwise not work.
|
|
5911
5989
|
if (me.mode === 'readwrite') {
|
|
5990
|
+
/* 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. */
|
|
5912
5991
|
if (me.__transactionFinished) {
|
|
5913
5992
|
abort();
|
|
5914
5993
|
return;
|
|
5915
5994
|
}
|
|
5995
|
+
/* c8 ignore stop -- see comment above */
|
|
5916
5996
|
me.__transactionEndCallback = abort;
|
|
5917
5997
|
return;
|
|
5918
5998
|
}
|
|
5919
5999
|
try {
|
|
5920
6000
|
me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
|
|
6001
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
|
|
5921
6002
|
} catch (err) {
|
|
5922
6003
|
// Browser errs when transaction has ended and since it most likely already erred here,
|
|
5923
6004
|
// we call to abort
|
|
5924
6005
|
abort();
|
|
5925
6006
|
}
|
|
6007
|
+
/* c8 ignore stop -- see comment above */
|
|
5926
6008
|
} else {
|
|
5927
6009
|
abort(null, {
|
|
5928
6010
|
code: 0
|
|
@@ -5940,6 +6022,7 @@ IDBTransaction.prototype.abort = function () {
|
|
|
5940
6022
|
if (!(me instanceof IDBTransaction)) {
|
|
5941
6023
|
throw new TypeError('Illegal invocation');
|
|
5942
6024
|
}
|
|
6025
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
5943
6026
|
if (CFG.DEBUG) {
|
|
5944
6027
|
console.log('The transaction was aborted', me);
|
|
5945
6028
|
}
|
|
@@ -5971,6 +6054,7 @@ IDBTransaction.prototype.commit = function () {
|
|
|
5971
6054
|
if (!me.__active || !me.__handlerActive || me.__committed) {
|
|
5972
6055
|
throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
|
|
5973
6056
|
}
|
|
6057
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
5974
6058
|
if (CFG.DEBUG) {
|
|
5975
6059
|
console.log('The transaction was explicitly committed', me);
|
|
5976
6060
|
}
|
|
@@ -6013,6 +6097,7 @@ IDBTransaction.__assertNotFinished = function (tx) {
|
|
|
6013
6097
|
};
|
|
6014
6098
|
|
|
6015
6099
|
// object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
|
|
6100
|
+
/* 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. */
|
|
6016
6101
|
/**
|
|
6017
6102
|
*
|
|
6018
6103
|
* @param {IDBTransactionFull} tx
|
|
@@ -6028,6 +6113,7 @@ IDBTransaction.__assertNotFinishedObjectStoreMethod = function (tx) {
|
|
|
6028
6113
|
throw err;
|
|
6029
6114
|
}
|
|
6030
6115
|
};
|
|
6116
|
+
/* c8 ignore stop -- see comment above */
|
|
6031
6117
|
|
|
6032
6118
|
/**
|
|
6033
6119
|
*
|
|
@@ -6952,7 +7038,7 @@ const w = {
|
|
|
6952
7038
|
const t = e.getTime();
|
|
6953
7039
|
return Number.isNaN(t) ? "NaN" : t;
|
|
6954
7040
|
},
|
|
6955
|
-
revive: e => "NaN" === e ?
|
|
7041
|
+
revive: e => new Date("NaN" === e ? NaN : e)
|
|
6956
7042
|
}
|
|
6957
7043
|
},
|
|
6958
7044
|
T = {
|
|
@@ -7640,9 +7726,12 @@ const pe = ye.concat({
|
|
|
7640
7726
|
// we need to override it so it works with our tests
|
|
7641
7727
|
|
|
7642
7728
|
const specSet = fe.flatMap(preset => Array.isArray(preset) ? preset : [preset]).find(preset => preset && !Array.isArray(preset) && 'filelist' in preset);
|
|
7643
|
-
const origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
7644
|
-
|
|
7645
|
-
const
|
|
7729
|
+
const origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
7730
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
7731
|
+
const origTest = origFileList && typeof origFileList === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
|
|
7732
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
|
|
7733
|
+
const origRevive = origFileList && typeof origFileList === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
|
|
7734
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
|
|
7646
7735
|
const customFileList = origFileList ? {
|
|
7647
7736
|
...origFileList,
|
|
7648
7737
|
/**
|
|
@@ -7651,10 +7740,7 @@ const customFileList = origFileList ? {
|
|
|
7651
7740
|
* @returns {boolean}
|
|
7652
7741
|
*/
|
|
7653
7742
|
test(x, state) {
|
|
7654
|
-
|
|
7655
|
-
return x instanceof FileList;
|
|
7656
|
-
}
|
|
7657
|
-
return typeof origTest === 'function' ? origTest(x, state) : false;
|
|
7743
|
+
return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
|
|
7658
7744
|
},
|
|
7659
7745
|
/**
|
|
7660
7746
|
* @param {unknown} x
|
|
@@ -7665,10 +7751,13 @@ const customFileList = origFileList ? {
|
|
|
7665
7751
|
if (typeof FileList !== 'undefined') {
|
|
7666
7752
|
return Reflect.construct(FileList, [x]);
|
|
7667
7753
|
}
|
|
7754
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
|
|
7668
7755
|
return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
|
|
7669
7756
|
}
|
|
7670
|
-
}
|
|
7671
|
-
|
|
7757
|
+
}
|
|
7758
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
7759
|
+
let typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
|
|
7760
|
+
customFileList ? {
|
|
7672
7761
|
filelist: customFileList
|
|
7673
7762
|
} : {}]);
|
|
7674
7763
|
|
|
@@ -7824,7 +7913,6 @@ const IDBIndexAlias = IDBIndex;
|
|
|
7824
7913
|
* __unique: boolean,
|
|
7825
7914
|
* __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
7826
7915
|
* __keyPath: import('./Key.js').KeyPath,
|
|
7827
|
-
* __recreated?: boolean,
|
|
7828
7916
|
* __fetchIndexData: (
|
|
7829
7917
|
* range: Query,
|
|
7830
7918
|
* opType: "value"|"key"|"count",
|
|
@@ -7922,6 +8010,7 @@ IDBIndex.__createInstance = function (store, indexProperties) {
|
|
|
7922
8010
|
storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
|
|
7923
8011
|
me.__pendingName = oldName;
|
|
7924
8012
|
const colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
|
|
8013
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
7925
8014
|
// @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
|
|
7926
8015
|
[...objectStore.indexNames].filter(indexName => indexName !== newName).map(indexName => [escapeIndexNameForSQL(indexName), 'BLOB']));
|
|
7927
8016
|
me.__renameIndex(objectStore, oldName, newName, colInfoToPreserveArr, function (tx, success) {
|
|
@@ -7969,7 +8058,7 @@ IDBIndex.__clone = function (index, store) {
|
|
|
7969
8058
|
}
|
|
7970
8059
|
});
|
|
7971
8060
|
/** @type {const} */
|
|
7972
|
-
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'
|
|
8061
|
+
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(p => {
|
|
7973
8062
|
// @ts-expect-error Why is this type "never"?
|
|
7974
8063
|
idx[p] = index[p];
|
|
7975
8064
|
});
|
|
@@ -8003,11 +8092,12 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
8003
8092
|
} = store;
|
|
8004
8093
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8005
8094
|
transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
|
|
8006
|
-
const columnExists = idx &&
|
|
8095
|
+
const columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
|
|
8007
8096
|
|
|
8008
8097
|
/** @type {{[key: string]: boolean}} */
|
|
8009
8098
|
let indexValues = {};
|
|
8010
8099
|
|
|
8100
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8011
8101
|
/**
|
|
8012
8102
|
* @param {WebSQLTransaction} tx
|
|
8013
8103
|
* @param {(Error & {code?: number})} err
|
|
@@ -8016,6 +8106,7 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
8016
8106
|
function error(tx, err) {
|
|
8017
8107
|
failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
|
|
8018
8108
|
}
|
|
8109
|
+
/* c8 ignore stop -- see comment above */
|
|
8019
8110
|
|
|
8020
8111
|
/**
|
|
8021
8112
|
* @param {WebSQLTransaction} tx
|
|
@@ -8065,12 +8156,6 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
8065
8156
|
} else {
|
|
8066
8157
|
delete index.__pendingCreate;
|
|
8067
8158
|
delete indexHandle.__pendingCreate;
|
|
8068
|
-
if (index.__deleted) {
|
|
8069
|
-
delete index.__deleted;
|
|
8070
|
-
delete indexHandle.__deleted;
|
|
8071
|
-
index.__recreated = true;
|
|
8072
|
-
indexHandle.__recreated = true;
|
|
8073
|
-
}
|
|
8074
8159
|
indexValues = {};
|
|
8075
8160
|
success(store);
|
|
8076
8161
|
}
|
|
@@ -8079,7 +8164,7 @@ IDBIndex.__createIndex = function (store, index) {
|
|
|
8079
8164
|
}, /** @type {SqlErrorCallback} */error);
|
|
8080
8165
|
}
|
|
8081
8166
|
const escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
8082
|
-
const escapedIndexNameSQL = escapeIndexNameForSQL(
|
|
8167
|
+
const escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
|
|
8083
8168
|
|
|
8084
8169
|
/**
|
|
8085
8170
|
* @param {WebSQLTransaction} tx
|
|
@@ -8133,6 +8218,7 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
8133
8218
|
} = store;
|
|
8134
8219
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8135
8220
|
transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
|
|
8221
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8136
8222
|
/**
|
|
8137
8223
|
* @param {WebSQLTransaction} tx
|
|
8138
8224
|
* @param {(Error & {code?: number})} err
|
|
@@ -8141,6 +8227,7 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
8141
8227
|
function error(tx, err) {
|
|
8142
8228
|
failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
|
|
8143
8229
|
}
|
|
8230
|
+
/* c8 ignore stop -- see comment above */
|
|
8144
8231
|
|
|
8145
8232
|
/**
|
|
8146
8233
|
* @returns {void}
|
|
@@ -8149,7 +8236,6 @@ IDBIndex.__deleteIndex = function (store, index) {
|
|
|
8149
8236
|
// Update the object store's index list
|
|
8150
8237
|
IDBIndex.__updateIndexList(store, tx, function (store) {
|
|
8151
8238
|
delete index.__pendingDelete;
|
|
8152
|
-
delete index.__recreated;
|
|
8153
8239
|
index.__deleted = true;
|
|
8154
8240
|
if (indexHandle) {
|
|
8155
8241
|
indexHandle.__deleted = true;
|
|
@@ -8210,27 +8296,25 @@ IDBIndex.__updateIndexList = function (store, tx, success, failure) {
|
|
|
8210
8296
|
* @param {Query} range
|
|
8211
8297
|
* @param {"value"|"key"|"count"} opType
|
|
8212
8298
|
* @param {boolean} nullDisallowed
|
|
8213
|
-
* @param {number} [count]
|
|
8214
8299
|
* @this {IDBIndexFull}
|
|
8215
8300
|
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
8216
8301
|
*/
|
|
8217
|
-
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed
|
|
8302
|
+
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
|
|
8218
8303
|
const me = this;
|
|
8219
|
-
if (count !== undefined) {
|
|
8220
|
-
count = enforceRange(count, 'unsigned long');
|
|
8221
|
-
}
|
|
8222
8304
|
IDBIndex.__invalidStateIfDeleted(me);
|
|
8223
8305
|
IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
|
|
8306
|
+
/* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
|
|
8224
8307
|
if (me.objectStore.__deleted) {
|
|
8225
8308
|
throw createDOMException('InvalidStateError', "This index's object store has been deleted");
|
|
8226
8309
|
}
|
|
8310
|
+
/* c8 ignore stop -- see comment above */
|
|
8227
8311
|
IDBTransaction.__assertActive(me.objectStore.transaction);
|
|
8228
8312
|
if (nullDisallowed && isNullish(range)) {
|
|
8229
8313
|
throw createDOMException('DataError', 'No key or range was specified');
|
|
8230
8314
|
}
|
|
8231
8315
|
const fetchArgs = buildFetchIndexDataSQL(nullDisallowed, me, range, opType, false);
|
|
8232
8316
|
return /** @type {import('./IDBTransaction.js').IDBTransactionFull} */me.objectStore.transaction.__addToTransactionQueue(function (...args) {
|
|
8233
|
-
executeFetchIndexData(
|
|
8317
|
+
executeFetchIndexData(...fetchArgs,
|
|
8234
8318
|
// @ts-expect-error It's ok
|
|
8235
8319
|
...args);
|
|
8236
8320
|
}, undefined, me);
|
|
@@ -8384,13 +8468,16 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8384
8468
|
const escapedTmpStoreNameSQL = sqlQuote('tmp_' + escapeStoreNameForSQL(storeName).slice(1, -1));
|
|
8385
8469
|
const colNamesToPreserve = colInfoToPreserveArr.map(colInfo => colInfo[0]);
|
|
8386
8470
|
const colInfoToPreserve = colInfoToPreserveArr.map(colInfo => colInfo.join(' '));
|
|
8471
|
+
/* 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. */
|
|
8387
8472
|
const listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
|
|
8473
|
+
/* c8 ignore next -- Defensive: see comment above. */
|
|
8388
8474
|
const listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
|
|
8389
8475
|
|
|
8390
8476
|
// We could adapt the approach at https://stackoverflow.com/a/8430746/271577
|
|
8391
8477
|
// to make the approach reusable without passing column names, but it is a bit fragile
|
|
8392
8478
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8393
8479
|
store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
|
|
8480
|
+
/* 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. */
|
|
8394
8481
|
/**
|
|
8395
8482
|
* @param {WebSQLTransaction} tx
|
|
8396
8483
|
* @param {(Error & {code?: number})} err
|
|
@@ -8399,6 +8486,7 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8399
8486
|
function sqlError(tx, err) {
|
|
8400
8487
|
error(err);
|
|
8401
8488
|
}
|
|
8489
|
+
/* c8 ignore stop -- see comment above */
|
|
8402
8490
|
/**
|
|
8403
8491
|
* @returns {void}
|
|
8404
8492
|
*/
|
|
@@ -8407,8 +8495,14 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8407
8495
|
cb(tx, success);
|
|
8408
8496
|
return;
|
|
8409
8497
|
}
|
|
8498
|
+
/* 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. */
|
|
8410
8499
|
success();
|
|
8411
8500
|
}
|
|
8501
|
+
/* c8 ignore stop -- see comment above */
|
|
8502
|
+
if (!CFG.useSQLiteIndexes) {
|
|
8503
|
+
finish();
|
|
8504
|
+
return;
|
|
8505
|
+
}
|
|
8412
8506
|
// See https://www.sqlite.org/lang_altertable.html#otheralter
|
|
8413
8507
|
// We don't query for indexes as we already have the info
|
|
8414
8508
|
// This approach has the advantage of auto-deleting indexes via the DROP TABLE
|
|
@@ -8432,10 +8526,6 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8432
8526
|
console.log(sql);
|
|
8433
8527
|
}
|
|
8434
8528
|
tx.executeSql(sql, [], function (tx) {
|
|
8435
|
-
if (!CFG.useSQLiteIndexes) {
|
|
8436
|
-
finish();
|
|
8437
|
-
return;
|
|
8438
|
-
}
|
|
8439
8529
|
const indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
|
|
8440
8530
|
.map(escapedIndexNameSQL => new SyncPromise(function (resolve, reject) {
|
|
8441
8531
|
const escapedIndexToRecreate = sqlQuote(escapedStoreNameSQL.slice(1, -1) + '^5' + escapedIndexNameSQL.slice(1, -1));
|
|
@@ -8443,13 +8533,16 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8443
8533
|
// if (CFG.DEBUG) { console.log(sql); }
|
|
8444
8534
|
// tx.executeSql(sql, [], function () {
|
|
8445
8535
|
const sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
|
|
8536
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
8446
8537
|
if (CFG.DEBUG) {
|
|
8447
8538
|
console.log(sql);
|
|
8448
8539
|
}
|
|
8449
|
-
tx.executeSql(sql, [], resolve,
|
|
8540
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8541
|
+
/** @type {SqlErrorCallback} */
|
|
8450
8542
|
function (tx, err) {
|
|
8451
8543
|
reject(err);
|
|
8452
|
-
}
|
|
8544
|
+
}
|
|
8545
|
+
/* c8 ignore stop -- see comment above */);
|
|
8453
8546
|
// }, function (tx, err) {
|
|
8454
8547
|
// reject(err);
|
|
8455
8548
|
// });
|
|
@@ -8466,19 +8559,25 @@ IDBIndex.prototype.__renameIndex = function (store, oldName, newName, colInfoToP
|
|
|
8466
8559
|
if (CFG.DEBUG) {
|
|
8467
8560
|
console.log(sql);
|
|
8468
8561
|
}
|
|
8469
|
-
tx.executeSql(sql, [], resolve,
|
|
8562
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8563
|
+
/** @type {SqlErrorCallback} */
|
|
8470
8564
|
function (tx, err) {
|
|
8471
8565
|
reject(err);
|
|
8472
|
-
}
|
|
8473
|
-
|
|
8566
|
+
}
|
|
8567
|
+
/* c8 ignore stop -- see comment above */);
|
|
8568
|
+
}, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8569
|
+
/** @type {SqlErrorCallback} */
|
|
8474
8570
|
function (tx, err) {
|
|
8475
8571
|
reject(err);
|
|
8476
|
-
}
|
|
8572
|
+
}
|
|
8573
|
+
/* c8 ignore stop -- see comment above */);
|
|
8477
8574
|
}));
|
|
8478
8575
|
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
|
|
8479
8576
|
error).catch(err => {
|
|
8577
|
+
/* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
|
|
8480
8578
|
console.log('Index rename error');
|
|
8481
8579
|
throw err;
|
|
8580
|
+
/* c8 ignore stop -- see comment above */
|
|
8482
8581
|
});
|
|
8483
8582
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
8484
8583
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
@@ -8505,7 +8604,6 @@ Object.defineProperty(IDBIndex, 'prototype', {
|
|
|
8505
8604
|
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
8506
8605
|
|
|
8507
8606
|
/**
|
|
8508
|
-
* @param {number|null} count
|
|
8509
8607
|
* @param {boolean} unboundedDisallowed
|
|
8510
8608
|
* @param {IDBIndexFull} index
|
|
8511
8609
|
* @param {boolean} hasKey
|
|
@@ -8522,12 +8620,9 @@ Object.defineProperty(IDBIndex, 'prototype', {
|
|
|
8522
8620
|
* @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
|
|
8523
8621
|
* @returns {void}
|
|
8524
8622
|
*/
|
|
8525
|
-
function executeFetchIndexData(
|
|
8623
|
+
function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
|
|
8526
8624
|
if (unboundedDisallowed) {
|
|
8527
|
-
|
|
8528
|
-
}
|
|
8529
|
-
if (count) {
|
|
8530
|
-
sql.push('LIMIT', String(count));
|
|
8625
|
+
sql.push('LIMIT', '1');
|
|
8531
8626
|
}
|
|
8532
8627
|
const isCount = opType === 'count';
|
|
8533
8628
|
if (CFG.DEBUG) {
|
|
@@ -8589,11 +8684,15 @@ function executeFetchIndexData(count, unboundedDisallowed, index, hasKey, range,
|
|
|
8589
8684
|
record = row;
|
|
8590
8685
|
}
|
|
8591
8686
|
}
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8687
|
+
/* 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. */
|
|
8688
|
+
if (!record) {
|
|
8689
|
+
continue;
|
|
8690
|
+
}
|
|
8691
|
+
/* c8 ignore stop -- see comment above */
|
|
8692
|
+
|
|
8693
|
+
records.push(decode$2(record));
|
|
8694
|
+
if (unboundedDisallowed) {
|
|
8695
|
+
break;
|
|
8597
8696
|
}
|
|
8598
8697
|
}
|
|
8599
8698
|
} else {
|
|
@@ -8608,8 +8707,16 @@ function executeFetchIndexData(count, unboundedDisallowed, index, hasKey, range,
|
|
|
8608
8707
|
if (isCount) {
|
|
8609
8708
|
success(recordCount);
|
|
8610
8709
|
} else if (recordCount === 0) {
|
|
8710
|
+
// `unboundedDisallowed` is always `true` here: this function is only reached (for
|
|
8711
|
+
// non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
|
|
8712
|
+
// through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
|
|
8713
|
+
// different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
|
|
8714
|
+
// (returning `[]` here) is unreachable given current callers.
|
|
8715
|
+
/* c8 ignore next -- see comment above */
|
|
8611
8716
|
success(unboundedDisallowed ? undefined : []);
|
|
8612
8717
|
} else {
|
|
8718
|
+
// `unboundedDisallowed` is always `true` here; see comment above.
|
|
8719
|
+
/* c8 ignore next -- see comment above */
|
|
8613
8720
|
success(unboundedDisallowed ? records[0] : records);
|
|
8614
8721
|
}
|
|
8615
8722
|
}, /** @type {SqlErrorCallback} */error);
|
|
@@ -8855,6 +8962,7 @@ IDBObjectStore.__createInstance = function (storeProperties, transaction) {
|
|
|
8855
8962
|
tx.executeSql(sql, sqlValues, function (tx) {
|
|
8856
8963
|
// This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
|
|
8857
8964
|
const sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
|
|
8965
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
|
|
8858
8966
|
if (CFG.DEBUG) {
|
|
8859
8967
|
console.log(sql);
|
|
8860
8968
|
}
|
|
@@ -8863,8 +8971,10 @@ IDBObjectStore.__createInstance = function (storeProperties, transaction) {
|
|
|
8863
8971
|
success();
|
|
8864
8972
|
});
|
|
8865
8973
|
}, function (tx, err) {
|
|
8974
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8866
8975
|
error(err);
|
|
8867
8976
|
return false;
|
|
8977
|
+
/* c8 ignore stop -- see comment above */
|
|
8868
8978
|
});
|
|
8869
8979
|
});
|
|
8870
8980
|
}
|
|
@@ -8938,6 +9048,7 @@ IDBObjectStore.__createObjectStore = function (db, store) {
|
|
|
8938
9048
|
storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
|
|
8939
9049
|
}
|
|
8940
9050
|
transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
|
|
9051
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8941
9052
|
/**
|
|
8942
9053
|
* @param {WebSQLTransaction} tx
|
|
8943
9054
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -8950,6 +9061,8 @@ IDBObjectStore.__createObjectStore = function (db, store) {
|
|
|
8950
9061
|
failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
|
|
8951
9062
|
return false;
|
|
8952
9063
|
}
|
|
9064
|
+
/* c8 ignore stop -- see comment above */
|
|
9065
|
+
|
|
8953
9066
|
const escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
8954
9067
|
// key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
|
|
8955
9068
|
const sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
|
|
@@ -9004,6 +9117,7 @@ IDBObjectStore.__deleteObjectStore = function (db, store) {
|
|
|
9004
9117
|
|
|
9005
9118
|
// Remove the object store from WebSQL
|
|
9006
9119
|
transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
|
|
9120
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9007
9121
|
/**
|
|
9008
9122
|
* @param {WebSQLTransaction} tx
|
|
9009
9123
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9016,6 +9130,8 @@ IDBObjectStore.__deleteObjectStore = function (db, store) {
|
|
|
9016
9130
|
failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
|
|
9017
9131
|
return false;
|
|
9018
9132
|
}
|
|
9133
|
+
/* c8 ignore stop -- see comment above */
|
|
9134
|
+
|
|
9019
9135
|
tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
|
|
9020
9136
|
if (data.rows.length > 0) {
|
|
9021
9137
|
tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
|
|
@@ -9195,13 +9311,15 @@ IDBObjectStore.prototype.__checkIndexConstraints = function (tx, value, excludeK
|
|
|
9195
9311
|
return;
|
|
9196
9312
|
}
|
|
9197
9313
|
const indexKeyValue = indexKey.value;
|
|
9314
|
+
/* 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. */
|
|
9198
9315
|
if (indexKeyValue === undefined) {
|
|
9199
9316
|
resolve(undefined);
|
|
9200
9317
|
return;
|
|
9201
9318
|
}
|
|
9319
|
+
/* c8 ignore stop -- see comment above */
|
|
9202
9320
|
const multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
9203
9321
|
const fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
9204
|
-
executeFetchIndexData(
|
|
9322
|
+
executeFetchIndexData(...fetchArgs, tx, null, function success(key) {
|
|
9205
9323
|
if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
|
|
9206
9324
|
resolve(undefined);
|
|
9207
9325
|
return;
|
|
@@ -9281,16 +9399,18 @@ IDBObjectStore.prototype.__insertData = function (tx, encoded, value, clonedKeyO
|
|
|
9281
9399
|
* @returns {void}
|
|
9282
9400
|
*/
|
|
9283
9401
|
function setIndexInfo(index) {
|
|
9402
|
+
/* 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. */
|
|
9284
9403
|
if (indexKeyValue === undefined) {
|
|
9285
9404
|
return;
|
|
9286
9405
|
}
|
|
9406
|
+
/* c8 ignore stop -- see comment above */
|
|
9287
9407
|
paramMap[index.__currentName] = /** @type {string} */
|
|
9288
9408
|
encode$1(indexKeyValue, index.multiEntry);
|
|
9289
9409
|
}
|
|
9290
9410
|
if (index.unique) {
|
|
9291
9411
|
const multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
9292
9412
|
const fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
9293
|
-
executeFetchIndexData(
|
|
9413
|
+
executeFetchIndexData(...fetchArgs, tx, null, function success(key) {
|
|
9294
9414
|
if (key === undefined) {
|
|
9295
9415
|
setIndexInfo(index);
|
|
9296
9416
|
resolve(undefined);
|
|
@@ -9375,6 +9495,7 @@ IDBObjectStore.prototype.add = function (value /* , key */) {
|
|
|
9375
9495
|
me.transaction.__assertWritable();
|
|
9376
9496
|
const request = /** @type {import('./IDBTransaction.js').IDBTransactionFull} */me.transaction.__createRequest(me);
|
|
9377
9497
|
const [ky, clonedValue] = me.__validateKeyAndValueAndCloneValue(value, key, false);
|
|
9498
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
9378
9499
|
// @ts-ignore -- Private API
|
|
9379
9500
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
|
|
9380
9501
|
return request;
|
|
@@ -9403,6 +9524,7 @@ IDBObjectStore.prototype.put = function (value /* , key */) {
|
|
|
9403
9524
|
me.transaction.__assertWritable();
|
|
9404
9525
|
const request = /** @type {import('./IDBTransaction.js').IDBTransactionFull} */me.transaction.__createRequest(me);
|
|
9405
9526
|
const [ky, clonedValue] = me.__validateKeyAndValueAndCloneValue(value, key, false);
|
|
9527
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
9406
9528
|
// @ts-ignore -- Private API
|
|
9407
9529
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
|
|
9408
9530
|
return request;
|
|
@@ -9429,8 +9551,10 @@ IDBObjectStore.prototype.__overwrite = function (tx, key, cb, error) {
|
|
|
9429
9551
|
}
|
|
9430
9552
|
cb(tx);
|
|
9431
9553
|
}, function (tx, err) {
|
|
9554
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9432
9555
|
error(err);
|
|
9433
9556
|
return false;
|
|
9557
|
+
/* c8 ignore stop -- see comment above */
|
|
9434
9558
|
});
|
|
9435
9559
|
};
|
|
9436
9560
|
|
|
@@ -9539,16 +9663,20 @@ IDBObjectStore.prototype.__get = function (query, getKey) {
|
|
|
9539
9663
|
return;
|
|
9540
9664
|
}
|
|
9541
9665
|
ret = getKey ? decode$1(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
|
|
9666
|
+
/* 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. */
|
|
9542
9667
|
} catch (e) {
|
|
9543
9668
|
// If no result is returned, or error occurs when parsing JSON
|
|
9544
9669
|
if (CFG.DEBUG) {
|
|
9545
9670
|
console.log(e);
|
|
9546
9671
|
}
|
|
9547
9672
|
}
|
|
9673
|
+
/* c8 ignore stop -- see comment above */
|
|
9548
9674
|
success(ret);
|
|
9549
9675
|
}, function (tx, err) {
|
|
9676
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9550
9677
|
error(err);
|
|
9551
9678
|
return false;
|
|
9679
|
+
/* c8 ignore stop -- see comment above */
|
|
9552
9680
|
});
|
|
9553
9681
|
}, undefined, me);
|
|
9554
9682
|
};
|
|
@@ -9663,8 +9791,10 @@ IDBObjectStore.prototype.delete = function (query) {
|
|
|
9663
9791
|
});
|
|
9664
9792
|
success();
|
|
9665
9793
|
}, function (tx, err) {
|
|
9794
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9666
9795
|
error(err);
|
|
9667
9796
|
return false;
|
|
9797
|
+
/* c8 ignore stop -- see comment above */
|
|
9668
9798
|
});
|
|
9669
9799
|
}, undefined, me);
|
|
9670
9800
|
};
|
|
@@ -9692,8 +9822,10 @@ IDBObjectStore.prototype.clear = function () {
|
|
|
9692
9822
|
});
|
|
9693
9823
|
success();
|
|
9694
9824
|
}, function (tx, err) {
|
|
9825
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9695
9826
|
error(err);
|
|
9696
9827
|
return false;
|
|
9828
|
+
/* c8 ignore stop -- see comment above */
|
|
9697
9829
|
});
|
|
9698
9830
|
}, undefined, me);
|
|
9699
9831
|
};
|
|
@@ -10023,7 +10155,7 @@ IDBDatabase.prototype.createObjectStore = function (storeName /* , createOptions
|
|
|
10023
10155
|
if (keyPath !== null && !isValidKeyPath(keyPath)) {
|
|
10024
10156
|
throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
|
|
10025
10157
|
}
|
|
10026
|
-
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
|
|
10158
|
+
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
|
|
10027
10159
|
throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
|
|
10028
10160
|
}
|
|
10029
10161
|
const autoInc = createOptions.autoIncrement;
|
|
@@ -10171,7 +10303,6 @@ IDBDatabase.prototype.throwIfUpgradeTransactionNull = function () {
|
|
|
10171
10303
|
}
|
|
10172
10304
|
};
|
|
10173
10305
|
|
|
10174
|
-
// Todo __forceClose: Add tests for `__forceClose`
|
|
10175
10306
|
/**
|
|
10176
10307
|
*
|
|
10177
10308
|
* @param {string} msg
|
|
@@ -10180,23 +10311,39 @@ IDBDatabase.prototype.throwIfUpgradeTransactionNull = function () {
|
|
|
10180
10311
|
*/
|
|
10181
10312
|
IDBDatabase.prototype.__forceClose = function (msg) {
|
|
10182
10313
|
const me = this;
|
|
10314
|
+
// `close()` (below) resets `me.__transactions` to `[]`, so the
|
|
10315
|
+
// transactions to abort -- and the total count the completion check
|
|
10316
|
+
// below needs -- must be captured before calling it, not read back off
|
|
10317
|
+
// `me.__transactions` afterward.
|
|
10318
|
+
const transactions = me.__transactions;
|
|
10183
10319
|
me.close();
|
|
10320
|
+
|
|
10321
|
+
/**
|
|
10322
|
+
* @returns {void}
|
|
10323
|
+
*/
|
|
10324
|
+
function dispatchClose() {
|
|
10325
|
+
// Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
|
|
10326
|
+
const evt = createEvent('close');
|
|
10327
|
+
setTimeout(() => {
|
|
10328
|
+
me.dispatchEvent(evt);
|
|
10329
|
+
}, 0);
|
|
10330
|
+
}
|
|
10331
|
+
if (!transactions.length) {
|
|
10332
|
+
dispatchClose();
|
|
10333
|
+
return;
|
|
10334
|
+
}
|
|
10184
10335
|
let ct = 0;
|
|
10185
|
-
|
|
10336
|
+
transactions.forEach(function (trans) {
|
|
10186
10337
|
// eslint-disable-next-line camelcase -- Clear API
|
|
10187
10338
|
trans.on__abort = function () {
|
|
10188
10339
|
ct++;
|
|
10189
|
-
if (ct
|
|
10190
|
-
|
|
10191
|
-
const evt = createEvent('close');
|
|
10192
|
-
setTimeout(() => {
|
|
10193
|
-
me.dispatchEvent(evt);
|
|
10194
|
-
}, 0);
|
|
10340
|
+
if (ct !== transactions.length) {
|
|
10341
|
+
return;
|
|
10195
10342
|
}
|
|
10343
|
+
dispatchClose();
|
|
10196
10344
|
};
|
|
10197
10345
|
trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
|
|
10198
10346
|
});
|
|
10199
|
-
me.__transactions = [];
|
|
10200
10347
|
};
|
|
10201
10348
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
10202
10349
|
defineOuterInterface(IDBDatabase.prototype, listeners);
|
|
@@ -10357,6 +10504,7 @@ function triggerAnyVersionChangeAndBlockedEvents(openConnections, req, oldVersio
|
|
|
10357
10504
|
return undefined;
|
|
10358
10505
|
}
|
|
10359
10506
|
const e = /** @type {Event & IDBVersionChangeEvent} */
|
|
10507
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10360
10508
|
// @ts-ignore It's ok; needed under some TS versions
|
|
10361
10509
|
new IDBVersionChangeEvent('versionchange', {
|
|
10362
10510
|
oldVersion,
|
|
@@ -10404,6 +10552,7 @@ function triggerAnyVersionChangeAndBlockedEvents(openConnections, req, oldVersio
|
|
|
10404
10552
|
}
|
|
10405
10553
|
};
|
|
10406
10554
|
const e = /** @type {Event & IDBVersionChangeEvent} */
|
|
10555
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10407
10556
|
// @ts-ignore It's ok; needed under some TS versions
|
|
10408
10557
|
new IDBVersionChangeEvent('blocked', {
|
|
10409
10558
|
oldVersion,
|
|
@@ -10464,6 +10613,13 @@ const pendingVersionChanges = new Map();
|
|
|
10464
10613
|
|
|
10465
10614
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
10466
10615
|
let sysdb;
|
|
10616
|
+
// Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
|
|
10617
|
+
// later change to that config (e.g. toggling in-memory mode on and back
|
|
10618
|
+
// off) causes `sysdb` to be recreated for the new setting rather than
|
|
10619
|
+
// staying pinned, forever, to whatever it was the first time any database
|
|
10620
|
+
// was created in the process.
|
|
10621
|
+
/** @type {string|null|undefined} */
|
|
10622
|
+
let sysdbMemoryDatabaseSetting;
|
|
10467
10623
|
let nameCounter = 0;
|
|
10468
10624
|
|
|
10469
10625
|
/**
|
|
@@ -10545,12 +10701,20 @@ function closeCachedWebSQLConnections(name, cb) {
|
|
|
10545
10701
|
function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
|
|
10546
10702
|
const useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
|
|
10547
10703
|
if (useMemoryDatabase) {
|
|
10704
|
+
/* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
|
|
10705
|
+
was initialized as an empty placeholder by `open()`'s connection-queue
|
|
10706
|
+
setup (`addRequestToConnectionQueue`, above `openDB`) but never
|
|
10707
|
+
populated with an actual instance -- e.g. `__openDatabase` throwing
|
|
10708
|
+
after a `dbVersions` row already existed for `name` from an earlier,
|
|
10709
|
+
successful `open()` -- or if `name` was never added to the cache at
|
|
10710
|
+
all. Not reachable via normal, non-tampered API usage. */
|
|
10548
10711
|
const latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
|
|
10549
10712
|
if (!latestSQLiteDBCached) {
|
|
10550
10713
|
console.warn('Could not find a memory database instance to delete.');
|
|
10551
10714
|
databaseDeleted();
|
|
10552
10715
|
return;
|
|
10553
10716
|
}
|
|
10717
|
+
/* c8 ignore stop -- see comment above */
|
|
10554
10718
|
const sqliteDB = latestSQLiteDBCached._db;
|
|
10555
10719
|
if (!sqliteDB || !sqliteDB.close) {
|
|
10556
10720
|
console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
|
|
@@ -10604,15 +10768,24 @@ function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, dat
|
|
|
10604
10768
|
tables.item(i).name)), [], function () {
|
|
10605
10769
|
deleteTables(i + 1);
|
|
10606
10770
|
}, function () {
|
|
10771
|
+
/* c8 ignore start -- Defensive: continues deleting the rest
|
|
10772
|
+
even if this specific store's table is already gone (e.g.
|
|
10773
|
+
duplicate `__sys__` rows for the same escaped table name, or
|
|
10774
|
+
external tampering); not reachable via normal API usage. */
|
|
10607
10775
|
deleteTables(i + 1);
|
|
10608
10776
|
return false;
|
|
10777
|
+
/* c8 ignore stop -- see comment above */
|
|
10609
10778
|
});
|
|
10610
10779
|
}
|
|
10611
10780
|
})(0);
|
|
10612
10781
|
}, function () {
|
|
10613
|
-
|
|
10782
|
+
/* c8 ignore start -- `__sys__` is always created by `openDB` before this
|
|
10783
|
+
database's `dbVersions` row (a prerequisite for reaching this code at
|
|
10784
|
+
all) is ever inserted; only reachable if the file was tampered with/
|
|
10785
|
+
removed externally afterward. */
|
|
10614
10786
|
databaseDeleted();
|
|
10615
10787
|
return false;
|
|
10788
|
+
/* c8 ignore stop -- see comment above */
|
|
10616
10789
|
});
|
|
10617
10790
|
});
|
|
10618
10791
|
}
|
|
@@ -10643,9 +10816,11 @@ function createSysDB(__openDatabase, success, failure) {
|
|
|
10643
10816
|
}
|
|
10644
10817
|
failure(er);
|
|
10645
10818
|
}
|
|
10646
|
-
if (sysdb) {
|
|
10819
|
+
if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
|
|
10647
10820
|
success();
|
|
10648
10821
|
} else {
|
|
10822
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
|
|
10823
|
+
sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
|
|
10649
10824
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
|
|
10650
10825
|
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);
|
|
10651
10826
|
sysdb.transaction(function (systx) {
|
|
@@ -10825,6 +11000,17 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
10825
11000
|
* @returns {void}
|
|
10826
11001
|
*/
|
|
10827
11002
|
let sysdbFinishedCb = function (systx, err, cb) {
|
|
11003
|
+
/* c8 ignore start -- This initial definition is always
|
|
11004
|
+
superseded before ever being invoked: the `sysdb.transaction(...)`
|
|
11005
|
+
call below always reaches its `nonstandardTransCb` (4th arg)
|
|
11006
|
+
after this same SQL batch finishes running (since `dbCreateError`
|
|
11007
|
+
always reports errors as "handled" and this call site is never
|
|
11008
|
+
a `readTransaction`), which unconditionally reassigns
|
|
11009
|
+
`sysdbFinishedCb` to a version using the library's own
|
|
11010
|
+
`rollback`/`commit` -- well before any real invocation from
|
|
11011
|
+
`on__beforecomplete`/`on__preabort`/`on__abort` below (those only
|
|
11012
|
+
fire once the upgrade transaction itself later completes/aborts).
|
|
11013
|
+
Kept as a defensive fallback in case that invariant ever changes. */
|
|
10828
11014
|
if (err) {
|
|
10829
11015
|
/**
|
|
10830
11016
|
* @param {unknown} [errorToShow]
|
|
@@ -10873,6 +11059,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
10873
11059
|
}
|
|
10874
11060
|
// In browser, should auto-commit
|
|
10875
11061
|
cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11062
|
+
/* c8 ignore stop -- see comment above */
|
|
10876
11063
|
};
|
|
10877
11064
|
sysdb.transaction(function (systx) {
|
|
10878
11065
|
/**
|
|
@@ -10880,6 +11067,7 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
10880
11067
|
*/
|
|
10881
11068
|
function versionSet() {
|
|
10882
11069
|
const e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
|
|
11070
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10883
11071
|
// @ts-ignore It's ok; needed under some TS versions
|
|
10884
11072
|
new IDBVersionChangeEvent('upgradeneeded', {
|
|
10885
11073
|
oldVersion,
|
|
@@ -11005,9 +11193,17 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
11005
11193
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11006
11194
|
req.transaction.on__complete = function () {
|
|
11007
11195
|
const pos = connection.__transactions.indexOf(req.transaction);
|
|
11196
|
+
// `req.transaction` (the versionchange transaction) is created
|
|
11197
|
+
// directly via `IDBTransaction.__createInstance` above, never
|
|
11198
|
+
// via `IDBDatabase.prototype.transaction()` (the only place
|
|
11199
|
+
// that pushes onto `connection.__transactions`), so `pos` is
|
|
11200
|
+
// always -1 here.
|
|
11201
|
+
/* c8 ignore start -- see comment above */
|
|
11008
11202
|
if (pos !== -1) {
|
|
11009
11203
|
connection.__transactions.splice(pos, 1);
|
|
11010
11204
|
}
|
|
11205
|
+
/* c8 ignore stop -- see comment above */
|
|
11206
|
+
|
|
11011
11207
|
if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
|
|
11012
11208
|
req.__transaction = null;
|
|
11013
11209
|
const err = createDOMException('AbortError', 'The connection has been closed.');
|
|
@@ -11043,9 +11239,16 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
11043
11239
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
|
|
11044
11240
|
}
|
|
11045
11241
|
}, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
11242
|
+
// Defensive fallback, not reachable in practice: same reasoning
|
|
11243
|
+
// as `deleteDatabase`'s own `nonstandardTransCb` below
|
|
11244
|
+
// (`currentTask.readOnly` is always false here, and
|
|
11245
|
+
// `dbCreateError` always returns `false`, so `err` is never
|
|
11246
|
+
// truthy either).
|
|
11247
|
+
/* c8 ignore start -- see comment above */
|
|
11046
11248
|
if (currentTask.readOnly || err) {
|
|
11047
11249
|
return true;
|
|
11048
11250
|
}
|
|
11251
|
+
/* c8 ignore stop -- see comment above */
|
|
11049
11252
|
sysdbFinishedCb = function (systx, err, cb) {
|
|
11050
11253
|
if (err) {
|
|
11051
11254
|
rollback(err,
|
|
@@ -11060,7 +11263,17 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
11060
11263
|
} else {
|
|
11061
11264
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
|
|
11062
11265
|
}
|
|
11063
|
-
},
|
|
11266
|
+
},
|
|
11267
|
+
// Deeply-nested defensive path: only reached if
|
|
11268
|
+
// the *revert* SQL (undoing the `dbVersions`
|
|
11269
|
+
// INSERT/UPDATE after the original version-
|
|
11270
|
+
// upgrade itself already failed) fails a
|
|
11271
|
+
// *second* time. Not feasibly triggerable
|
|
11272
|
+
// without fault-injecting the underlying SQL
|
|
11273
|
+
// driver on this specific, already-failing
|
|
11274
|
+
// revert statement.
|
|
11275
|
+
function (sqlErr) {
|
|
11276
|
+
/* c8 ignore next 2 -- see comment above */
|
|
11064
11277
|
isRevertingSysdb = false;
|
|
11065
11278
|
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11066
11279
|
}, function () {
|
|
@@ -11076,8 +11289,20 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
11076
11289
|
});
|
|
11077
11290
|
return undefined;
|
|
11078
11291
|
}).catch(err => {
|
|
11292
|
+
/* c8 ignore start -- Purely defensive: nothing in
|
|
11293
|
+
`triggerAnyVersionChangeAndBlockedEvents`'s promise chain
|
|
11294
|
+
(or this `.then()` continuation above) ever rejects/throws
|
|
11295
|
+
under any reachable application-level condition -- all of
|
|
11296
|
+
its continuations resolve cleanly, and its `dispatchEvent`
|
|
11297
|
+
calls are deliberately fire-and-forget ("No need to catch
|
|
11298
|
+
errors"), running inside a `setTimeout` where a listener
|
|
11299
|
+
throwing becomes an uncaught exception in that macrotask
|
|
11300
|
+
rather than a promise rejection here. This exists solely
|
|
11301
|
+
to surface a truly-unexpected internal bug via the console
|
|
11302
|
+
before rethrowing, not to handle a real, testable error path. */
|
|
11079
11303
|
console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
|
|
11080
11304
|
throw err;
|
|
11305
|
+
/* c8 ignore stop -- see comment above */
|
|
11081
11306
|
});
|
|
11082
11307
|
} else {
|
|
11083
11308
|
finishRequest();
|
|
@@ -11105,11 +11330,19 @@ IDBFactory.prototype.open = function (name /* , version */) {
|
|
|
11105
11330
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
11106
11331
|
db = websqlDBCache[name][version];
|
|
11107
11332
|
} else {
|
|
11108
|
-
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
11333
|
+
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
11109
11334
|
if (useDatabaseCache) {
|
|
11335
|
+
/* c8 ignore start -- Defensive: by the time `openDB` runs,
|
|
11336
|
+
`websqlDBCache[name]` has always already been created by
|
|
11337
|
+
`addRequestToConnectionQueue`'s own callback above (guarded
|
|
11338
|
+
by this same `useDatabaseCache` condition), which always
|
|
11339
|
+
runs first and unconditionally ensures the entry exists
|
|
11340
|
+
before ever calling `openDB`. Kept as a safety net in case
|
|
11341
|
+
that invariant ever changes. */
|
|
11110
11342
|
if (!Object.hasOwn(websqlDBCache, name)) {
|
|
11111
11343
|
websqlDBCache[name] = {};
|
|
11112
11344
|
}
|
|
11345
|
+
/* c8 ignore stop -- see comment above */
|
|
11113
11346
|
websqlDBCache[name][version] = db;
|
|
11114
11347
|
}
|
|
11115
11348
|
}
|
|
@@ -11260,6 +11493,7 @@ IDBFactory.prototype.deleteDatabase = function (name) {
|
|
|
11260
11493
|
req.__result = undefined;
|
|
11261
11494
|
req.__done = true;
|
|
11262
11495
|
const e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11496
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11263
11497
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11264
11498
|
new IDBVersionChangeEvent('success', {
|
|
11265
11499
|
oldVersion: version,
|
|
@@ -11303,9 +11537,23 @@ IDBFactory.prototype.deleteDatabase = function (name) {
|
|
|
11303
11537
|
cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
|
|
11304
11538
|
}, dbError);
|
|
11305
11539
|
}, dbError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
11540
|
+
/* c8 ignore start -- Defensive fallback, not reachable in
|
|
11541
|
+
practice: `currentTask.readOnly` is always `false` here
|
|
11542
|
+
(this callback is only ever attached to the writable
|
|
11543
|
+
`sysdb.transaction(...)` call above, never to a
|
|
11544
|
+
`sysdb.readTransaction(...)`), and `err` can only be
|
|
11545
|
+
truthy if the `DELETE FROM dbVersions` statement's own
|
|
11546
|
+
error callback (`dbError`) reports the failure back to
|
|
11547
|
+
`websql-configurable` as unhandled -- but `dbError`
|
|
11548
|
+
deliberately always `return`s `false`, which tells the
|
|
11549
|
+
library the error was already handled (and to keep
|
|
11550
|
+
`err` falsy here), precisely so this custom
|
|
11551
|
+
`sysdbFinishedCbDelete` rollback/commit path below is
|
|
11552
|
+
used instead of the library's own default rollback. */
|
|
11306
11553
|
if (currentTask.readOnly || err) {
|
|
11307
11554
|
return true;
|
|
11308
11555
|
}
|
|
11556
|
+
/* c8 ignore stop -- see comment above */
|
|
11309
11557
|
sysdbFinishedCbDelete = function (err, cb) {
|
|
11310
11558
|
if (err) {
|
|
11311
11559
|
rollback(err, cb);
|
|
@@ -11432,10 +11680,9 @@ IDBFactory.prototype.databases = function () {
|
|
|
11432
11680
|
};
|
|
11433
11681
|
|
|
11434
11682
|
/**
|
|
11435
|
-
* @todo forceClose: Test
|
|
11436
11683
|
* This is provided to facilitate unit-testing of the
|
|
11437
11684
|
* closing of a database connection with a forced flag:
|
|
11438
|
-
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection
|
|
11685
|
+
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
|
|
11439
11686
|
* @param {string} dbName
|
|
11440
11687
|
* @param {Integer} connIdx
|
|
11441
11688
|
* @param {string} msg
|
|
@@ -11535,6 +11782,7 @@ IDBRecord.__createInstance = function (key, primaryKey, value) {
|
|
|
11535
11782
|
* @this {IDBRecordFull}
|
|
11536
11783
|
*/
|
|
11537
11784
|
function IDBRecord() {
|
|
11785
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11538
11786
|
// @ts-ignore Should be ok
|
|
11539
11787
|
this[Symbol.toStringTag] = 'IDBRecord';
|
|
11540
11788
|
this.__key = key;
|
|
@@ -11575,6 +11823,7 @@ readonlyProperties.forEach(prop => {
|
|
|
11575
11823
|
if (!(this instanceof IDBRecordAlias)) {
|
|
11576
11824
|
throw new TypeError('Illegal invocation');
|
|
11577
11825
|
}
|
|
11826
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11578
11827
|
// @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
|
|
11579
11828
|
return this['__' + prop];
|
|
11580
11829
|
}
|
|
@@ -11918,6 +12167,7 @@ IDBCursor.prototype.__findBasic = function (key, primaryKey, tx, success, error,
|
|
|
11918
12167
|
success(undefined, undefined, undefined);
|
|
11919
12168
|
}
|
|
11920
12169
|
}, function (tx, err) {
|
|
12170
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
11921
12171
|
if (CFG.DEBUG) {
|
|
11922
12172
|
console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
11923
12173
|
}
|
|
@@ -12093,7 +12343,16 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
|
|
|
12093
12343
|
if (a.key > b.key) {
|
|
12094
12344
|
return me.direction === 'prev' ? -1 : 1;
|
|
12095
12345
|
}
|
|
12346
|
+
/* c8 ignore start -- Defensive: only reachable if two matches
|
|
12347
|
+
in the same batch shared both the same `matchingKey` and
|
|
12348
|
+
the same primary `key`, which would require the same
|
|
12349
|
+
record's multi-entry array to contain a duplicate value.
|
|
12350
|
+
`Key.js`'s array-to-key conversion already drops duplicate
|
|
12351
|
+
values when a multi-entry index entry is built, so this
|
|
12352
|
+
can never happen in practice; kept only to satisfy the
|
|
12353
|
+
`Array.prototype.sort` comparator contract. */
|
|
12096
12354
|
return 0;
|
|
12355
|
+
/* c8 ignore stop -- see comment above */
|
|
12097
12356
|
});
|
|
12098
12357
|
me.__prefetchedIndex = 0;
|
|
12099
12358
|
me.__prefetchedData = {
|
|
@@ -12112,13 +12371,19 @@ IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, e
|
|
|
12112
12371
|
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
12113
12372
|
}
|
|
12114
12373
|
me.__decode(rows[0], success);
|
|
12115
|
-
},
|
|
12374
|
+
},
|
|
12375
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
12376
|
+
execution error (e.g. I/O error, corruption) while querying for
|
|
12377
|
+
multi-entry cursor matches; not reliably reproducible without
|
|
12378
|
+
mocking the SQL layer. */
|
|
12379
|
+
function (tx, err) {
|
|
12116
12380
|
if (CFG.DEBUG) {
|
|
12117
12381
|
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12118
12382
|
}
|
|
12119
12383
|
error(err);
|
|
12120
12384
|
return false;
|
|
12121
12385
|
});
|
|
12386
|
+
/* c8 ignore stop -- see comment above */
|
|
12122
12387
|
}
|
|
12123
12388
|
runQuery();
|
|
12124
12389
|
};
|
|
@@ -12227,6 +12492,7 @@ IDBCursor.prototype.__sourceOrEffectiveObjStoreDeleted = function () {
|
|
|
12227
12492
|
* @returns {void}
|
|
12228
12493
|
*/
|
|
12229
12494
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
12495
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12230
12496
|
// @ts-ignore Why is this not being found?; needed under some TS versions
|
|
12231
12497
|
this.__prefetchedData = null;
|
|
12232
12498
|
this.__multiEntryExhausted = false;
|
|
@@ -12251,7 +12517,7 @@ IDBCursor.prototype.__continue = function (key, advanceContinue) {
|
|
|
12251
12517
|
convertValueToKeyRethrowingAndIfInvalid(key);
|
|
12252
12518
|
const cmpResult = cmp(key, me.key);
|
|
12253
12519
|
if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
|
|
12254
|
-
throw createDOMException('DataError', 'Cannot
|
|
12520
|
+
throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
|
|
12255
12521
|
}
|
|
12256
12522
|
}
|
|
12257
12523
|
this.__continueFinish(key, undefined, advanceState);
|
|
@@ -12500,6 +12766,7 @@ IDBCursor.prototype.update = function (valueToUpdate) {
|
|
|
12500
12766
|
// continuation logic in `__findBasic` to see this update's
|
|
12501
12767
|
// effect on ordering (see "Modify records during cursor
|
|
12502
12768
|
// iteration" in idbcursor_update_index.any.js).
|
|
12769
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12503
12770
|
// @ts-ignore -- API (not erring in TS 6)
|
|
12504
12771
|
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
12505
12772
|
}
|
|
@@ -12546,14 +12813,33 @@ IDBCursor.prototype.delete = function () {
|
|
|
12546
12813
|
// We don't invalidate the cache (as we don't access it anymore
|
|
12547
12814
|
// and it will set the index off)
|
|
12548
12815
|
success(undefined);
|
|
12816
|
+
/* c8 ignore start -- Defensive: `__find` (invoked just above) has
|
|
12817
|
+
already confirmed a row exists for this primary key within the
|
|
12818
|
+
same transaction queue, so `rowsAffected` should always be 1 in
|
|
12819
|
+
normal usage. This branch would only be reached if the underlying
|
|
12820
|
+
row were removed by another request queued in the same
|
|
12821
|
+
transaction between `__find`'s check and this DELETE actually
|
|
12822
|
+
running (e.g. deleting the same record directly via the object
|
|
12823
|
+
store while a cursor over it is mid-iteration); attempts to
|
|
12824
|
+
construct such a scenario instead trigger a transaction abort
|
|
12825
|
+
(`AbortError`) before this callback ever runs, since the default
|
|
12826
|
+
action of an unhandled request error is to abort the
|
|
12827
|
+
transaction. */
|
|
12549
12828
|
} else {
|
|
12550
12829
|
// @ts-expect-error Apparently ok
|
|
12551
12830
|
error('No rows with key found' + key);
|
|
12552
12831
|
}
|
|
12553
|
-
|
|
12832
|
+
/* c8 ignore stop -- see comment above */
|
|
12833
|
+
},
|
|
12834
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
12835
|
+
execution error (e.g. I/O error, corruption) while deleting the
|
|
12836
|
+
current row; not reliably reproducible without mocking the SQL
|
|
12837
|
+
layer. */
|
|
12838
|
+
function (tx, data) {
|
|
12554
12839
|
error(data);
|
|
12555
12840
|
return false;
|
|
12556
12841
|
});
|
|
12842
|
+
/* c8 ignore stop -- see comment above */
|
|
12557
12843
|
}, error);
|
|
12558
12844
|
}, undefined, me);
|
|
12559
12845
|
};
|
|
@@ -12959,7 +13245,7 @@ function setGlobalVars(idb, initialConfig) {
|
|
|
12959
13245
|
setConfig(initialConfig);
|
|
12960
13246
|
}
|
|
12961
13247
|
const IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
|
|
12962
|
-
/** @type {unknown} */idb || globalThis
|
|
13248
|
+
/** @type {unknown} */idb || globalThis;
|
|
12963
13249
|
/**
|
|
12964
13250
|
* @param {string} name
|
|
12965
13251
|
* @param {unknown} value
|
|
@@ -13054,77 +13340,84 @@ function setGlobalVars(idb, initialConfig) {
|
|
|
13054
13340
|
});
|
|
13055
13341
|
}
|
|
13056
13342
|
const shimIDBFactory = IDBFactory;
|
|
13057
|
-
if (CFG.win.openDatabase
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13343
|
+
if (CFG.win.openDatabase === undefined) {
|
|
13344
|
+
return;
|
|
13345
|
+
}
|
|
13346
|
+
shimIndexedDB.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
|
|
13347
|
+
// Polyfill ALL of IndexedDB, using WebSQL
|
|
13348
|
+
shim('indexedDB', shimIndexedDB, {
|
|
13349
|
+
enumerable: true,
|
|
13350
|
+
configurable: true,
|
|
13351
|
+
get() {
|
|
13352
|
+
if (this !== IDB && !isNullish(this) && !this.shimNS) {
|
|
13353
|
+
// Latter is hack for test environment
|
|
13354
|
+
throw new TypeError('Illegal invocation');
|
|
13069
13355
|
}
|
|
13070
|
-
|
|
13071
|
-
/** @type {[string, unknown][]} */
|
|
13072
|
-
[['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(([prop, obj]) => {
|
|
13073
|
-
shim(prop, obj, {
|
|
13074
|
-
enumerable: false,
|
|
13075
|
-
configurable: true
|
|
13076
|
-
});
|
|
13077
|
-
});
|
|
13078
|
-
// For Node environments
|
|
13079
|
-
if (CFG.fs) {
|
|
13080
|
-
setFS(CFG.fs);
|
|
13356
|
+
return shimIndexedDB;
|
|
13081
13357
|
}
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13358
|
+
});
|
|
13359
|
+
/** @type {[string, unknown][]} */
|
|
13360
|
+
[['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(([prop, obj]) => {
|
|
13361
|
+
shim(prop, obj, {
|
|
13362
|
+
enumerable: false,
|
|
13363
|
+
configurable: true
|
|
13364
|
+
});
|
|
13365
|
+
});
|
|
13366
|
+
// For Node environments
|
|
13367
|
+
if (CFG.fs) {
|
|
13368
|
+
setFS(CFG.fs);
|
|
13369
|
+
}
|
|
13370
|
+
if (CFG.fullIDLSupport) {
|
|
13371
|
+
// Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
|
|
13372
|
+
|
|
13373
|
+
Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
|
|
13374
|
+
Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
|
|
13375
|
+
Object.setPrototypeOf(IDBDatabase, EventTarget);
|
|
13376
|
+
Object.setPrototypeOf(IDBRequest, EventTarget);
|
|
13377
|
+
Object.setPrototypeOf(IDBTransaction, EventTarget);
|
|
13378
|
+
Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
|
|
13379
|
+
// `ShimDOMException` is the real native `DOMException` when one
|
|
13380
|
+
// is available (see `DOMException.js`'s `useNativeDOMException`)
|
|
13381
|
+
// -- which, unlike the shim classes above, is a single,
|
|
13382
|
+
// process-wide singleton shared by reference across every
|
|
13383
|
+
// sandbox this library gets installed into (see
|
|
13384
|
+
// `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
|
|
13385
|
+
// already has the correct prototype chain out of the box
|
|
13386
|
+
// (`Object.getPrototypeOf(DOMException) === Function.prototype`,
|
|
13387
|
+
// not `Error`), so forcing it here isn't just unneeded but
|
|
13388
|
+
// actively wrong -- and, because it's shared, permanently
|
|
13389
|
+
// wrong for every later use of `DOMException` in the same
|
|
13390
|
+
// process (e.g. a later WPT test file's own idlharness-style
|
|
13391
|
+
// check that `DOMException` does *not* inherit from `Error`
|
|
13392
|
+
// on the class side), not just this one shim install.
|
|
13393
|
+
if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
|
|
13394
|
+
Object.setPrototypeOf(ShimDOMException, Error);
|
|
13395
|
+
Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
|
|
13109
13396
|
}
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
if (CFG.replaceNonIDBGlobals) {
|
|
13118
|
-
setNonIDBGlobals();
|
|
13119
|
-
}
|
|
13397
|
+
}
|
|
13398
|
+
if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
|
|
13399
|
+
if (CFG.addNonIDBGlobals) {
|
|
13400
|
+
// As `DOMStringList` exists per IDL (and Chrome) in the global
|
|
13401
|
+
// thread (but not in workers), we prefix the name to avoid
|
|
13402
|
+
// shadowing or conflicts
|
|
13403
|
+
setNonIDBGlobals('Shim');
|
|
13120
13404
|
}
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
return;
|
|
13405
|
+
if (CFG.replaceNonIDBGlobals) {
|
|
13406
|
+
setNonIDBGlobals();
|
|
13124
13407
|
}
|
|
13125
|
-
/* c8 ignore stop -- TS guard */
|
|
13126
|
-
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13127
13408
|
}
|
|
13409
|
+
/* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
|
|
13410
|
+
confirmed truthy just before this function (`__useShim`) was
|
|
13411
|
+
defined and immediately invoked (see the `if ('shimIndexedDB'
|
|
13412
|
+
in IDB && IDB.shimIndexedDB)` guard above), and nothing in
|
|
13413
|
+
this function's body reassigns or deletes it. Only reachable
|
|
13414
|
+
if `IDB` is some unusual object (e.g. a Proxy) whose
|
|
13415
|
+
`shimIndexedDB` property value changes between reads. */
|
|
13416
|
+
if (!IDB.shimIndexedDB) {
|
|
13417
|
+
return;
|
|
13418
|
+
}
|
|
13419
|
+
/* c8 ignore stop -- see comment above */
|
|
13420
|
+
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13128
13421
|
};
|
|
13129
13422
|
IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
|
|
13130
13423
|
CFG.DEBUG = val;
|
|
@@ -13232,6 +13525,7 @@ function setGlobalVars(idb, initialConfig) {
|
|
|
13232
13525
|
* @returns {SQLiteDatabaseInstance}
|
|
13233
13526
|
*/
|
|
13234
13527
|
function wrappedSQLiteDatabase(name) {
|
|
13528
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13235
13529
|
// @ts-ignore It's ok; needed under some TS versions
|
|
13236
13530
|
const db = new SQLiteDatabase(name, {});
|
|
13237
13531
|
if (CFG.sqlBusyTimeout) {
|