indexeddbshim 19.0.5 → 19.0.7
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/README.md +2 -0
- 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 +73 -33
- 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 +543 -221
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +572 -249
- 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 +543 -221
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +572 -249
- 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 +572 -249
- 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/licenseInfo.json +8 -0
- package/package.json +106 -102
- 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 +53 -22
- package/src/Sca.js +9 -4
- package/src/nodeWebSQL.js +1 -0
- package/src/setGlobalVars.js +86 -77
- package/src/util.js +5 -6
package/dist/indexeddbshim.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! indexeddbshim - v19.0.
|
|
1
|
+
/*! indexeddbshim - v19.0.7 - 9/23/2026 */
|
|
2
2
|
|
|
3
3
|
(function (factory) {
|
|
4
4
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
@@ -473,6 +473,7 @@
|
|
|
473
473
|
var ShimDOMException$1 = typeof DOMException === 'undefined'
|
|
474
474
|
// Todo: Better polyfill (if even needed here)
|
|
475
475
|
/* eslint-disable no-shadow -- Polyfill */
|
|
476
|
+
/* c8 ignore start -- Only reachable when the global `DOMException` is absent, which it never is in this project's test environment (Node always provides it) */
|
|
476
477
|
// eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
|
|
477
478
|
?
|
|
478
479
|
/**
|
|
@@ -490,9 +491,10 @@
|
|
|
490
491
|
configurable: true
|
|
491
492
|
});
|
|
492
493
|
return err;
|
|
493
|
-
}
|
|
494
|
+
}
|
|
495
|
+
/* c8 ignore stop */ : DOMException;
|
|
494
496
|
|
|
495
|
-
/** @type {WeakMap<object,
|
|
497
|
+
/** @type {WeakMap<object, EventWithProps>} */
|
|
496
498
|
var ev = new WeakMap();
|
|
497
499
|
/** @type {WeakMap<object, EventWithProps>} */
|
|
498
500
|
var evCfg = new WeakMap();
|
|
@@ -538,11 +540,12 @@
|
|
|
538
540
|
obj[prop] = {
|
|
539
541
|
configurable: true,
|
|
540
542
|
get: function get() {
|
|
541
|
-
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
543
|
+
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
544
|
+
/* c8 ignore next -- Every prop this is ever called with ('type'/'bubbles'/'cancelable'/'timeStamp'/'composed'/'detail') always ends up set on `_evCfg` or `_ev` by the time it's read, so this is unreachable */ : undefined;
|
|
542
545
|
}
|
|
543
546
|
};
|
|
544
547
|
return obj;
|
|
545
|
-
}, /** @type {
|
|
548
|
+
}, /** @type {PropertyDescriptorMap} */{}));
|
|
546
549
|
}
|
|
547
550
|
|
|
548
551
|
/**
|
|
@@ -565,8 +568,9 @@
|
|
|
565
568
|
throw new TypeError('Illegal invocation');
|
|
566
569
|
}
|
|
567
570
|
var _evCfg = getEvCfg(this);
|
|
568
|
-
var _ev = ev.get(this);
|
|
569
|
-
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
571
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
572
|
+
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
573
|
+
/* c8 ignore next -- Nothing currently sets `_evCfg.isTrusted` (see the commented-out assignment above); kept for when/if it's revived */ ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
|
|
570
574
|
}
|
|
571
575
|
|
|
572
576
|
/**
|
|
@@ -717,15 +721,15 @@
|
|
|
717
721
|
// this untyped alias, rather than `ShimEvent.prototype` directly, keeps
|
|
718
722
|
// that dynamic-augmentation pattern working without a `@ts-expect-error`
|
|
719
723
|
// on every single line below.
|
|
720
|
-
|
|
721
|
-
var ShimEventProto = ShimEvent.prototype;
|
|
724
|
+
|
|
725
|
+
var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
|
|
722
726
|
|
|
723
727
|
/** @this {EventWithProps} */
|
|
724
728
|
ShimEventProto.preventDefault = function preventDefault() {
|
|
725
729
|
if (!(this instanceof ShimEvent)) {
|
|
726
730
|
throw new TypeError('Illegal invocation');
|
|
727
731
|
}
|
|
728
|
-
var _ev = ev.get(this);
|
|
732
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
729
733
|
var _evCfg = getEvCfg(this);
|
|
730
734
|
if (this.cancelable && !_evCfg._passive) {
|
|
731
735
|
_evCfg.defaultPrevented = true;
|
|
@@ -923,13 +927,12 @@
|
|
|
923
927
|
return _createClass(CustomEvent);
|
|
924
928
|
}(Event);
|
|
925
929
|
var ShimCustomEvent = CustomEvent;
|
|
926
|
-
/** @type {
|
|
927
|
-
var ShimCustomEventProto = ShimCustomEvent.prototype;
|
|
930
|
+
var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
|
|
928
931
|
/**
|
|
929
932
|
* @param {string} type
|
|
930
933
|
* @param {boolean} [bubbles]
|
|
931
934
|
* @param {boolean} [cancelable]
|
|
932
|
-
* @param {
|
|
935
|
+
* @param {unknown} [detail]
|
|
933
936
|
* @this {EventWithProps}
|
|
934
937
|
*/
|
|
935
938
|
ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
|
|
@@ -941,6 +944,10 @@
|
|
|
941
944
|
throw new TypeError('Illegal invocation');
|
|
942
945
|
}
|
|
943
946
|
var _evCfg = getEvCfg(this);
|
|
947
|
+
if (_evCfg._dispatched) {
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
|
|
944
951
|
// @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
|
|
945
952
|
// eslint-disable-next-line prefer-rest-params -- Keep signature
|
|
946
953
|
initEventInternal(this, type, {
|
|
@@ -948,16 +955,13 @@
|
|
|
948
955
|
cancelable: cancelable,
|
|
949
956
|
detail: detail
|
|
950
957
|
}, arguments[4]);
|
|
951
|
-
if (_evCfg._dispatched) {
|
|
952
|
-
return;
|
|
953
|
-
}
|
|
954
958
|
if (detail !== undefined) {
|
|
955
959
|
_evCfg.detail = detail;
|
|
956
960
|
}
|
|
957
961
|
// `initCustomEvent` deliberately excluded -- see the matching comment
|
|
958
962
|
// in `initEventInternal` for `initEvent`, above; the same reasoning
|
|
959
963
|
// applies here.
|
|
960
|
-
definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
|
|
964
|
+
definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
|
|
961
965
|
};
|
|
962
966
|
// @ts-expect-error Not part of the class body itself
|
|
963
967
|
ShimCustomEvent[Symbol.toStringTag] = 'Function';
|
|
@@ -1364,7 +1368,7 @@
|
|
|
1364
1368
|
/** @type {string[]} */
|
|
1365
1369
|
this._extraProperties.forEach(function (prop) {
|
|
1366
1370
|
if (Reflect.has(e, prop)) {
|
|
1367
|
-
/** @type {
|
|
1371
|
+
/** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
|
|
1368
1372
|
}
|
|
1369
1373
|
});
|
|
1370
1374
|
}
|
|
@@ -1443,6 +1447,7 @@
|
|
|
1443
1447
|
if (child) {
|
|
1444
1448
|
child._defaultSync = this._defaultSync;
|
|
1445
1449
|
}
|
|
1450
|
+
/* c8 ignore next -- `cfg._children` always has exactly as many entries as remaining capturing-phase steps (built from the same walk that starts this phase), so `child` is never falsy here; the `|| this` fallback is defensive only */
|
|
1446
1451
|
return (child || this)._dispatchEvent(eventCopy, false);
|
|
1447
1452
|
}
|
|
1448
1453
|
case phases.AT_TARGET:
|
|
@@ -1740,7 +1745,7 @@
|
|
|
1740
1745
|
* databaseNameLengthLimit: number|false,
|
|
1741
1746
|
* escapeNFDForDatabaseNames: boolean,
|
|
1742
1747
|
* addSQLiteExtension: boolean,
|
|
1743
|
-
* memoryDatabase: string,
|
|
1748
|
+
* memoryDatabase: string|null|undefined,
|
|
1744
1749
|
* deleteDatabaseFiles: boolean,
|
|
1745
1750
|
* databaseBasePath: string,
|
|
1746
1751
|
* sysDatabaseBasePath: string,
|
|
@@ -1883,13 +1888,27 @@
|
|
|
1883
1888
|
// Various types of in-memory databases that can auto-delete
|
|
1884
1889
|
['memoryDatabase',
|
|
1885
1890
|
/**
|
|
1886
|
-
*
|
|
1891
|
+
* `null`/`undefined` are accepted (and left unvalidated against the
|
|
1892
|
+
* regex below) specifically so this can be reset back to its
|
|
1893
|
+
* unset/disabled state after being set: unlike other `CFG`
|
|
1894
|
+
* boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
|
|
1895
|
+
* with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
|
|
1896
|
+
* usage sites check `typeof CFG.memoryDatabase === 'string'`, so
|
|
1897
|
+
* even the empty string counts as "on" (it's a distinct, valid
|
|
1898
|
+
* in-memory mode of its own -- an unnamed private temporary
|
|
1899
|
+
* database -- not an "off" state). Without this, once set to any
|
|
1900
|
+
* string there would be no value passable back through this same
|
|
1901
|
+
* validator that turns `useMemoryDatabase` false again.
|
|
1902
|
+
* @param {string|null|undefined} val
|
|
1887
1903
|
* @throws {TypeError}
|
|
1888
1904
|
* @returns {void}
|
|
1889
1905
|
*/
|
|
1890
1906
|
function (val) {
|
|
1907
|
+
if (val === null || val === undefined) {
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1891
1910
|
if (!/^(?::memory:|file::memory:(\?(?:[\0-"\$-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?(#(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?)?$/.test(/** @type {string} */val)) {
|
|
1892
|
-
throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a
|
|
1911
|
+
throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
|
|
1893
1912
|
}
|
|
1894
1913
|
}],
|
|
1895
1914
|
// NODE-SPECIFIC CONFIG
|
|
@@ -1943,10 +1962,7 @@
|
|
|
1943
1962
|
return arg.replaceAll(/((?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])))(?!(?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|(^|(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))((?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g, function (_, unmatchedHighSurrogate, precedingLow, unmatchedLowSurrogate) {
|
|
1944
1963
|
// Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
|
|
1945
1964
|
// but Chrome having problems
|
|
1946
|
-
|
|
1947
|
-
return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1948
|
-
}
|
|
1949
|
-
return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1965
|
+
return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1950
1966
|
});
|
|
1951
1967
|
}
|
|
1952
1968
|
|
|
@@ -2613,7 +2629,8 @@
|
|
|
2613
2629
|
function createNativeDOMException(name, message) {
|
|
2614
2630
|
// @ts-expect-error It's ok
|
|
2615
2631
|
// eslint-disable-next-line new-cap -- Ok
|
|
2616
|
-
return new DOMException.prototype.constructor(message,
|
|
2632
|
+
return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
|
|
2633
|
+
name || 'DOMException');
|
|
2617
2634
|
}
|
|
2618
2635
|
|
|
2619
2636
|
// From web-platform-tests testharness.js name_code_map (though not in new spec)
|
|
@@ -2777,8 +2794,10 @@
|
|
|
2777
2794
|
*/
|
|
2778
2795
|
get: function get() {
|
|
2779
2796
|
if (!(this instanceof DOMException ||
|
|
2797
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2780
2798
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2781
2799
|
this instanceof DummyDOMException ||
|
|
2800
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2782
2801
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2783
2802
|
this instanceof Error)) {
|
|
2784
2803
|
throw new TypeError('Illegal invocation');
|
|
@@ -2837,6 +2856,7 @@
|
|
|
2837
2856
|
value: DOMException
|
|
2838
2857
|
});
|
|
2839
2858
|
|
|
2859
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2840
2860
|
// @ts-ignore We don't need all its properties; needed under some TS versions
|
|
2841
2861
|
return DOMException;
|
|
2842
2862
|
}
|
|
@@ -2849,6 +2869,7 @@
|
|
|
2849
2869
|
* @returns {Error}
|
|
2850
2870
|
*/
|
|
2851
2871
|
function createNonNativeDOMException(name, message) {
|
|
2872
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2852
2873
|
// @ts-ignore It's ok; needed under some TS versions
|
|
2853
2874
|
return new ShimNonNativeDOMException(message, name);
|
|
2854
2875
|
}
|
|
@@ -2871,6 +2892,8 @@
|
|
|
2871
2892
|
return;
|
|
2872
2893
|
}
|
|
2873
2894
|
var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
|
|
2895
|
+
|
|
2896
|
+
/* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
|
|
2874
2897
|
var method = typeof console.error === 'function' ? 'error' : 'log';
|
|
2875
2898
|
console[method](name + ': ' + message + '. ' + (msg || ''));
|
|
2876
2899
|
if (console.trace) {
|
|
@@ -3056,8 +3079,10 @@
|
|
|
3056
3079
|
*/
|
|
3057
3080
|
IDBRequest.__super = function IDBRequest() {
|
|
3058
3081
|
var _this = this;
|
|
3082
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3059
3083
|
// @ts-ignore It's ok
|
|
3060
3084
|
this[Symbol.toStringTag] = 'IDBRequest';
|
|
3085
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3061
3086
|
// @ts-ignore Part of `ShimEventTarget`
|
|
3062
3087
|
this.__setOptions({
|
|
3063
3088
|
legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
|
|
@@ -3115,10 +3140,7 @@
|
|
|
3115
3140
|
* @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
|
|
3116
3141
|
*/
|
|
3117
3142
|
IDBRequest.prototype.__getParent = function () {
|
|
3118
|
-
|
|
3119
|
-
return null;
|
|
3120
|
-
}
|
|
3121
|
-
return this.__transaction;
|
|
3143
|
+
return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
|
|
3122
3144
|
};
|
|
3123
3145
|
|
|
3124
3146
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
@@ -3177,8 +3199,10 @@
|
|
|
3177
3199
|
function IDBOpenDBRequest() {
|
|
3178
3200
|
IDBRequest.__super.call(this);
|
|
3179
3201
|
|
|
3202
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3180
3203
|
// @ts-ignore It's ok
|
|
3181
3204
|
this[Symbol.toStringTag] = 'IDBOpenDBRequest';
|
|
3205
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3182
3206
|
// @ts-ignore It's ok
|
|
3183
3207
|
this.__setOptions({
|
|
3184
3208
|
legacyOutputDidListenersThrowFlag: true,
|
|
@@ -4048,6 +4072,33 @@
|
|
|
4048
4072
|
return convertValueToKeyValueDecoded(input, null, true, true);
|
|
4049
4073
|
}
|
|
4050
4074
|
|
|
4075
|
+
/**
|
|
4076
|
+
* @param {BufferSource|ArrayBufferLike} buffer
|
|
4077
|
+
* @returns {boolean}
|
|
4078
|
+
*/
|
|
4079
|
+
function isBufferDetached(buffer) {
|
|
4080
|
+
// Use the standard property if available
|
|
4081
|
+
// @ts-expect-error - More recent API
|
|
4082
|
+
if (typeof buffer.detached === 'boolean') {
|
|
4083
|
+
// @ts-expect-error - More recent API
|
|
4084
|
+
return buffer.detached;
|
|
4085
|
+
}
|
|
4086
|
+
/* c8 ignore next 14 -- Older browsers */
|
|
4087
|
+
|
|
4088
|
+
// Fallback check via byteLength and constructor test
|
|
4089
|
+
if (buffer.byteLength !== 0) {
|
|
4090
|
+
return false;
|
|
4091
|
+
}
|
|
4092
|
+
try {
|
|
4093
|
+
// @ts-expect-error Ok
|
|
4094
|
+
// eslint-disable-next-line no-new -- Throwaway
|
|
4095
|
+
new Uint8Array(buffer);
|
|
4096
|
+
return false;
|
|
4097
|
+
} catch (_unused) {
|
|
4098
|
+
return true;
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
|
|
4051
4102
|
/**
|
|
4052
4103
|
*
|
|
4053
4104
|
* @param {BufferSource} O
|
|
@@ -4060,15 +4111,16 @@
|
|
|
4060
4111
|
var length;
|
|
4061
4112
|
if (ArrayBuffer.isView(O)) {
|
|
4062
4113
|
// Has [[ViewedArrayBuffer]] internal slot
|
|
4063
|
-
var arrayBuffer = O.buffer;
|
|
4064
|
-
if (arrayBuffer === undefined) {
|
|
4065
|
-
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was undefined.');
|
|
4066
|
-
}
|
|
4067
4114
|
offset = O.byteOffset; // [[ByteOffset]] (will also throw as desired if detached)
|
|
4068
4115
|
length = O.byteLength; // [[ByteLength]] (will also throw as desired if detached)
|
|
4069
4116
|
} else {
|
|
4070
4117
|
length = O.byteLength; // [[ArrayBufferByteLength]] on ArrayBuffer (will also throw as desired if detached)
|
|
4071
4118
|
}
|
|
4119
|
+
var arrayBuffer = ArrayBuffer.isView(O) ? O.buffer : O;
|
|
4120
|
+
if (isBufferDetached(arrayBuffer)) {
|
|
4121
|
+
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was detached.');
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4072
4124
|
// const octets = new Uint8Array(input);
|
|
4073
4125
|
// const octets = types.binary.decode(types.binary.encode(input));
|
|
4074
4126
|
return new Uint8Array(
|
|
@@ -4140,7 +4192,7 @@
|
|
|
4140
4192
|
var octets;
|
|
4141
4193
|
try {
|
|
4142
4194
|
octets = getCopyBytesHeldByBufferSource(/** @type {BufferSource} */input);
|
|
4143
|
-
} catch (
|
|
4195
|
+
} catch (_unused2) {
|
|
4144
4196
|
return {
|
|
4145
4197
|
type: type,
|
|
4146
4198
|
invalid: true,
|
|
@@ -4189,8 +4241,14 @@
|
|
|
4189
4241
|
}
|
|
4190
4242
|
if (!multiEntry || !fullKeys && keys.every(function (k) {
|
|
4191
4243
|
return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
|
|
4192
|
-
}) ||
|
|
4193
|
-
|
|
4244
|
+
}) ||
|
|
4245
|
+
// `keys` holds full `{type, value}` objects here (see
|
|
4246
|
+
// `safePush` below), so -- like the sibling branch
|
|
4247
|
+
// above -- `cmp` (which expects raw `Value`s, not
|
|
4248
|
+
// decoded key objects) must compare their `.value`s,
|
|
4249
|
+
// not the wrapper objects themselves.
|
|
4250
|
+
fullKeys && keys.every(function (k) {
|
|
4251
|
+
return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
|
|
4194
4252
|
})) {
|
|
4195
4253
|
safePush(keys, fullKeys ? key : key.value);
|
|
4196
4254
|
}
|
|
@@ -4215,12 +4273,9 @@
|
|
|
4215
4273
|
{
|
|
4216
4274
|
var date = /** @type {Date} */input;
|
|
4217
4275
|
if (!Number.isNaN(date.getTime())) {
|
|
4218
|
-
return
|
|
4219
|
-
type: type,
|
|
4220
|
-
value: date.getTime()
|
|
4221
|
-
} : {
|
|
4276
|
+
return {
|
|
4222
4277
|
type: type,
|
|
4223
|
-
value: new Date(date)
|
|
4278
|
+
value: fullKeys ? date.getTime() : new Date(date)
|
|
4224
4279
|
};
|
|
4225
4280
|
}
|
|
4226
4281
|
return {
|
|
@@ -4308,10 +4363,7 @@
|
|
|
4308
4363
|
if (r.failure) {
|
|
4309
4364
|
return r;
|
|
4310
4365
|
}
|
|
4311
|
-
|
|
4312
|
-
return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
|
|
4313
|
-
}
|
|
4314
|
-
return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4366
|
+
return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4315
4367
|
}
|
|
4316
4368
|
|
|
4317
4369
|
/**
|
|
@@ -4492,10 +4544,7 @@
|
|
|
4492
4544
|
*/
|
|
4493
4545
|
function isMultiEntryMatch(encodedEntry, encodedKey) {
|
|
4494
4546
|
var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
|
|
4495
|
-
|
|
4496
|
-
return encodedKey.indexOf(encodedEntry) > 1;
|
|
4497
|
-
}
|
|
4498
|
-
return encodedKey === encodedEntry;
|
|
4547
|
+
return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
|
|
4499
4548
|
}
|
|
4500
4549
|
|
|
4501
4550
|
/**
|
|
@@ -4613,10 +4662,7 @@
|
|
|
4613
4662
|
* @returns {undefined|ValueType}
|
|
4614
4663
|
*/
|
|
4615
4664
|
function _decode(key, inArray) {
|
|
4616
|
-
|
|
4617
|
-
return undefined;
|
|
4618
|
-
}
|
|
4619
|
-
return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4665
|
+
return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4620
4666
|
}
|
|
4621
4667
|
|
|
4622
4668
|
/**
|
|
@@ -5022,10 +5068,11 @@
|
|
|
5022
5068
|
if (hasLower && hasUpper) {
|
|
5023
5069
|
sql.push('AND');
|
|
5024
5070
|
}
|
|
5025
|
-
if (hasUpper) {
|
|
5026
|
-
|
|
5027
|
-
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5071
|
+
if (!hasUpper) {
|
|
5072
|
+
return;
|
|
5028
5073
|
}
|
|
5074
|
+
sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
|
|
5075
|
+
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5029
5076
|
}
|
|
5030
5077
|
|
|
5031
5078
|
/**
|
|
@@ -5038,10 +5085,7 @@
|
|
|
5038
5085
|
if (instanceOf(value, IDBKeyRange)) {
|
|
5039
5086
|
// We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
|
|
5040
5087
|
var range = /** @type {IDBKeyRangeFull} */value;
|
|
5041
|
-
|
|
5042
|
-
return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
|
|
5043
|
-
}
|
|
5044
|
-
return range;
|
|
5088
|
+
return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
|
|
5045
5089
|
}
|
|
5046
5090
|
if (isNullish(value)) {
|
|
5047
5091
|
if (nullDisallowed) {
|
|
@@ -5086,9 +5130,11 @@
|
|
|
5086
5130
|
if (testObject.test) {
|
|
5087
5131
|
cleanInterface = true;
|
|
5088
5132
|
}
|
|
5133
|
+
/* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5089
5134
|
} catch (err) {
|
|
5090
5135
|
// Object.defineProperty does not work as intended.
|
|
5091
5136
|
}
|
|
5137
|
+
/* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5092
5138
|
}
|
|
5093
5139
|
|
|
5094
5140
|
/**
|
|
@@ -5289,6 +5335,7 @@
|
|
|
5289
5335
|
this._length = 0;
|
|
5290
5336
|
};
|
|
5291
5337
|
DOMStringList.prototype = DOMStringListAlias.prototype;
|
|
5338
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
5292
5339
|
// @ts-ignore It's ok; needed under some TS versions
|
|
5293
5340
|
return /** @type {DOMStringListFull} */new DOMStringList();
|
|
5294
5341
|
}
|
|
@@ -5588,12 +5635,14 @@
|
|
|
5588
5635
|
*/
|
|
5589
5636
|
IDBTransaction.prototype.__executeRequests = function () {
|
|
5590
5637
|
var me = this;
|
|
5638
|
+
/* c8 ignore start -- Dead code: `__executeRequests` has exactly one caller (a single `setTimeout` scheduled once per transaction), so `me.__running` can never already be `true` when this function starts. */
|
|
5591
5639
|
if (me.__running) {
|
|
5592
5640
|
if (CFG.DEBUG) {
|
|
5593
5641
|
console.log('Looks like the request set is already running', me.mode);
|
|
5594
5642
|
}
|
|
5595
5643
|
return;
|
|
5596
5644
|
}
|
|
5645
|
+
/* c8 ignore stop -- see comment above */
|
|
5597
5646
|
|
|
5598
5647
|
// The synchronous script that created this transaction (and
|
|
5599
5648
|
// synchronously queued whatever requests it wanted to) has now
|
|
@@ -5643,6 +5692,7 @@
|
|
|
5643
5692
|
queueMicrotask(cb);
|
|
5644
5693
|
return;
|
|
5645
5694
|
}
|
|
5695
|
+
/* c8 ignore start -- Browser-only path: in every automated test environment (Node's websql-configurable/better-sqlite3 driver, and the fake/mock drivers modeled after it) `__usesStandardDriver()` is always `false` (they support the 4-arg `nonstandardTransCb` signature), so `isStandardDriver` is never `true` and this branch is never reached. Only a real standard (3-arg) WebSQL driver, as found in an actual browser, would exercise it. */
|
|
5646
5696
|
try {
|
|
5647
5697
|
tx.executeSql('SELECT 1', [], function () {
|
|
5648
5698
|
cb();
|
|
@@ -5656,6 +5706,7 @@
|
|
|
5656
5706
|
// abort the transaction here.
|
|
5657
5707
|
me.__abortTransaction(/** @type {Error|DOMException} */err);
|
|
5658
5708
|
}
|
|
5709
|
+
/* c8 ignore stop -- see comment above */
|
|
5659
5710
|
}
|
|
5660
5711
|
|
|
5661
5712
|
/**
|
|
@@ -5668,21 +5719,26 @@
|
|
|
5668
5719
|
* @returns {void}
|
|
5669
5720
|
*/
|
|
5670
5721
|
function success(result, req) {
|
|
5722
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path (e.g. a driver-level failure or explicit `abort()`) racing with this request's own in-flight SQL success callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
|
|
5671
5723
|
if (me.__errored || me.__requestsFinished) {
|
|
5672
5724
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5673
5725
|
return;
|
|
5674
5726
|
}
|
|
5727
|
+
/* c8 ignore stop -- see comment above */
|
|
5675
5728
|
if (req) {
|
|
5676
5729
|
q.req = req; // Need to do this in case of cursors
|
|
5677
5730
|
}
|
|
5731
|
+
/* c8 ignore start -- Dead code: `launchQueuedOp` only ever passes `success` as a callback in the branch where `q.req` is already truthy, and a falsy `req` param here leaves `q.req` unchanged, so `q.req` can't be falsy at this point. */
|
|
5678
5732
|
if (!q.req) {
|
|
5679
|
-
// TS guard
|
|
5680
5733
|
return;
|
|
5681
5734
|
}
|
|
5735
|
+
/* c8 ignore stop -- see comment above */
|
|
5736
|
+
/* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's success callback more than once for the same queued op; not reliably reproducible without directly manipulating the SQL driver. */
|
|
5682
5737
|
if (q.req.__done) {
|
|
5683
5738
|
// Avoid continuing with aborted requests
|
|
5684
5739
|
return;
|
|
5685
5740
|
}
|
|
5741
|
+
/* c8 ignore stop -- see comment above */
|
|
5686
5742
|
q.req.__done = true;
|
|
5687
5743
|
q.req.__result = result;
|
|
5688
5744
|
q.req.__error = null;
|
|
@@ -5699,6 +5755,7 @@
|
|
|
5699
5755
|
// is what actually resets `__handlerActive`, once it's
|
|
5700
5756
|
// confirmed (across its own bounded microtask wait) that no
|
|
5701
5757
|
// such continuation queued anything.
|
|
5758
|
+
/* c8 ignore start -- Deliberately not tested: throwing from a request's `onsuccess` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
|
|
5702
5759
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
5703
5760
|
logError('Error', 'An error occurred in a success handler attached to request chain', e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
|
|
5704
5761
|
if (!me.__committed) {
|
|
@@ -5708,6 +5765,7 @@
|
|
|
5708
5765
|
return;
|
|
5709
5766
|
}
|
|
5710
5767
|
}
|
|
5768
|
+
/* c8 ignore stop -- see comment above */
|
|
5711
5769
|
runContinuationSafely(advanceAfterDispatch);
|
|
5712
5770
|
}
|
|
5713
5771
|
|
|
@@ -5719,15 +5777,19 @@
|
|
|
5719
5777
|
* @returns {void}
|
|
5720
5778
|
*/
|
|
5721
5779
|
function error() {
|
|
5780
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this request's own in-flight SQL error callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
|
|
5722
5781
|
if (me.__errored || me.__requestsFinished) {
|
|
5723
5782
|
// We've already called "onerror", "onabort", or thrown within
|
|
5724
5783
|
// the transaction, so don't do it again.
|
|
5725
5784
|
return;
|
|
5726
5785
|
}
|
|
5786
|
+
/* c8 ignore stop -- see comment above */
|
|
5787
|
+
/* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's error callback more than once, or after its success callback already ran; not reliably reproducible without directly manipulating the SQL driver. */
|
|
5727
5788
|
if (q.req && q.req.__done) {
|
|
5728
5789
|
// Avoid continuing with aborted requests
|
|
5729
5790
|
return;
|
|
5730
5791
|
}
|
|
5792
|
+
/* c8 ignore stop -- see comment above */
|
|
5731
5793
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
5732
5794
|
args[_key] = arguments[_key];
|
|
5733
5795
|
}
|
|
@@ -5752,10 +5814,11 @@
|
|
|
5752
5814
|
}
|
|
5753
5815
|
});
|
|
5754
5816
|
q.req.addDefaultEventListener('error', function () {
|
|
5817
|
+
/* c8 ignore start -- Defensive: this default listener is skipped entirely by `eventtargeter` whenever the event was `preventDefault()`-ed (the only case in which the shared `q` variable above could have already advanced to a different, non-request queue entry by the time a default listener runs); not reachable via the public API under normal (synchronous) dispatch. */
|
|
5755
5818
|
if (!q.req) {
|
|
5756
|
-
// TS guard
|
|
5757
5819
|
return;
|
|
5758
5820
|
}
|
|
5821
|
+
/* c8 ignore stop -- see comment above */
|
|
5759
5822
|
me.__abortTransaction(q.req.__error);
|
|
5760
5823
|
});
|
|
5761
5824
|
me.__active = true;
|
|
@@ -5767,16 +5830,19 @@
|
|
|
5767
5830
|
q.req.dispatchEvent(e);
|
|
5768
5831
|
// Do not set __active or __handlerActive flags to false yet --
|
|
5769
5832
|
// see the matching comment in `success`, above.
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5833
|
+
/* 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. */
|
|
5834
|
+
if (!e.__legacyOutputDidListenersThrowError) {
|
|
5835
|
+
return;
|
|
5836
|
+
}
|
|
5837
|
+
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
|
|
5838
|
+
e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
|
|
5839
|
+
if (me.__committed) {
|
|
5840
|
+
// An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
|
|
5841
|
+
runContinuationSafely(advanceAfterDispatch);
|
|
5842
|
+
return;
|
|
5779
5843
|
}
|
|
5844
|
+
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
|
|
5845
|
+
/* c8 ignore stop -- see comment above */
|
|
5780
5846
|
}
|
|
5781
5847
|
|
|
5782
5848
|
/**
|
|
@@ -5800,10 +5866,12 @@
|
|
|
5800
5866
|
// (not reset here).
|
|
5801
5867
|
return true;
|
|
5802
5868
|
}
|
|
5869
|
+
/* c8 ignore start -- Defensive: reaching this queue entry via the normal advancement path after it was independently marked `__done` (e.g. by `__abortTransaction`'s own separate, async per-request error dispatch) requires a narrow race between that async cleanup and this synchronous advancement; not reliably reproducible without directly manipulating that timing. */
|
|
5803
5870
|
if (q.req.__done) {
|
|
5804
5871
|
// Avoid continuing with aborted requests
|
|
5805
5872
|
return false;
|
|
5806
5873
|
}
|
|
5874
|
+
/* c8 ignore stop -- see comment above */
|
|
5807
5875
|
// We're now handing off to (possibly async) work for
|
|
5808
5876
|
// this request, so the transaction is no longer active
|
|
5809
5877
|
// until its own `success`/`error` dispatch (below)
|
|
@@ -5828,18 +5896,22 @@
|
|
|
5828
5896
|
return;
|
|
5829
5897
|
}
|
|
5830
5898
|
q.op(tx, q.args, success, error, executeNextRequest);
|
|
5899
|
+
/* c8 ignore start -- Defensive: `q.op` (the SQL driver callback) is expected to report failures via its own `error`/`failure` callback argument rather than throwing synchronously; not reliably reproducible without directly forcing the driver to throw. */
|
|
5831
5900
|
} catch (e) {
|
|
5832
5901
|
error(/** @type {Error} */e);
|
|
5833
5902
|
}
|
|
5903
|
+
/* c8 ignore stop -- see comment above */
|
|
5834
5904
|
}
|
|
5835
5905
|
|
|
5836
5906
|
/**
|
|
5837
5907
|
* @returns {void}
|
|
5838
5908
|
*/
|
|
5839
5909
|
function runQueuedRequest() {
|
|
5910
|
+
/* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
|
|
5840
5911
|
if (!prepareNextRequest()) {
|
|
5841
5912
|
return;
|
|
5842
5913
|
}
|
|
5914
|
+
/* c8 ignore stop -- see comment above */
|
|
5843
5915
|
launchQueuedOp();
|
|
5844
5916
|
}
|
|
5845
5917
|
|
|
@@ -5870,9 +5942,11 @@
|
|
|
5870
5942
|
* @returns {void}
|
|
5871
5943
|
*/
|
|
5872
5944
|
function checkQueueEntry(attemptsLeft) {
|
|
5945
|
+
/* c8 ignore start -- Defensive: only reached if the transaction is independently errored/finished (e.g. an explicit `abort()`) during this function's keep-alive polling wait; not reliably reproducible without a contrived timing race. */
|
|
5873
5946
|
if (me.__errored || me.__requestsFinished) {
|
|
5874
5947
|
return;
|
|
5875
5948
|
}
|
|
5949
|
+
/* c8 ignore stop -- see comment above */
|
|
5876
5950
|
if (i < me.__requests.length) {
|
|
5877
5951
|
runQueuedRequest();
|
|
5878
5952
|
return;
|
|
@@ -5894,10 +5968,12 @@
|
|
|
5894
5968
|
* @returns {void}
|
|
5895
5969
|
*/
|
|
5896
5970
|
function executeNextRequest() {
|
|
5971
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
|
|
5897
5972
|
if (me.__errored || me.__requestsFinished) {
|
|
5898
5973
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5899
5974
|
return;
|
|
5900
5975
|
}
|
|
5976
|
+
/* c8 ignore stop -- see comment above */
|
|
5901
5977
|
i++;
|
|
5902
5978
|
if (i >= me.__requests.length) {
|
|
5903
5979
|
checkQueueEntry(keepAliveAttempts);
|
|
@@ -5932,31 +6008,34 @@
|
|
|
5932
6008
|
* @returns {void}
|
|
5933
6009
|
*/
|
|
5934
6010
|
function advanceAfterDispatch() {
|
|
6011
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
|
|
5935
6012
|
if (me.__errored || me.__requestsFinished) {
|
|
5936
6013
|
return;
|
|
5937
6014
|
}
|
|
6015
|
+
/* c8 ignore stop -- see comment above */
|
|
5938
6016
|
i++;
|
|
5939
6017
|
if (i >= me.__requests.length) {
|
|
5940
6018
|
checkQueueEntry(keepAliveAttempts);
|
|
5941
6019
|
return;
|
|
5942
6020
|
}
|
|
5943
6021
|
keepAliveAndWait(function () {
|
|
5944
|
-
if (
|
|
5945
|
-
|
|
5946
|
-
}
|
|
5947
|
-
if (!prepareNextRequest()) {
|
|
6022
|
+
/* 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. */
|
|
6023
|
+
if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
|
|
5948
6024
|
return;
|
|
5949
6025
|
}
|
|
6026
|
+
/* c8 ignore stop -- see comment above */
|
|
5950
6027
|
launchQueuedOp();
|
|
5951
6028
|
});
|
|
5952
6029
|
}
|
|
5953
6030
|
executeNextRequest();
|
|
5954
6031
|
}, function webSQLError(webSQLErr) {
|
|
6032
|
+
/* c8 ignore start -- Dead code: the underlying websql-configurable driver's `_onTransactionComplete` always passes either `null` or a genuine `Error`/`DOMException` as this callback's argument, never the literal value `true`, under any driver used by the test suite. */
|
|
5955
6033
|
// @ts-expect-error It's ok
|
|
5956
6034
|
if (webSQLErr === true) {
|
|
5957
6035
|
// Not a genuine SQL error
|
|
5958
6036
|
return;
|
|
5959
6037
|
}
|
|
6038
|
+
/* c8 ignore stop -- see comment above */
|
|
5960
6039
|
var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
|
|
5961
6040
|
me.__abortTransaction(err);
|
|
5962
6041
|
}, function () {
|
|
@@ -5967,18 +6046,25 @@
|
|
|
5967
6046
|
// Node
|
|
5968
6047
|
return;
|
|
5969
6048
|
}
|
|
6049
|
+
/* c8 ignore start -- Defensive: reaching this callback before `requestsFinished` has already set `__transactionEndCallback` (or finished) would require the underlying driver's own "queue empty" signal to race ahead of this codebase's own request-completion tracking; not observed (nor reliably reproducible) in this test suite, where the latter always wins. */
|
|
5970
6050
|
if (!me.__transactionEndCallback && !me.__requestsFinished) {
|
|
5971
6051
|
me.__transactionFinished = true;
|
|
5972
6052
|
return;
|
|
5973
6053
|
}
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
6054
|
+
/* c8 ignore stop -- see comment above */
|
|
6055
|
+
/* 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. */
|
|
6056
|
+
if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
|
|
6057
|
+
return;
|
|
5977
6058
|
}
|
|
6059
|
+
me.__transFinishedCbFired = true;
|
|
6060
|
+
me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
|
|
6061
|
+
/* c8 ignore stop -- see comment above */
|
|
5978
6062
|
}, function (currentTask, err, done, rollback, commit) {
|
|
6063
|
+
/* c8 ignore start -- Defensive: `err` here would mean the underlying WebSQL/SQLite driver reported a genuine unhandled SQL error bubbling out of this transaction's own executed statements -- every `executeSql` error callback in this codebase already handles/reports its own errors (returning `false`), so this is not reliably reproducible without mocking the SQL layer. */
|
|
5979
6064
|
if (err) {
|
|
5980
6065
|
return true;
|
|
5981
6066
|
}
|
|
6067
|
+
/* c8 ignore stop -- see comment above */
|
|
5982
6068
|
// `readonly` transactions never hold a real SQL transaction open
|
|
5983
6069
|
// (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
|
|
5984
6070
|
// them), so there's no commit/rollback round trip to defer --
|
|
@@ -6027,6 +6113,7 @@
|
|
|
6027
6113
|
*/
|
|
6028
6114
|
function complete() {
|
|
6029
6115
|
me.__completed = true;
|
|
6116
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6030
6117
|
if (CFG.DEBUG) {
|
|
6031
6118
|
console.log('Transaction completed');
|
|
6032
6119
|
}
|
|
@@ -6036,6 +6123,7 @@
|
|
|
6036
6123
|
me.dispatchEvent(evt);
|
|
6037
6124
|
me.__internal = false;
|
|
6038
6125
|
me.dispatchEvent(createEvent('__complete'));
|
|
6126
|
+
/* c8 ignore start -- Deliberately not tested: throwing from an `oncomplete`/`__complete` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
|
|
6039
6127
|
} catch (e) {
|
|
6040
6128
|
me.__internal = false;
|
|
6041
6129
|
// An error occurred in the "oncomplete" handler.
|
|
@@ -6043,6 +6131,7 @@
|
|
|
6043
6131
|
// (this may seem odd/bad, but it's how all native IndexedDB implementations work)
|
|
6044
6132
|
me.__errored = true;
|
|
6045
6133
|
throw e;
|
|
6134
|
+
/* c8 ignore stop -- see comment above */
|
|
6046
6135
|
} finally {
|
|
6047
6136
|
activeTransactions.delete(me);
|
|
6048
6137
|
me.__storeHandles = {};
|
|
@@ -6050,10 +6139,12 @@
|
|
|
6050
6139
|
}
|
|
6051
6140
|
}
|
|
6052
6141
|
if (me.mode === 'readwrite' || me.mode === 'readonly') {
|
|
6142
|
+
/* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described above (also `c8 ignore`d there), which is not observed in this test suite. */
|
|
6053
6143
|
if (me.__transactionFinished) {
|
|
6054
6144
|
complete();
|
|
6055
6145
|
return;
|
|
6056
6146
|
}
|
|
6147
|
+
/* c8 ignore stop -- see comment above */
|
|
6057
6148
|
me.__transactionEndCallback = complete;
|
|
6058
6149
|
// The underlying SQL driver's own "queue empty" check
|
|
6059
6150
|
// (`nonstandardTransCb`, above) typically already ran and
|
|
@@ -6089,6 +6180,7 @@
|
|
|
6089
6180
|
IDBTransaction.prototype.__createRequest = function (source) {
|
|
6090
6181
|
var me = this;
|
|
6091
6182
|
var request = IDBRequest.__createInstance();
|
|
6183
|
+
/* c8 ignore next -- Defensive: every call site (via `__addToTransactionQueue` or directly) always passes an explicit `source`, so the `me.db` fallback is not reachable via the public API. */
|
|
6092
6184
|
request.__source = source !== undefined ? source : me.db;
|
|
6093
6185
|
request.__transaction = me;
|
|
6094
6186
|
return request;
|
|
@@ -6158,9 +6250,11 @@
|
|
|
6158
6250
|
* @returns {void}
|
|
6159
6251
|
*/
|
|
6160
6252
|
IDBTransaction.prototype.__assertActive = function () {
|
|
6253
|
+
/* c8 ignore start -- Defensive: every call site (via `__addToTransactionQueue`/`__addNonRequestToTransactionQueue`) either already performed the static `IDBTransaction.__assertActive(tx)` check synchronously just beforehand, or queues against a transaction just created fresh (necessarily active), so this redundant instance-level check is not reachable via the public API. */
|
|
6161
6254
|
if (!this.__active || !this.__handlerActive || this.__committed) {
|
|
6162
6255
|
throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
|
|
6163
6256
|
}
|
|
6257
|
+
/* c8 ignore stop -- see comment above */
|
|
6164
6258
|
};
|
|
6165
6259
|
|
|
6166
6260
|
/**
|
|
@@ -6174,6 +6268,7 @@
|
|
|
6174
6268
|
}
|
|
6175
6269
|
};
|
|
6176
6270
|
|
|
6271
|
+
/* c8 ignore start -- Dead code: this instance method has no callers anywhere in src/ (confirmed via grep); every real call site uses the static `IDBTransaction.__assertVersionChange(tx)` directly instead. */
|
|
6177
6272
|
/**
|
|
6178
6273
|
* @this {IDBTransactionFull}
|
|
6179
6274
|
* @returns {void}
|
|
@@ -6181,6 +6276,7 @@
|
|
|
6181
6276
|
IDBTransaction.prototype.__assertVersionChange = function () {
|
|
6182
6277
|
IDBTransaction.__assertVersionChange(this);
|
|
6183
6278
|
};
|
|
6279
|
+
/* c8 ignore stop -- see comment above */
|
|
6184
6280
|
|
|
6185
6281
|
/**
|
|
6186
6282
|
* Returns the specified object store.
|
|
@@ -6202,9 +6298,12 @@
|
|
|
6202
6298
|
throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
|
|
6203
6299
|
}
|
|
6204
6300
|
var store = me.db.__objectStores[objectStoreName];
|
|
6301
|
+
/* c8 ignore start -- Defensive: `me.__objectStoreNames` (checked just above) and `me.db.__objectStores` are always kept in sync by every code path that adds/renames/removes a store, so a name that passes the participation check above should always also be found here; not reliably reproducible via the public API. */
|
|
6205
6302
|
if (!store) {
|
|
6206
6303
|
throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
|
|
6207
6304
|
}
|
|
6305
|
+
/* c8 ignore stop -- see comment above */
|
|
6306
|
+
|
|
6208
6307
|
if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
|
|
6209
6308
|
// These latter conditions are to allow store
|
|
6210
6309
|
// recreation to create new clone object
|
|
@@ -6223,10 +6322,12 @@
|
|
|
6223
6322
|
IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
6224
6323
|
var me = this;
|
|
6225
6324
|
logError('Error', 'An error occurred in a transaction', err);
|
|
6325
|
+
/* c8 ignore start -- Defensive re-entrancy guard: only reached if `__abortTransaction` is invoked a second time on the same transaction after `__errored` is already `true` (e.g. two independent internal error paths racing); not reliably reproducible without a contrived timing race. */
|
|
6226
6326
|
if (me.__errored) {
|
|
6227
6327
|
// We've already called "onerror", "onabort", or thrown, so don't do it again.
|
|
6228
6328
|
return;
|
|
6229
6329
|
}
|
|
6330
|
+
/* c8 ignore stop -- see comment above */
|
|
6230
6331
|
me.__errored = true;
|
|
6231
6332
|
if (me.mode === 'versionchange') {
|
|
6232
6333
|
// Steps for aborting an upgrade transaction
|
|
@@ -6256,19 +6357,16 @@
|
|
|
6256
6357
|
if (err !== null) {
|
|
6257
6358
|
me.__error = err;
|
|
6258
6359
|
}
|
|
6360
|
+
|
|
6361
|
+
/* c8 ignore start -- Defense in depth: `err` is only ever `null` here via `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)` call, which now checks `__requestsFinished` itself first and throws `InvalidStateError` synchronously before ever reaching this point -- so this guard should not see a non-null `err` in practice. */
|
|
6259
6362
|
if (me.__requestsFinished && err !== null) {
|
|
6260
6363
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
6261
|
-
// So throw the error instead.
|
|
6262
|
-
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
6263
|
-
// call, which now checks `__requestsFinished` itself first and
|
|
6264
|
-
// throws `InvalidStateError` synchronously before ever reaching
|
|
6265
|
-
// this point -- so this guard is just defense in depth against
|
|
6266
|
-
// `err` somehow being `null` some other way, not something this
|
|
6267
|
-
// path should see in practice.
|
|
6364
|
+
// So throw the error instead.
|
|
6268
6365
|
setTimeout(function () {
|
|
6269
6366
|
throw err;
|
|
6270
6367
|
}, 0);
|
|
6271
6368
|
}
|
|
6369
|
+
/* c8 ignore stop -- see comment above */
|
|
6272
6370
|
|
|
6273
6371
|
/**
|
|
6274
6372
|
* @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
|
|
@@ -6277,13 +6375,17 @@
|
|
|
6277
6375
|
*/
|
|
6278
6376
|
function abort(tx, errOrResult) {
|
|
6279
6377
|
if (!tx) {
|
|
6378
|
+
/* c8 ignore next -- Debug-only log; only reached via the no-op `abort()` calls below (rare paths), and requires `CFG.DEBUG` to have any effect anyway. */
|
|
6280
6379
|
if (CFG.DEBUG) {
|
|
6281
6380
|
console.log('Rollback not possible due to missing transaction', me);
|
|
6282
6381
|
}
|
|
6382
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver erroring on the manual `ROLLBACK` executed below (with a result object exposing a numeric `code`) is not reliably reproducible without mocking the SQL layer. */
|
|
6283
6383
|
} else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
|
|
6284
6384
|
if (CFG.DEBUG) {
|
|
6285
6385
|
console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
|
|
6286
6386
|
}
|
|
6387
|
+
/* c8 ignore stop -- see comment above */
|
|
6388
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6287
6389
|
} else if (CFG.DEBUG) {
|
|
6288
6390
|
console.log('Rollback succeeded', me);
|
|
6289
6391
|
}
|
|
@@ -6299,10 +6401,11 @@
|
|
|
6299
6401
|
// behaves first-in-first-out with the same timeout so we could
|
|
6300
6402
|
// just use a `forEach`.
|
|
6301
6403
|
return promises.then(function () {
|
|
6404
|
+
/* c8 ignore start -- Dead code: the preceding `.filter()` only keeps entries with a truthy `q.req`, and nothing ever resets `q.req` back to a falsy value afterward, so this invariant can't actually be violated. */
|
|
6302
6405
|
if (!q.req) {
|
|
6303
|
-
// TS guard
|
|
6304
6406
|
throw new Error('Missing request');
|
|
6305
6407
|
}
|
|
6408
|
+
/* c8 ignore stop -- see comment above */
|
|
6306
6409
|
q.req.__done = true;
|
|
6307
6410
|
q.req.__result = undefined;
|
|
6308
6411
|
q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
|
|
@@ -6313,10 +6416,11 @@
|
|
|
6313
6416
|
return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
|
|
6314
6417
|
function (resolve) {
|
|
6315
6418
|
setTimeout(function () {
|
|
6419
|
+
/* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
|
|
6316
6420
|
if (!q.req) {
|
|
6317
|
-
// TS guard
|
|
6318
6421
|
throw new Error('Missing request');
|
|
6319
6422
|
}
|
|
6423
|
+
/* c8 ignore stop -- see comment above */
|
|
6320
6424
|
q.req.dispatchEvent(reqEvt); // No need to catch errors
|
|
6321
6425
|
resolve();
|
|
6322
6426
|
}, 0);
|
|
@@ -6336,10 +6440,12 @@
|
|
|
6336
6440
|
releaseFinishedTransaction(me);
|
|
6337
6441
|
}, 0);
|
|
6338
6442
|
return undefined;
|
|
6443
|
+
/* c8 ignore start -- Diagnostic safety net: nothing in the preceding promise chain normally rejects (the only throws it could catch are the dead invariant-violation checks above), so this handler is not reachable in practice. */
|
|
6339
6444
|
}).catch(function (err) {
|
|
6340
6445
|
console.log('Abort error');
|
|
6341
6446
|
throw err;
|
|
6342
6447
|
});
|
|
6448
|
+
/* c8 ignore stop -- see comment above */
|
|
6343
6449
|
}
|
|
6344
6450
|
me.__transFinishedCb(true, function (rollback) {
|
|
6345
6451
|
if (rollback && me.__tx) {
|
|
@@ -6347,20 +6453,24 @@
|
|
|
6347
6453
|
// rollback automatically), but for Node.js, etc., we give chance for
|
|
6348
6454
|
// manual aborts which would otherwise not work.
|
|
6349
6455
|
if (me.mode === 'readwrite') {
|
|
6456
|
+
/* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described earlier in this file (also `c8 ignore`d there), which is not observed in this test suite. */
|
|
6350
6457
|
if (me.__transactionFinished) {
|
|
6351
6458
|
abort();
|
|
6352
6459
|
return;
|
|
6353
6460
|
}
|
|
6461
|
+
/* c8 ignore stop -- see comment above */
|
|
6354
6462
|
me.__transactionEndCallback = abort;
|
|
6355
6463
|
return;
|
|
6356
6464
|
}
|
|
6357
6465
|
try {
|
|
6358
6466
|
me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
|
|
6467
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
|
|
6359
6468
|
} catch (err) {
|
|
6360
6469
|
// Browser errs when transaction has ended and since it most likely already erred here,
|
|
6361
6470
|
// we call to abort
|
|
6362
6471
|
abort();
|
|
6363
6472
|
}
|
|
6473
|
+
/* c8 ignore stop -- see comment above */
|
|
6364
6474
|
} else {
|
|
6365
6475
|
abort(null, {
|
|
6366
6476
|
code: 0
|
|
@@ -6378,6 +6488,7 @@
|
|
|
6378
6488
|
if (!(me instanceof IDBTransaction)) {
|
|
6379
6489
|
throw new TypeError('Illegal invocation');
|
|
6380
6490
|
}
|
|
6491
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6381
6492
|
if (CFG.DEBUG) {
|
|
6382
6493
|
console.log('The transaction was aborted', me);
|
|
6383
6494
|
}
|
|
@@ -6409,6 +6520,7 @@
|
|
|
6409
6520
|
if (!me.__active || !me.__handlerActive || me.__committed) {
|
|
6410
6521
|
throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
|
|
6411
6522
|
}
|
|
6523
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6412
6524
|
if (CFG.DEBUG) {
|
|
6413
6525
|
console.log('The transaction was explicitly committed', me);
|
|
6414
6526
|
}
|
|
@@ -6451,6 +6563,7 @@
|
|
|
6451
6563
|
};
|
|
6452
6564
|
|
|
6453
6565
|
// object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
|
|
6566
|
+
/* c8 ignore start -- Dead code: this function has no callers anywhere in src/ (confirmed via grep); object store methods use `IDBTransaction.__assertActive`/`__assertNotFinished` directly instead. */
|
|
6454
6567
|
/**
|
|
6455
6568
|
*
|
|
6456
6569
|
* @param {IDBTransactionFull} tx
|
|
@@ -6466,6 +6579,7 @@
|
|
|
6466
6579
|
throw err;
|
|
6467
6580
|
}
|
|
6468
6581
|
};
|
|
6582
|
+
/* c8 ignore stop -- see comment above */
|
|
6469
6583
|
|
|
6470
6584
|
/**
|
|
6471
6585
|
*
|
|
@@ -7563,7 +7677,7 @@
|
|
|
7563
7677
|
return Number.isNaN(t) ? "NaN" : t;
|
|
7564
7678
|
},
|
|
7565
7679
|
revive: function revive(e) {
|
|
7566
|
-
return "NaN" === e ?
|
|
7680
|
+
return new Date("NaN" === e ? NaN : e);
|
|
7567
7681
|
}
|
|
7568
7682
|
}
|
|
7569
7683
|
},
|
|
@@ -8423,9 +8537,12 @@
|
|
|
8423
8537
|
}).find(function (preset) {
|
|
8424
8538
|
return preset && !Array.isArray(preset) && 'filelist' in preset;
|
|
8425
8539
|
});
|
|
8426
|
-
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8427
|
-
|
|
8428
|
-
var
|
|
8540
|
+
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8541
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8542
|
+
var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
|
|
8543
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
|
|
8544
|
+
var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
|
|
8545
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
|
|
8429
8546
|
var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
|
|
8430
8547
|
/**
|
|
8431
8548
|
* @param {unknown} x
|
|
@@ -8433,10 +8550,7 @@
|
|
|
8433
8550
|
* @returns {boolean}
|
|
8434
8551
|
*/
|
|
8435
8552
|
test: function test(x, state) {
|
|
8436
|
-
|
|
8437
|
-
return x instanceof FileList;
|
|
8438
|
-
}
|
|
8439
|
-
return typeof origTest === 'function' ? origTest(x, state) : false;
|
|
8553
|
+
return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
|
|
8440
8554
|
},
|
|
8441
8555
|
/**
|
|
8442
8556
|
* @param {unknown} x
|
|
@@ -8447,10 +8561,12 @@
|
|
|
8447
8561
|
if (typeof FileList !== 'undefined') {
|
|
8448
8562
|
return Reflect.construct(FileList, [x]);
|
|
8449
8563
|
}
|
|
8564
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
|
|
8450
8565
|
return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
|
|
8451
8566
|
}
|
|
8452
|
-
}) : undefined;
|
|
8453
|
-
var typeson = new Typeson().register([fe,
|
|
8567
|
+
}) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8568
|
+
var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
|
|
8569
|
+
customFileList ? {
|
|
8454
8570
|
filelist: customFileList
|
|
8455
8571
|
} : {}]);
|
|
8456
8572
|
|
|
@@ -8606,7 +8722,6 @@
|
|
|
8606
8722
|
* __unique: boolean,
|
|
8607
8723
|
* __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
8608
8724
|
* __keyPath: import('./Key.js').KeyPath,
|
|
8609
|
-
* __recreated?: boolean,
|
|
8610
8725
|
* __fetchIndexData: (
|
|
8611
8726
|
* range: Query,
|
|
8612
8727
|
* opType: "value"|"key"|"count",
|
|
@@ -8700,6 +8815,7 @@
|
|
|
8700
8815
|
storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
|
|
8701
8816
|
me.__pendingName = oldName;
|
|
8702
8817
|
var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
|
|
8818
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
8703
8819
|
// @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
|
|
8704
8820
|
_toConsumableArray(objectStore.indexNames).filter(function (indexName) {
|
|
8705
8821
|
return indexName !== newName;
|
|
@@ -8751,7 +8867,7 @@
|
|
|
8751
8867
|
}
|
|
8752
8868
|
});
|
|
8753
8869
|
/** @type {const} */
|
|
8754
|
-
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'
|
|
8870
|
+
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
|
|
8755
8871
|
// @ts-expect-error Why is this type "never"?
|
|
8756
8872
|
idx[p] = index[p];
|
|
8757
8873
|
});
|
|
@@ -8783,11 +8899,12 @@
|
|
|
8783
8899
|
var transaction = store.transaction;
|
|
8784
8900
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8785
8901
|
transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
|
|
8786
|
-
var columnExists = idx &&
|
|
8902
|
+
var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
|
|
8787
8903
|
|
|
8788
8904
|
/** @type {{[key: string]: boolean}} */
|
|
8789
8905
|
var indexValues = {};
|
|
8790
8906
|
|
|
8907
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8791
8908
|
/**
|
|
8792
8909
|
* @param {WebSQLTransaction} tx
|
|
8793
8910
|
* @param {(Error & {code?: number})} err
|
|
@@ -8796,6 +8913,7 @@
|
|
|
8796
8913
|
function error(tx, err) {
|
|
8797
8914
|
failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
|
|
8798
8915
|
}
|
|
8916
|
+
/* c8 ignore stop -- see comment above */
|
|
8799
8917
|
|
|
8800
8918
|
/**
|
|
8801
8919
|
* @param {WebSQLTransaction} tx
|
|
@@ -8845,12 +8963,6 @@
|
|
|
8845
8963
|
} else {
|
|
8846
8964
|
delete index.__pendingCreate;
|
|
8847
8965
|
delete indexHandle.__pendingCreate;
|
|
8848
|
-
if (index.__deleted) {
|
|
8849
|
-
delete index.__deleted;
|
|
8850
|
-
delete indexHandle.__deleted;
|
|
8851
|
-
index.__recreated = true;
|
|
8852
|
-
indexHandle.__recreated = true;
|
|
8853
|
-
}
|
|
8854
8966
|
indexValues = {};
|
|
8855
8967
|
success(store);
|
|
8856
8968
|
}
|
|
@@ -8859,7 +8971,7 @@
|
|
|
8859
8971
|
}, /** @type {SqlErrorCallback} */error);
|
|
8860
8972
|
}
|
|
8861
8973
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
8862
|
-
var escapedIndexNameSQL = escapeIndexNameForSQL(
|
|
8974
|
+
var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
|
|
8863
8975
|
|
|
8864
8976
|
/**
|
|
8865
8977
|
* @param {WebSQLTransaction} tx
|
|
@@ -8911,6 +9023,7 @@
|
|
|
8911
9023
|
var transaction = store.transaction;
|
|
8912
9024
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8913
9025
|
transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
|
|
9026
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8914
9027
|
/**
|
|
8915
9028
|
* @param {WebSQLTransaction} tx
|
|
8916
9029
|
* @param {(Error & {code?: number})} err
|
|
@@ -8919,6 +9032,7 @@
|
|
|
8919
9032
|
function error(tx, err) {
|
|
8920
9033
|
failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
|
|
8921
9034
|
}
|
|
9035
|
+
/* c8 ignore stop -- see comment above */
|
|
8922
9036
|
|
|
8923
9037
|
/**
|
|
8924
9038
|
* @returns {void}
|
|
@@ -8927,7 +9041,6 @@
|
|
|
8927
9041
|
// Update the object store's index list
|
|
8928
9042
|
IDBIndex.__updateIndexList(store, tx, function (store) {
|
|
8929
9043
|
delete index.__pendingDelete;
|
|
8930
|
-
delete index.__recreated;
|
|
8931
9044
|
index.__deleted = true;
|
|
8932
9045
|
if (indexHandle) {
|
|
8933
9046
|
indexHandle.__deleted = true;
|
|
@@ -8988,20 +9101,18 @@
|
|
|
8988
9101
|
* @param {Query} range
|
|
8989
9102
|
* @param {"value"|"key"|"count"} opType
|
|
8990
9103
|
* @param {boolean} nullDisallowed
|
|
8991
|
-
* @param {number} [count]
|
|
8992
9104
|
* @this {IDBIndexFull}
|
|
8993
9105
|
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
8994
9106
|
*/
|
|
8995
|
-
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed
|
|
9107
|
+
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
|
|
8996
9108
|
var me = this;
|
|
8997
|
-
if (count !== undefined) {
|
|
8998
|
-
count = enforceRange(count, 'unsigned long');
|
|
8999
|
-
}
|
|
9000
9109
|
IDBIndex.__invalidStateIfDeleted(me);
|
|
9001
9110
|
IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
|
|
9111
|
+
/* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
|
|
9002
9112
|
if (me.objectStore.__deleted) {
|
|
9003
9113
|
throw createDOMException('InvalidStateError', "This index's object store has been deleted");
|
|
9004
9114
|
}
|
|
9115
|
+
/* c8 ignore stop -- see comment above */
|
|
9005
9116
|
IDBTransaction.__assertActive(me.objectStore.transaction);
|
|
9006
9117
|
if (nullDisallowed && isNullish(range)) {
|
|
9007
9118
|
throw createDOMException('DataError', 'No key or range was specified');
|
|
@@ -9011,7 +9122,7 @@
|
|
|
9011
9122
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
9012
9123
|
args[_key] = arguments[_key];
|
|
9013
9124
|
}
|
|
9014
|
-
executeFetchIndexData.apply(void 0,
|
|
9125
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
|
|
9015
9126
|
}, undefined, me);
|
|
9016
9127
|
};
|
|
9017
9128
|
|
|
@@ -9170,13 +9281,16 @@
|
|
|
9170
9281
|
var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
|
|
9171
9282
|
return colInfo.join(' ');
|
|
9172
9283
|
});
|
|
9284
|
+
/* c8 ignore next -- Defensive: the sole caller always supplies a non-empty `colInfoToPreserveArr` (seeded with `key`/`value` column info), so the empty-array fallback is unreachable. */
|
|
9173
9285
|
var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
|
|
9286
|
+
/* c8 ignore next -- Defensive: see comment above. */
|
|
9174
9287
|
var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
|
|
9175
9288
|
|
|
9176
9289
|
// We could adapt the approach at https://stackoverflow.com/a/8430746/271577
|
|
9177
9290
|
// to make the approach reusable without passing column names, but it is a bit fragile
|
|
9178
9291
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
9179
9292
|
store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
|
|
9293
|
+
/* c8 ignore start -- Defensive: only reached if one of the chained `CREATE TABLE`/`INSERT`/`DROP TABLE`/`ALTER TABLE` statements below fails, which is not reliably reproducible without mocking the SQL layer. */
|
|
9180
9294
|
/**
|
|
9181
9295
|
* @param {WebSQLTransaction} tx
|
|
9182
9296
|
* @param {(Error & {code?: number})} err
|
|
@@ -9185,6 +9299,7 @@
|
|
|
9185
9299
|
function sqlError(tx, err) {
|
|
9186
9300
|
error(err);
|
|
9187
9301
|
}
|
|
9302
|
+
/* c8 ignore stop -- see comment above */
|
|
9188
9303
|
/**
|
|
9189
9304
|
* @returns {void}
|
|
9190
9305
|
*/
|
|
@@ -9193,8 +9308,14 @@
|
|
|
9193
9308
|
cb(tx, success);
|
|
9194
9309
|
return;
|
|
9195
9310
|
}
|
|
9311
|
+
/* c8 ignore start -- Defensive: `__renameIndex`'s only caller (the `IDBIndex.prototype.name` setter) always supplies a `cb`, so this fallback is dead with the current call graph. */
|
|
9196
9312
|
success();
|
|
9197
9313
|
}
|
|
9314
|
+
/* c8 ignore stop -- see comment above */
|
|
9315
|
+
if (!CFG.useSQLiteIndexes) {
|
|
9316
|
+
finish();
|
|
9317
|
+
return;
|
|
9318
|
+
}
|
|
9198
9319
|
// See https://www.sqlite.org/lang_altertable.html#otheralter
|
|
9199
9320
|
// We don't query for indexes as we already have the info
|
|
9200
9321
|
// This approach has the advantage of auto-deleting indexes via the DROP TABLE
|
|
@@ -9218,10 +9339,6 @@
|
|
|
9218
9339
|
console.log(sql);
|
|
9219
9340
|
}
|
|
9220
9341
|
tx.executeSql(sql, [], function (tx) {
|
|
9221
|
-
if (!CFG.useSQLiteIndexes) {
|
|
9222
|
-
finish();
|
|
9223
|
-
return;
|
|
9224
|
-
}
|
|
9225
9342
|
var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
|
|
9226
9343
|
.map(function (escapedIndexNameSQL) {
|
|
9227
9344
|
return new SyncPromise(function (resolve, reject) {
|
|
@@ -9230,13 +9347,16 @@
|
|
|
9230
9347
|
// if (CFG.DEBUG) { console.log(sql); }
|
|
9231
9348
|
// tx.executeSql(sql, [], function () {
|
|
9232
9349
|
var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
|
|
9350
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
9233
9351
|
if (CFG.DEBUG) {
|
|
9234
9352
|
console.log(sql);
|
|
9235
9353
|
}
|
|
9236
|
-
tx.executeSql(sql, [], resolve,
|
|
9354
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9355
|
+
/** @type {SqlErrorCallback} */
|
|
9237
9356
|
function (tx, err) {
|
|
9238
9357
|
reject(err);
|
|
9239
|
-
}
|
|
9358
|
+
}
|
|
9359
|
+
/* c8 ignore stop -- see comment above */);
|
|
9240
9360
|
// }, function (tx, err) {
|
|
9241
9361
|
// reject(err);
|
|
9242
9362
|
// });
|
|
@@ -9254,19 +9374,25 @@
|
|
|
9254
9374
|
if (CFG.DEBUG) {
|
|
9255
9375
|
console.log(sql);
|
|
9256
9376
|
}
|
|
9257
|
-
tx.executeSql(sql, [], resolve,
|
|
9377
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9378
|
+
/** @type {SqlErrorCallback} */
|
|
9258
9379
|
function (tx, err) {
|
|
9259
9380
|
reject(err);
|
|
9260
|
-
}
|
|
9261
|
-
|
|
9381
|
+
}
|
|
9382
|
+
/* c8 ignore stop -- see comment above */);
|
|
9383
|
+
}, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9384
|
+
/** @type {SqlErrorCallback} */
|
|
9262
9385
|
function (tx, err) {
|
|
9263
9386
|
reject(err);
|
|
9264
|
-
}
|
|
9387
|
+
}
|
|
9388
|
+
/* c8 ignore stop -- see comment above */);
|
|
9265
9389
|
}));
|
|
9266
9390
|
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
|
|
9267
9391
|
error).catch(function (err) {
|
|
9392
|
+
/* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
|
|
9268
9393
|
console.log('Index rename error');
|
|
9269
9394
|
throw err;
|
|
9395
|
+
/* c8 ignore stop -- see comment above */
|
|
9270
9396
|
});
|
|
9271
9397
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
9272
9398
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
@@ -9295,7 +9421,6 @@
|
|
|
9295
9421
|
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
9296
9422
|
|
|
9297
9423
|
/**
|
|
9298
|
-
* @param {number|null} count
|
|
9299
9424
|
* @param {boolean} unboundedDisallowed
|
|
9300
9425
|
* @param {IDBIndexFull} index
|
|
9301
9426
|
* @param {boolean} hasKey
|
|
@@ -9312,12 +9437,9 @@
|
|
|
9312
9437
|
* @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
|
|
9313
9438
|
* @returns {void}
|
|
9314
9439
|
*/
|
|
9315
|
-
function executeFetchIndexData(
|
|
9440
|
+
function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
|
|
9316
9441
|
if (unboundedDisallowed) {
|
|
9317
|
-
|
|
9318
|
-
}
|
|
9319
|
-
if (count) {
|
|
9320
|
-
sql.push('LIMIT', String(count));
|
|
9442
|
+
sql.push('LIMIT', '1');
|
|
9321
9443
|
}
|
|
9322
9444
|
var isCount = opType === 'count';
|
|
9323
9445
|
if (CFG.DEBUG) {
|
|
@@ -9355,41 +9477,48 @@
|
|
|
9355
9477
|
var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
|
|
9356
9478
|
var encodedKey = _encode(range, index.multiEntry);
|
|
9357
9479
|
var _loop = function _loop() {
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
record = row;
|
|
9378
|
-
} else if (!hasKey && !multiChecks) {
|
|
9379
|
-
if (rowKey !== undefined) {
|
|
9380
|
-
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9480
|
+
var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
|
|
9481
|
+
var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
|
|
9482
|
+
_decode(row[escapedIndexNameForKeyCol]);
|
|
9483
|
+
var record;
|
|
9484
|
+
if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
|
|
9485
|
+
/**
|
|
9486
|
+
* @param {import('./Key.js').ValueType} check
|
|
9487
|
+
* @returns {boolean}
|
|
9488
|
+
*/
|
|
9489
|
+
function (check) {
|
|
9490
|
+
return rowKey.includes(check);
|
|
9491
|
+
}) ||
|
|
9492
|
+
// More precise than our SQL
|
|
9493
|
+
isMultiEntryMatch(
|
|
9494
|
+
// Added `JSON.stringify` as was having problems with
|
|
9495
|
+
// `JSON.stringify` encoding added to nested
|
|
9496
|
+
// array keys
|
|
9497
|
+
JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
|
|
9498
|
+
recordCount++;
|
|
9381
9499
|
record = row;
|
|
9500
|
+
} else if (!hasKey && !multiChecks) {
|
|
9501
|
+
if (rowKey !== undefined) {
|
|
9502
|
+
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9503
|
+
record = row;
|
|
9504
|
+
}
|
|
9382
9505
|
}
|
|
9383
|
-
|
|
9384
|
-
|
|
9506
|
+
/* 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. */
|
|
9507
|
+
if (!record) {
|
|
9508
|
+
return 0; // continue
|
|
9509
|
+
}
|
|
9510
|
+
/* c8 ignore stop -- see comment above */
|
|
9511
|
+
|
|
9385
9512
|
records.push(decode$1(record));
|
|
9386
9513
|
if (unboundedDisallowed) {
|
|
9387
9514
|
return 1; // break
|
|
9388
9515
|
}
|
|
9389
|
-
}
|
|
9390
|
-
|
|
9516
|
+
},
|
|
9517
|
+
_ret;
|
|
9391
9518
|
for (var i = 0; i < data.rows.length; i++) {
|
|
9392
|
-
|
|
9519
|
+
_ret = _loop();
|
|
9520
|
+
if (_ret === 0) continue;
|
|
9521
|
+
if (_ret === 1) break;
|
|
9393
9522
|
}
|
|
9394
9523
|
} else {
|
|
9395
9524
|
for (var _i = 0; _i < data.rows.length; _i++) {
|
|
@@ -9403,8 +9532,16 @@
|
|
|
9403
9532
|
if (isCount) {
|
|
9404
9533
|
success(recordCount);
|
|
9405
9534
|
} else if (recordCount === 0) {
|
|
9535
|
+
// `unboundedDisallowed` is always `true` here: this function is only reached (for
|
|
9536
|
+
// non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
|
|
9537
|
+
// through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
|
|
9538
|
+
// different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
|
|
9539
|
+
// (returning `[]` here) is unreachable given current callers.
|
|
9540
|
+
/* c8 ignore next -- see comment above */
|
|
9406
9541
|
success(unboundedDisallowed ? undefined : []);
|
|
9407
9542
|
} else {
|
|
9543
|
+
// `unboundedDisallowed` is always `true` here; see comment above.
|
|
9544
|
+
/* c8 ignore next -- see comment above */
|
|
9408
9545
|
success(unboundedDisallowed ? records[0] : records);
|
|
9409
9546
|
}
|
|
9410
9547
|
}, /** @type {SqlErrorCallback} */error);
|
|
@@ -9648,6 +9785,7 @@
|
|
|
9648
9785
|
tx.executeSql(sql, sqlValues, function (tx) {
|
|
9649
9786
|
// This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
|
|
9650
9787
|
var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
|
|
9788
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
|
|
9651
9789
|
if (CFG.DEBUG) {
|
|
9652
9790
|
console.log(sql);
|
|
9653
9791
|
}
|
|
@@ -9656,8 +9794,10 @@
|
|
|
9656
9794
|
success();
|
|
9657
9795
|
});
|
|
9658
9796
|
}, function (tx, err) {
|
|
9797
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9659
9798
|
error(err);
|
|
9660
9799
|
return false;
|
|
9800
|
+
/* c8 ignore stop -- see comment above */
|
|
9661
9801
|
});
|
|
9662
9802
|
});
|
|
9663
9803
|
}
|
|
@@ -9731,6 +9871,7 @@
|
|
|
9731
9871
|
storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
|
|
9732
9872
|
}
|
|
9733
9873
|
transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
|
|
9874
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9734
9875
|
/**
|
|
9735
9876
|
* @param {WebSQLTransaction} tx
|
|
9736
9877
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9743,6 +9884,8 @@
|
|
|
9743
9884
|
failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
|
|
9744
9885
|
return false;
|
|
9745
9886
|
}
|
|
9887
|
+
/* c8 ignore stop -- see comment above */
|
|
9888
|
+
|
|
9746
9889
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
9747
9890
|
// key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
|
|
9748
9891
|
var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
|
|
@@ -9797,6 +9940,7 @@
|
|
|
9797
9940
|
|
|
9798
9941
|
// Remove the object store from WebSQL
|
|
9799
9942
|
transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
|
|
9943
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9800
9944
|
/**
|
|
9801
9945
|
* @param {WebSQLTransaction} tx
|
|
9802
9946
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9809,6 +9953,8 @@
|
|
|
9809
9953
|
failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
|
|
9810
9954
|
return false;
|
|
9811
9955
|
}
|
|
9956
|
+
/* c8 ignore stop -- see comment above */
|
|
9957
|
+
|
|
9812
9958
|
tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
|
|
9813
9959
|
if (data.rows.length > 0) {
|
|
9814
9960
|
tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
|
|
@@ -9988,13 +10134,15 @@
|
|
|
9988
10134
|
return;
|
|
9989
10135
|
}
|
|
9990
10136
|
var indexKeyValue = indexKey.value;
|
|
10137
|
+
/* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
|
|
9991
10138
|
if (indexKeyValue === undefined) {
|
|
9992
10139
|
resolve(undefined);
|
|
9993
10140
|
return;
|
|
9994
10141
|
}
|
|
10142
|
+
/* c8 ignore stop -- see comment above */
|
|
9995
10143
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
9996
10144
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
9997
|
-
executeFetchIndexData.apply(void 0,
|
|
10145
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
9998
10146
|
if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
|
|
9999
10147
|
resolve(undefined);
|
|
10000
10148
|
return;
|
|
@@ -10074,16 +10222,18 @@
|
|
|
10074
10222
|
* @returns {void}
|
|
10075
10223
|
*/
|
|
10076
10224
|
function setIndexInfo(index) {
|
|
10225
|
+
/* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
|
|
10077
10226
|
if (indexKeyValue === undefined) {
|
|
10078
10227
|
return;
|
|
10079
10228
|
}
|
|
10229
|
+
/* c8 ignore stop -- see comment above */
|
|
10080
10230
|
paramMap[index.__currentName] = /** @type {string} */
|
|
10081
10231
|
_encode(indexKeyValue, index.multiEntry);
|
|
10082
10232
|
}
|
|
10083
10233
|
if (index.unique) {
|
|
10084
10234
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
10085
10235
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
10086
|
-
executeFetchIndexData.apply(void 0,
|
|
10236
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
10087
10237
|
if (key === undefined) {
|
|
10088
10238
|
setIndexInfo(index);
|
|
10089
10239
|
resolve(undefined);
|
|
@@ -10174,6 +10324,7 @@
|
|
|
10174
10324
|
_me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
|
|
10175
10325
|
ky = _me$__validateKeyAndV2[0],
|
|
10176
10326
|
clonedValue = _me$__validateKeyAndV2[1];
|
|
10327
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10177
10328
|
// @ts-ignore -- Private API
|
|
10178
10329
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
|
|
10179
10330
|
return request;
|
|
@@ -10205,6 +10356,7 @@
|
|
|
10205
10356
|
_me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
|
|
10206
10357
|
ky = _me$__validateKeyAndV4[0],
|
|
10207
10358
|
clonedValue = _me$__validateKeyAndV4[1];
|
|
10359
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10208
10360
|
// @ts-ignore -- Private API
|
|
10209
10361
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
|
|
10210
10362
|
return request;
|
|
@@ -10231,8 +10383,10 @@
|
|
|
10231
10383
|
}
|
|
10232
10384
|
cb(tx);
|
|
10233
10385
|
}, function (tx, err) {
|
|
10386
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10234
10387
|
error(err);
|
|
10235
10388
|
return false;
|
|
10389
|
+
/* c8 ignore stop -- see comment above */
|
|
10236
10390
|
});
|
|
10237
10391
|
};
|
|
10238
10392
|
|
|
@@ -10341,16 +10495,20 @@
|
|
|
10341
10495
|
return;
|
|
10342
10496
|
}
|
|
10343
10497
|
ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
|
|
10498
|
+
/* c8 ignore start -- Defensive: catches unexpected decode failures (e.g. corrupted stored data); not reliably reproducible via the public API since encode/decode are always paired and never write undecodable data. */
|
|
10344
10499
|
} catch (e) {
|
|
10345
10500
|
// If no result is returned, or error occurs when parsing JSON
|
|
10346
10501
|
if (CFG.DEBUG) {
|
|
10347
10502
|
console.log(e);
|
|
10348
10503
|
}
|
|
10349
10504
|
}
|
|
10505
|
+
/* c8 ignore stop -- see comment above */
|
|
10350
10506
|
success(ret);
|
|
10351
10507
|
}, function (tx, err) {
|
|
10508
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10352
10509
|
error(err);
|
|
10353
10510
|
return false;
|
|
10511
|
+
/* c8 ignore stop -- see comment above */
|
|
10354
10512
|
});
|
|
10355
10513
|
}, undefined, me);
|
|
10356
10514
|
};
|
|
@@ -10462,8 +10620,10 @@
|
|
|
10462
10620
|
});
|
|
10463
10621
|
success();
|
|
10464
10622
|
}, function (tx, err) {
|
|
10623
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10465
10624
|
error(err);
|
|
10466
10625
|
return false;
|
|
10626
|
+
/* c8 ignore stop -- see comment above */
|
|
10467
10627
|
});
|
|
10468
10628
|
}, undefined, me);
|
|
10469
10629
|
};
|
|
@@ -10491,8 +10651,10 @@
|
|
|
10491
10651
|
});
|
|
10492
10652
|
success();
|
|
10493
10653
|
}, function (tx, err) {
|
|
10654
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10494
10655
|
error(err);
|
|
10495
10656
|
return false;
|
|
10657
|
+
/* c8 ignore stop -- see comment above */
|
|
10496
10658
|
});
|
|
10497
10659
|
}, undefined, me);
|
|
10498
10660
|
};
|
|
@@ -10827,7 +10989,7 @@
|
|
|
10827
10989
|
if (keyPath !== null && !isValidKeyPath(keyPath)) {
|
|
10828
10990
|
throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
|
|
10829
10991
|
}
|
|
10830
|
-
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
|
|
10992
|
+
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
|
|
10831
10993
|
throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
|
|
10832
10994
|
}
|
|
10833
10995
|
var autoInc = createOptions.autoIncrement;
|
|
@@ -10976,7 +11138,6 @@
|
|
|
10976
11138
|
}
|
|
10977
11139
|
};
|
|
10978
11140
|
|
|
10979
|
-
// Todo __forceClose: Add tests for `__forceClose`
|
|
10980
11141
|
/**
|
|
10981
11142
|
*
|
|
10982
11143
|
* @param {string} msg
|
|
@@ -10985,23 +11146,39 @@
|
|
|
10985
11146
|
*/
|
|
10986
11147
|
IDBDatabase.prototype.__forceClose = function (msg) {
|
|
10987
11148
|
var me = this;
|
|
11149
|
+
// `close()` (below) resets `me.__transactions` to `[]`, so the
|
|
11150
|
+
// transactions to abort -- and the total count the completion check
|
|
11151
|
+
// below needs -- must be captured before calling it, not read back off
|
|
11152
|
+
// `me.__transactions` afterward.
|
|
11153
|
+
var transactions = me.__transactions;
|
|
10988
11154
|
me.close();
|
|
11155
|
+
|
|
11156
|
+
/**
|
|
11157
|
+
* @returns {void}
|
|
11158
|
+
*/
|
|
11159
|
+
function dispatchClose() {
|
|
11160
|
+
// Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
|
|
11161
|
+
var evt = createEvent('close');
|
|
11162
|
+
setTimeout(function () {
|
|
11163
|
+
me.dispatchEvent(evt);
|
|
11164
|
+
}, 0);
|
|
11165
|
+
}
|
|
11166
|
+
if (!transactions.length) {
|
|
11167
|
+
dispatchClose();
|
|
11168
|
+
return;
|
|
11169
|
+
}
|
|
10989
11170
|
var ct = 0;
|
|
10990
|
-
|
|
11171
|
+
transactions.forEach(function (trans) {
|
|
10991
11172
|
// eslint-disable-next-line camelcase -- Clear API
|
|
10992
11173
|
trans.on__abort = function () {
|
|
10993
11174
|
ct++;
|
|
10994
|
-
if (ct
|
|
10995
|
-
|
|
10996
|
-
var evt = createEvent('close');
|
|
10997
|
-
setTimeout(function () {
|
|
10998
|
-
me.dispatchEvent(evt);
|
|
10999
|
-
}, 0);
|
|
11175
|
+
if (ct !== transactions.length) {
|
|
11176
|
+
return;
|
|
11000
11177
|
}
|
|
11178
|
+
dispatchClose();
|
|
11001
11179
|
};
|
|
11002
11180
|
trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
|
|
11003
11181
|
});
|
|
11004
|
-
me.__transactions = [];
|
|
11005
11182
|
};
|
|
11006
11183
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
11007
11184
|
defineOuterInterface(IDBDatabase.prototype, listeners);
|
|
@@ -11168,6 +11345,7 @@
|
|
|
11168
11345
|
return undefined;
|
|
11169
11346
|
}
|
|
11170
11347
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11348
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11171
11349
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11172
11350
|
new IDBVersionChangeEvent('versionchange', {
|
|
11173
11351
|
oldVersion: oldVersion,
|
|
@@ -11215,6 +11393,7 @@
|
|
|
11215
11393
|
}
|
|
11216
11394
|
};
|
|
11217
11395
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11396
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11218
11397
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11219
11398
|
new IDBVersionChangeEvent('blocked', {
|
|
11220
11399
|
oldVersion: oldVersion,
|
|
@@ -11275,6 +11454,13 @@
|
|
|
11275
11454
|
|
|
11276
11455
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
11277
11456
|
var sysdb;
|
|
11457
|
+
// Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
|
|
11458
|
+
// later change to that config (e.g. toggling in-memory mode on and back
|
|
11459
|
+
// off) causes `sysdb` to be recreated for the new setting rather than
|
|
11460
|
+
// staying pinned, forever, to whatever it was the first time any database
|
|
11461
|
+
// was created in the process.
|
|
11462
|
+
/** @type {string|null|undefined} */
|
|
11463
|
+
var sysdbMemoryDatabaseSetting;
|
|
11278
11464
|
var nameCounter = 0;
|
|
11279
11465
|
|
|
11280
11466
|
/**
|
|
@@ -11356,12 +11542,20 @@
|
|
|
11356
11542
|
function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
|
|
11357
11543
|
var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
|
|
11358
11544
|
if (useMemoryDatabase) {
|
|
11545
|
+
/* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
|
|
11546
|
+
was initialized as an empty placeholder by `open()`'s connection-queue
|
|
11547
|
+
setup (`addRequestToConnectionQueue`, above `openDB`) but never
|
|
11548
|
+
populated with an actual instance -- e.g. `__openDatabase` throwing
|
|
11549
|
+
after a `dbVersions` row already existed for `name` from an earlier,
|
|
11550
|
+
successful `open()` -- or if `name` was never added to the cache at
|
|
11551
|
+
all. Not reachable via normal, non-tampered API usage. */
|
|
11359
11552
|
var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
|
|
11360
11553
|
if (!latestSQLiteDBCached) {
|
|
11361
11554
|
console.warn('Could not find a memory database instance to delete.');
|
|
11362
11555
|
databaseDeleted();
|
|
11363
11556
|
return;
|
|
11364
11557
|
}
|
|
11558
|
+
/* c8 ignore stop -- see comment above */
|
|
11365
11559
|
var _sqliteDB = latestSQLiteDBCached._db;
|
|
11366
11560
|
if (!_sqliteDB || !_sqliteDB.close) {
|
|
11367
11561
|
console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
|
|
@@ -11415,15 +11609,24 @@
|
|
|
11415
11609
|
tables.item(i).name)), [], function () {
|
|
11416
11610
|
deleteTables(i + 1);
|
|
11417
11611
|
}, function () {
|
|
11612
|
+
/* c8 ignore start -- Defensive: continues deleting the rest
|
|
11613
|
+
even if this specific store's table is already gone (e.g.
|
|
11614
|
+
duplicate `__sys__` rows for the same escaped table name, or
|
|
11615
|
+
external tampering); not reachable via normal API usage. */
|
|
11418
11616
|
deleteTables(i + 1);
|
|
11419
11617
|
return false;
|
|
11618
|
+
/* c8 ignore stop -- see comment above */
|
|
11420
11619
|
});
|
|
11421
11620
|
}
|
|
11422
11621
|
})(0);
|
|
11423
11622
|
}, function () {
|
|
11424
|
-
|
|
11623
|
+
/* c8 ignore start -- `__sys__` is always created by `openDB` before this
|
|
11624
|
+
database's `dbVersions` row (a prerequisite for reaching this code at
|
|
11625
|
+
all) is ever inserted; only reachable if the file was tampered with/
|
|
11626
|
+
removed externally afterward. */
|
|
11425
11627
|
databaseDeleted();
|
|
11426
11628
|
return false;
|
|
11629
|
+
/* c8 ignore stop -- see comment above */
|
|
11427
11630
|
});
|
|
11428
11631
|
});
|
|
11429
11632
|
}
|
|
@@ -11454,9 +11657,11 @@
|
|
|
11454
11657
|
}
|
|
11455
11658
|
failure(er);
|
|
11456
11659
|
}
|
|
11457
|
-
if (sysdb) {
|
|
11660
|
+
if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
|
|
11458
11661
|
success();
|
|
11459
11662
|
} else {
|
|
11663
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
|
|
11664
|
+
sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
|
|
11460
11665
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
|
|
11461
11666
|
sysdb = __openDatabase(typeof CFG.memoryDatabase === 'string' ? CFG.memoryDatabase : joinPath(typeof CFG.sysDatabaseBasePath === 'string' ? CFG.sysDatabaseBasePath : CFG.databaseBasePath || '', '__sysdb__' + (CFG.addSQLiteExtension !== false ? '.sqlite' : '')), '1', 'System Database', CFG.DEFAULT_DB_SIZE);
|
|
11462
11667
|
sysdb.transaction(function (systx) {
|
|
@@ -11636,6 +11841,17 @@
|
|
|
11636
11841
|
* @returns {void}
|
|
11637
11842
|
*/
|
|
11638
11843
|
var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11844
|
+
/* c8 ignore start -- This initial definition is always
|
|
11845
|
+
superseded before ever being invoked: the `sysdb.transaction(...)`
|
|
11846
|
+
call below always reaches its `nonstandardTransCb` (4th arg)
|
|
11847
|
+
after this same SQL batch finishes running (since `dbCreateError`
|
|
11848
|
+
always reports errors as "handled" and this call site is never
|
|
11849
|
+
a `readTransaction`), which unconditionally reassigns
|
|
11850
|
+
`sysdbFinishedCb` to a version using the library's own
|
|
11851
|
+
`rollback`/`commit` -- well before any real invocation from
|
|
11852
|
+
`on__beforecomplete`/`on__preabort`/`on__abort` below (those only
|
|
11853
|
+
fire once the upgrade transaction itself later completes/aborts).
|
|
11854
|
+
Kept as a defensive fallback in case that invariant ever changes. */
|
|
11639
11855
|
if (err) {
|
|
11640
11856
|
/**
|
|
11641
11857
|
* @param {unknown} [errorToShow]
|
|
@@ -11684,6 +11900,7 @@
|
|
|
11684
11900
|
}
|
|
11685
11901
|
// In browser, should auto-commit
|
|
11686
11902
|
cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11903
|
+
/* c8 ignore stop -- see comment above */
|
|
11687
11904
|
};
|
|
11688
11905
|
sysdb.transaction(function (systx) {
|
|
11689
11906
|
/**
|
|
@@ -11691,6 +11908,7 @@
|
|
|
11691
11908
|
*/
|
|
11692
11909
|
function versionSet() {
|
|
11693
11910
|
var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
|
|
11911
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11694
11912
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11695
11913
|
new IDBVersionChangeEvent('upgradeneeded', {
|
|
11696
11914
|
oldVersion: oldVersion,
|
|
@@ -11816,9 +12034,17 @@
|
|
|
11816
12034
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11817
12035
|
req.transaction.on__complete = function () {
|
|
11818
12036
|
var pos = connection.__transactions.indexOf(req.transaction);
|
|
12037
|
+
// `req.transaction` (the versionchange transaction) is created
|
|
12038
|
+
// directly via `IDBTransaction.__createInstance` above, never
|
|
12039
|
+
// via `IDBDatabase.prototype.transaction()` (the only place
|
|
12040
|
+
// that pushes onto `connection.__transactions`), so `pos` is
|
|
12041
|
+
// always -1 here.
|
|
12042
|
+
/* c8 ignore start -- see comment above */
|
|
11819
12043
|
if (pos !== -1) {
|
|
11820
12044
|
connection.__transactions.splice(pos, 1);
|
|
11821
12045
|
}
|
|
12046
|
+
/* c8 ignore stop -- see comment above */
|
|
12047
|
+
|
|
11822
12048
|
if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
|
|
11823
12049
|
req.__transaction = null;
|
|
11824
12050
|
var err = createDOMException('AbortError', 'The connection has been closed.');
|
|
@@ -11854,9 +12080,16 @@
|
|
|
11854
12080
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
|
|
11855
12081
|
}
|
|
11856
12082
|
}, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12083
|
+
// Defensive fallback, not reachable in practice: same reasoning
|
|
12084
|
+
// as `deleteDatabase`'s own `nonstandardTransCb` below
|
|
12085
|
+
// (`currentTask.readOnly` is always false here, and
|
|
12086
|
+
// `dbCreateError` always returns `false`, so `err` is never
|
|
12087
|
+
// truthy either).
|
|
12088
|
+
/* c8 ignore start -- see comment above */
|
|
11857
12089
|
if (currentTask.readOnly || err) {
|
|
11858
12090
|
return true;
|
|
11859
12091
|
}
|
|
12092
|
+
/* c8 ignore stop -- see comment above */
|
|
11860
12093
|
sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11861
12094
|
if (err) {
|
|
11862
12095
|
rollback(err,
|
|
@@ -11871,7 +12104,17 @@
|
|
|
11871
12104
|
} else {
|
|
11872
12105
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
|
|
11873
12106
|
}
|
|
11874
|
-
},
|
|
12107
|
+
},
|
|
12108
|
+
// Deeply-nested defensive path: only reached if
|
|
12109
|
+
// the *revert* SQL (undoing the `dbVersions`
|
|
12110
|
+
// INSERT/UPDATE after the original version-
|
|
12111
|
+
// upgrade itself already failed) fails a
|
|
12112
|
+
// *second* time. Not feasibly triggerable
|
|
12113
|
+
// without fault-injecting the underlying SQL
|
|
12114
|
+
// driver on this specific, already-failing
|
|
12115
|
+
// revert statement.
|
|
12116
|
+
function (sqlErr) {
|
|
12117
|
+
/* c8 ignore next 2 -- see comment above */
|
|
11875
12118
|
isRevertingSysdb = false;
|
|
11876
12119
|
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11877
12120
|
}, function () {
|
|
@@ -11887,8 +12130,20 @@
|
|
|
11887
12130
|
});
|
|
11888
12131
|
return undefined;
|
|
11889
12132
|
}).catch(function (err) {
|
|
12133
|
+
/* c8 ignore start -- Purely defensive: nothing in
|
|
12134
|
+
`triggerAnyVersionChangeAndBlockedEvents`'s promise chain
|
|
12135
|
+
(or this `.then()` continuation above) ever rejects/throws
|
|
12136
|
+
under any reachable application-level condition -- all of
|
|
12137
|
+
its continuations resolve cleanly, and its `dispatchEvent`
|
|
12138
|
+
calls are deliberately fire-and-forget ("No need to catch
|
|
12139
|
+
errors"), running inside a `setTimeout` where a listener
|
|
12140
|
+
throwing becomes an uncaught exception in that macrotask
|
|
12141
|
+
rather than a promise rejection here. This exists solely
|
|
12142
|
+
to surface a truly-unexpected internal bug via the console
|
|
12143
|
+
before rethrowing, not to handle a real, testable error path. */
|
|
11890
12144
|
console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
|
|
11891
12145
|
throw err;
|
|
12146
|
+
/* c8 ignore stop -- see comment above */
|
|
11892
12147
|
});
|
|
11893
12148
|
} else {
|
|
11894
12149
|
finishRequest();
|
|
@@ -11916,11 +12171,19 @@
|
|
|
11916
12171
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
11917
12172
|
db = websqlDBCache[name][version];
|
|
11918
12173
|
} else {
|
|
11919
|
-
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
12174
|
+
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
11920
12175
|
if (useDatabaseCache) {
|
|
12176
|
+
/* c8 ignore start -- Defensive: by the time `openDB` runs,
|
|
12177
|
+
`websqlDBCache[name]` has always already been created by
|
|
12178
|
+
`addRequestToConnectionQueue`'s own callback above (guarded
|
|
12179
|
+
by this same `useDatabaseCache` condition), which always
|
|
12180
|
+
runs first and unconditionally ensures the entry exists
|
|
12181
|
+
before ever calling `openDB`. Kept as a safety net in case
|
|
12182
|
+
that invariant ever changes. */
|
|
11921
12183
|
if (!Object.hasOwn(websqlDBCache, name)) {
|
|
11922
12184
|
websqlDBCache[name] = {};
|
|
11923
12185
|
}
|
|
12186
|
+
/* c8 ignore stop -- see comment above */
|
|
11924
12187
|
websqlDBCache[name][version] = db;
|
|
11925
12188
|
}
|
|
11926
12189
|
}
|
|
@@ -12071,6 +12334,7 @@
|
|
|
12071
12334
|
req.__result = undefined;
|
|
12072
12335
|
req.__done = true;
|
|
12073
12336
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
12337
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12074
12338
|
// @ts-ignore It's ok; needed under some TS versions
|
|
12075
12339
|
new IDBVersionChangeEvent('success', {
|
|
12076
12340
|
oldVersion: version,
|
|
@@ -12113,9 +12377,23 @@
|
|
|
12113
12377
|
cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
|
|
12114
12378
|
}, dbError);
|
|
12115
12379
|
}, dbError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12380
|
+
/* c8 ignore start -- Defensive fallback, not reachable in
|
|
12381
|
+
practice: `currentTask.readOnly` is always `false` here
|
|
12382
|
+
(this callback is only ever attached to the writable
|
|
12383
|
+
`sysdb.transaction(...)` call above, never to a
|
|
12384
|
+
`sysdb.readTransaction(...)`), and `err` can only be
|
|
12385
|
+
truthy if the `DELETE FROM dbVersions` statement's own
|
|
12386
|
+
error callback (`dbError`) reports the failure back to
|
|
12387
|
+
`websql-configurable` as unhandled -- but `dbError`
|
|
12388
|
+
deliberately always `return`s `false`, which tells the
|
|
12389
|
+
library the error was already handled (and to keep
|
|
12390
|
+
`err` falsy here), precisely so this custom
|
|
12391
|
+
`sysdbFinishedCbDelete` rollback/commit path below is
|
|
12392
|
+
used instead of the library's own default rollback. */
|
|
12116
12393
|
if (currentTask.readOnly || err) {
|
|
12117
12394
|
return true;
|
|
12118
12395
|
}
|
|
12396
|
+
/* c8 ignore stop -- see comment above */
|
|
12119
12397
|
sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
|
|
12120
12398
|
if (err) {
|
|
12121
12399
|
rollback(err, cb);
|
|
@@ -12241,10 +12519,9 @@
|
|
|
12241
12519
|
};
|
|
12242
12520
|
|
|
12243
12521
|
/**
|
|
12244
|
-
* @todo forceClose: Test
|
|
12245
12522
|
* This is provided to facilitate unit-testing of the
|
|
12246
12523
|
* closing of a database connection with a forced flag:
|
|
12247
|
-
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection
|
|
12524
|
+
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
|
|
12248
12525
|
* @param {string} dbName
|
|
12249
12526
|
* @param {Integer} connIdx
|
|
12250
12527
|
* @param {string} msg
|
|
@@ -12345,6 +12622,7 @@
|
|
|
12345
12622
|
* @this {IDBRecordFull}
|
|
12346
12623
|
*/
|
|
12347
12624
|
function IDBRecord() {
|
|
12625
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12348
12626
|
// @ts-ignore Should be ok
|
|
12349
12627
|
this[Symbol.toStringTag] = 'IDBRecord';
|
|
12350
12628
|
this.__key = key;
|
|
@@ -12381,6 +12659,7 @@
|
|
|
12381
12659
|
if (!(this instanceof IDBRecordAlias)) {
|
|
12382
12660
|
throw new TypeError('Illegal invocation');
|
|
12383
12661
|
}
|
|
12662
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12384
12663
|
// @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
|
|
12385
12664
|
return this['__' + prop];
|
|
12386
12665
|
});
|
|
@@ -12723,6 +13002,7 @@
|
|
|
12723
13002
|
success(undefined, undefined, undefined);
|
|
12724
13003
|
}
|
|
12725
13004
|
}, function (tx, err) {
|
|
13005
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
12726
13006
|
if (CFG.DEBUG) {
|
|
12727
13007
|
console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12728
13008
|
}
|
|
@@ -12906,7 +13186,16 @@
|
|
|
12906
13186
|
if (a.key > b.key) {
|
|
12907
13187
|
return me.direction === 'prev' ? -1 : 1;
|
|
12908
13188
|
}
|
|
13189
|
+
/* c8 ignore start -- Defensive: only reachable if two matches
|
|
13190
|
+
in the same batch shared both the same `matchingKey` and
|
|
13191
|
+
the same primary `key`, which would require the same
|
|
13192
|
+
record's multi-entry array to contain a duplicate value.
|
|
13193
|
+
`Key.js`'s array-to-key conversion already drops duplicate
|
|
13194
|
+
values when a multi-entry index entry is built, so this
|
|
13195
|
+
can never happen in practice; kept only to satisfy the
|
|
13196
|
+
`Array.prototype.sort` comparator contract. */
|
|
12909
13197
|
return 0;
|
|
13198
|
+
/* c8 ignore stop -- see comment above */
|
|
12910
13199
|
});
|
|
12911
13200
|
me.__prefetchedIndex = 0;
|
|
12912
13201
|
me.__prefetchedData = {
|
|
@@ -12925,13 +13214,19 @@
|
|
|
12925
13214
|
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
12926
13215
|
}
|
|
12927
13216
|
me.__decode(rows[0], success);
|
|
12928
|
-
},
|
|
13217
|
+
},
|
|
13218
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13219
|
+
execution error (e.g. I/O error, corruption) while querying for
|
|
13220
|
+
multi-entry cursor matches; not reliably reproducible without
|
|
13221
|
+
mocking the SQL layer. */
|
|
13222
|
+
function (tx, err) {
|
|
12929
13223
|
if (CFG.DEBUG) {
|
|
12930
13224
|
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12931
13225
|
}
|
|
12932
13226
|
error(err);
|
|
12933
13227
|
return false;
|
|
12934
13228
|
});
|
|
13229
|
+
/* c8 ignore stop -- see comment above */
|
|
12935
13230
|
}
|
|
12936
13231
|
runQuery();
|
|
12937
13232
|
};
|
|
@@ -13040,6 +13335,7 @@
|
|
|
13040
13335
|
* @returns {void}
|
|
13041
13336
|
*/
|
|
13042
13337
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
13338
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13043
13339
|
// @ts-ignore Why is this not being found?; needed under some TS versions
|
|
13044
13340
|
this.__prefetchedData = null;
|
|
13045
13341
|
this.__multiEntryExhausted = false;
|
|
@@ -13064,7 +13360,7 @@
|
|
|
13064
13360
|
convertValueToKeyRethrowingAndIfInvalid(key);
|
|
13065
13361
|
var cmpResult = cmp(key, me.key);
|
|
13066
13362
|
if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
|
|
13067
|
-
throw createDOMException('DataError', 'Cannot
|
|
13363
|
+
throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
|
|
13068
13364
|
}
|
|
13069
13365
|
}
|
|
13070
13366
|
this.__continueFinish(key, undefined, advanceState);
|
|
@@ -13321,6 +13617,7 @@
|
|
|
13321
13617
|
// continuation logic in `__findBasic` to see this update's
|
|
13322
13618
|
// effect on ordering (see "Modify records during cursor
|
|
13323
13619
|
// iteration" in idbcursor_update_index.any.js).
|
|
13620
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13324
13621
|
// @ts-ignore -- API (not erring in TS 6)
|
|
13325
13622
|
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
13326
13623
|
}
|
|
@@ -13370,14 +13667,33 @@
|
|
|
13370
13667
|
// We don't invalidate the cache (as we don't access it anymore
|
|
13371
13668
|
// and it will set the index off)
|
|
13372
13669
|
success(undefined);
|
|
13670
|
+
/* c8 ignore start -- Defensive: `__find` (invoked just above) has
|
|
13671
|
+
already confirmed a row exists for this primary key within the
|
|
13672
|
+
same transaction queue, so `rowsAffected` should always be 1 in
|
|
13673
|
+
normal usage. This branch would only be reached if the underlying
|
|
13674
|
+
row were removed by another request queued in the same
|
|
13675
|
+
transaction between `__find`'s check and this DELETE actually
|
|
13676
|
+
running (e.g. deleting the same record directly via the object
|
|
13677
|
+
store while a cursor over it is mid-iteration); attempts to
|
|
13678
|
+
construct such a scenario instead trigger a transaction abort
|
|
13679
|
+
(`AbortError`) before this callback ever runs, since the default
|
|
13680
|
+
action of an unhandled request error is to abort the
|
|
13681
|
+
transaction. */
|
|
13373
13682
|
} else {
|
|
13374
13683
|
// @ts-expect-error Apparently ok
|
|
13375
13684
|
error('No rows with key found' + key);
|
|
13376
13685
|
}
|
|
13377
|
-
|
|
13686
|
+
/* c8 ignore stop -- see comment above */
|
|
13687
|
+
},
|
|
13688
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13689
|
+
execution error (e.g. I/O error, corruption) while deleting the
|
|
13690
|
+
current row; not reliably reproducible without mocking the SQL
|
|
13691
|
+
layer. */
|
|
13692
|
+
function (tx, data) {
|
|
13378
13693
|
error(data);
|
|
13379
13694
|
return false;
|
|
13380
13695
|
});
|
|
13696
|
+
/* c8 ignore stop -- see comment above */
|
|
13381
13697
|
}, error);
|
|
13382
13698
|
}, undefined, me);
|
|
13383
13699
|
};
|
|
@@ -13785,7 +14101,7 @@
|
|
|
13785
14101
|
*/
|
|
13786
14102
|
function setGlobalVars(idb, initialConfig) {
|
|
13787
14103
|
var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
|
|
13788
|
-
/** @type {unknown} */globalThis
|
|
14104
|
+
/** @type {unknown} */globalThis;
|
|
13789
14105
|
/**
|
|
13790
14106
|
* @param {string} name
|
|
13791
14107
|
* @param {unknown} value
|
|
@@ -13876,80 +14192,87 @@
|
|
|
13876
14192
|
});
|
|
13877
14193
|
}
|
|
13878
14194
|
var shimIDBFactory = IDBFactory;
|
|
13879
|
-
if (CFG.win.openDatabase
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
14195
|
+
if (CFG.win.openDatabase === undefined) {
|
|
14196
|
+
return;
|
|
14197
|
+
}
|
|
14198
|
+
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
|
|
14199
|
+
// Polyfill ALL of IndexedDB, using WebSQL
|
|
14200
|
+
shim('indexedDB', shimIndexedDB, {
|
|
14201
|
+
enumerable: true,
|
|
14202
|
+
configurable: true,
|
|
14203
|
+
get: function get() {
|
|
14204
|
+
if (this !== IDB && !isNullish(this) && !this.shimNS) {
|
|
14205
|
+
// Latter is hack for test environment
|
|
14206
|
+
throw new TypeError('Illegal invocation');
|
|
13891
14207
|
}
|
|
13892
|
-
|
|
13893
|
-
/** @type {[string, unknown][]} */
|
|
13894
|
-
[['IDBFactory', shimIDBFactory], ['IDBDatabase', IDBDatabase], ['IDBObjectStore', IDBObjectStore], ['IDBIndex', IDBIndex], ['IDBTransaction', IDBTransaction], ['IDBCursor', IDBCursor], ['IDBCursorWithValue', IDBCursorWithValue], ['IDBRecord', IDBRecord], ['IDBKeyRange', IDBKeyRange], ['IDBRequest', IDBRequest], ['IDBOpenDBRequest', IDBOpenDBRequest], ['IDBVersionChangeEvent', IDBVersionChangeEvent]].forEach(function (_ref3) {
|
|
13895
|
-
var _ref4 = _slicedToArray(_ref3, 2),
|
|
13896
|
-
prop = _ref4[0],
|
|
13897
|
-
obj = _ref4[1];
|
|
13898
|
-
shim(prop, obj, {
|
|
13899
|
-
enumerable: false,
|
|
13900
|
-
configurable: true
|
|
13901
|
-
});
|
|
13902
|
-
});
|
|
13903
|
-
// For Node environments
|
|
13904
|
-
if (CFG.fs) {
|
|
13905
|
-
setFS(CFG.fs);
|
|
14208
|
+
return shimIndexedDB;
|
|
13906
14209
|
}
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
14210
|
+
});
|
|
14211
|
+
/** @type {[string, unknown][]} */
|
|
14212
|
+
[['IDBFactory', shimIDBFactory], ['IDBDatabase', IDBDatabase], ['IDBObjectStore', IDBObjectStore], ['IDBIndex', IDBIndex], ['IDBTransaction', IDBTransaction], ['IDBCursor', IDBCursor], ['IDBCursorWithValue', IDBCursorWithValue], ['IDBRecord', IDBRecord], ['IDBKeyRange', IDBKeyRange], ['IDBRequest', IDBRequest], ['IDBOpenDBRequest', IDBOpenDBRequest], ['IDBVersionChangeEvent', IDBVersionChangeEvent]].forEach(function (_ref3) {
|
|
14213
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
14214
|
+
prop = _ref4[0],
|
|
14215
|
+
obj = _ref4[1];
|
|
14216
|
+
shim(prop, obj, {
|
|
14217
|
+
enumerable: false,
|
|
14218
|
+
configurable: true
|
|
14219
|
+
});
|
|
14220
|
+
});
|
|
14221
|
+
// For Node environments
|
|
14222
|
+
if (CFG.fs) {
|
|
14223
|
+
setFS(CFG.fs);
|
|
14224
|
+
}
|
|
14225
|
+
if (CFG.fullIDLSupport) {
|
|
14226
|
+
// Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
|
|
14227
|
+
|
|
14228
|
+
Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
|
|
14229
|
+
Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
|
|
14230
|
+
Object.setPrototypeOf(IDBDatabase, EventTarget);
|
|
14231
|
+
Object.setPrototypeOf(IDBRequest, EventTarget);
|
|
14232
|
+
Object.setPrototypeOf(IDBTransaction, EventTarget);
|
|
14233
|
+
Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
|
|
14234
|
+
// `ShimDOMException` is the real native `DOMException` when one
|
|
14235
|
+
// is available (see `DOMException.js`'s `useNativeDOMException`)
|
|
14236
|
+
// -- which, unlike the shim classes above, is a single,
|
|
14237
|
+
// process-wide singleton shared by reference across every
|
|
14238
|
+
// sandbox this library gets installed into (see
|
|
14239
|
+
// `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
|
|
14240
|
+
// already has the correct prototype chain out of the box
|
|
14241
|
+
// (`Object.getPrototypeOf(DOMException) === Function.prototype`,
|
|
14242
|
+
// not `Error`), so forcing it here isn't just unneeded but
|
|
14243
|
+
// actively wrong -- and, because it's shared, permanently
|
|
14244
|
+
// wrong for every later use of `DOMException` in the same
|
|
14245
|
+
// process (e.g. a later WPT test file's own idlharness-style
|
|
14246
|
+
// check that `DOMException` does *not* inherit from `Error`
|
|
14247
|
+
// on the class side), not just this one shim install.
|
|
14248
|
+
if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
|
|
14249
|
+
Object.setPrototypeOf(ShimDOMException, Error);
|
|
14250
|
+
Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
|
|
13934
14251
|
}
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
if (CFG.replaceNonIDBGlobals) {
|
|
13943
|
-
setNonIDBGlobals();
|
|
13944
|
-
}
|
|
14252
|
+
}
|
|
14253
|
+
if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
|
|
14254
|
+
if (CFG.addNonIDBGlobals) {
|
|
14255
|
+
// As `DOMStringList` exists per IDL (and Chrome) in the global
|
|
14256
|
+
// thread (but not in workers), we prefix the name to avoid
|
|
14257
|
+
// shadowing or conflicts
|
|
14258
|
+
setNonIDBGlobals('Shim');
|
|
13945
14259
|
}
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
return;
|
|
14260
|
+
if (CFG.replaceNonIDBGlobals) {
|
|
14261
|
+
setNonIDBGlobals();
|
|
13949
14262
|
}
|
|
13950
|
-
/* c8 ignore stop -- TS guard */
|
|
13951
|
-
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13952
14263
|
}
|
|
14264
|
+
/* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
|
|
14265
|
+
confirmed truthy just before this function (`__useShim`) was
|
|
14266
|
+
defined and immediately invoked (see the `if ('shimIndexedDB'
|
|
14267
|
+
in IDB && IDB.shimIndexedDB)` guard above), and nothing in
|
|
14268
|
+
this function's body reassigns or deletes it. Only reachable
|
|
14269
|
+
if `IDB` is some unusual object (e.g. a Proxy) whose
|
|
14270
|
+
`shimIndexedDB` property value changes between reads. */
|
|
14271
|
+
if (!IDB.shimIndexedDB) {
|
|
14272
|
+
return;
|
|
14273
|
+
}
|
|
14274
|
+
/* c8 ignore stop -- see comment above */
|
|
14275
|
+
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13953
14276
|
};
|
|
13954
14277
|
IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
|
|
13955
14278
|
CFG.DEBUG = val;
|