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
|
@@ -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) :
|
|
@@ -486,6 +486,7 @@
|
|
|
486
486
|
var ShimDOMException$1 = typeof DOMException === 'undefined'
|
|
487
487
|
// Todo: Better polyfill (if even needed here)
|
|
488
488
|
/* eslint-disable no-shadow -- Polyfill */
|
|
489
|
+
/* c8 ignore start -- Only reachable when the global `DOMException` is absent, which it never is in this project's test environment (Node always provides it) */
|
|
489
490
|
// eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
|
|
490
491
|
?
|
|
491
492
|
/**
|
|
@@ -503,9 +504,10 @@
|
|
|
503
504
|
configurable: true
|
|
504
505
|
});
|
|
505
506
|
return err;
|
|
506
|
-
}
|
|
507
|
+
}
|
|
508
|
+
/* c8 ignore stop */ : DOMException;
|
|
507
509
|
|
|
508
|
-
/** @type {WeakMap<object,
|
|
510
|
+
/** @type {WeakMap<object, EventWithProps>} */
|
|
509
511
|
var ev = new WeakMap();
|
|
510
512
|
/** @type {WeakMap<object, EventWithProps>} */
|
|
511
513
|
var evCfg = new WeakMap();
|
|
@@ -551,11 +553,12 @@
|
|
|
551
553
|
obj[prop] = {
|
|
552
554
|
configurable: true,
|
|
553
555
|
get: function get() {
|
|
554
|
-
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
556
|
+
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
557
|
+
/* c8 ignore next -- Every prop this is ever called with ('type'/'bubbles'/'cancelable'/'timeStamp'/'composed'/'detail') always ends up set on `_evCfg` or `_ev` by the time it's read, so this is unreachable */ : undefined;
|
|
555
558
|
}
|
|
556
559
|
};
|
|
557
560
|
return obj;
|
|
558
|
-
}, /** @type {
|
|
561
|
+
}, /** @type {PropertyDescriptorMap} */{}));
|
|
559
562
|
}
|
|
560
563
|
|
|
561
564
|
/**
|
|
@@ -578,8 +581,9 @@
|
|
|
578
581
|
throw new TypeError('Illegal invocation');
|
|
579
582
|
}
|
|
580
583
|
var _evCfg = getEvCfg(this);
|
|
581
|
-
var _ev = ev.get(this);
|
|
582
|
-
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
584
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
585
|
+
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
586
|
+
/* c8 ignore next -- Nothing currently sets `_evCfg.isTrusted` (see the commented-out assignment above); kept for when/if it's revived */ ? _evCfg.isTrusted : Reflect.has(_ev, 'isTrusted') && _ev.isTrusted);
|
|
583
587
|
}
|
|
584
588
|
|
|
585
589
|
/**
|
|
@@ -730,15 +734,15 @@
|
|
|
730
734
|
// this untyped alias, rather than `ShimEvent.prototype` directly, keeps
|
|
731
735
|
// that dynamic-augmentation pattern working without a `@ts-expect-error`
|
|
732
736
|
// on every single line below.
|
|
733
|
-
|
|
734
|
-
var ShimEventProto = ShimEvent.prototype;
|
|
737
|
+
|
|
738
|
+
var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
|
|
735
739
|
|
|
736
740
|
/** @this {EventWithProps} */
|
|
737
741
|
ShimEventProto.preventDefault = function preventDefault() {
|
|
738
742
|
if (!(this instanceof ShimEvent)) {
|
|
739
743
|
throw new TypeError('Illegal invocation');
|
|
740
744
|
}
|
|
741
|
-
var _ev = ev.get(this);
|
|
745
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
742
746
|
var _evCfg = getEvCfg(this);
|
|
743
747
|
if (this.cancelable && !_evCfg._passive) {
|
|
744
748
|
_evCfg.defaultPrevented = true;
|
|
@@ -936,13 +940,12 @@
|
|
|
936
940
|
return _createClass(CustomEvent);
|
|
937
941
|
}(Event);
|
|
938
942
|
var ShimCustomEvent = CustomEvent;
|
|
939
|
-
/** @type {
|
|
940
|
-
var ShimCustomEventProto = ShimCustomEvent.prototype;
|
|
943
|
+
var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
|
|
941
944
|
/**
|
|
942
945
|
* @param {string} type
|
|
943
946
|
* @param {boolean} [bubbles]
|
|
944
947
|
* @param {boolean} [cancelable]
|
|
945
|
-
* @param {
|
|
948
|
+
* @param {unknown} [detail]
|
|
946
949
|
* @this {EventWithProps}
|
|
947
950
|
*/
|
|
948
951
|
ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
|
|
@@ -954,6 +957,10 @@
|
|
|
954
957
|
throw new TypeError('Illegal invocation');
|
|
955
958
|
}
|
|
956
959
|
var _evCfg = getEvCfg(this);
|
|
960
|
+
if (_evCfg._dispatched) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
|
|
957
964
|
// @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
|
|
958
965
|
// eslint-disable-next-line prefer-rest-params -- Keep signature
|
|
959
966
|
initEventInternal(this, type, {
|
|
@@ -961,16 +968,13 @@
|
|
|
961
968
|
cancelable: cancelable,
|
|
962
969
|
detail: detail
|
|
963
970
|
}, arguments[4]);
|
|
964
|
-
if (_evCfg._dispatched) {
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
971
|
if (detail !== undefined) {
|
|
968
972
|
_evCfg.detail = detail;
|
|
969
973
|
}
|
|
970
974
|
// `initCustomEvent` deliberately excluded -- see the matching comment
|
|
971
975
|
// in `initEventInternal` for `initEvent`, above; the same reasoning
|
|
972
976
|
// applies here.
|
|
973
|
-
definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
|
|
977
|
+
definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
|
|
974
978
|
};
|
|
975
979
|
// @ts-expect-error Not part of the class body itself
|
|
976
980
|
ShimCustomEvent[Symbol.toStringTag] = 'Function';
|
|
@@ -1377,7 +1381,7 @@
|
|
|
1377
1381
|
/** @type {string[]} */
|
|
1378
1382
|
this._extraProperties.forEach(function (prop) {
|
|
1379
1383
|
if (Reflect.has(e, prop)) {
|
|
1380
|
-
/** @type {
|
|
1384
|
+
/** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
|
|
1381
1385
|
}
|
|
1382
1386
|
});
|
|
1383
1387
|
}
|
|
@@ -1456,6 +1460,7 @@
|
|
|
1456
1460
|
if (child) {
|
|
1457
1461
|
child._defaultSync = this._defaultSync;
|
|
1458
1462
|
}
|
|
1463
|
+
/* c8 ignore next -- `cfg._children` always has exactly as many entries as remaining capturing-phase steps (built from the same walk that starts this phase), so `child` is never falsy here; the `|| this` fallback is defensive only */
|
|
1459
1464
|
return (child || this)._dispatchEvent(eventCopy, false);
|
|
1460
1465
|
}
|
|
1461
1466
|
case phases.AT_TARGET:
|
|
@@ -1753,7 +1758,7 @@
|
|
|
1753
1758
|
* databaseNameLengthLimit: number|false,
|
|
1754
1759
|
* escapeNFDForDatabaseNames: boolean,
|
|
1755
1760
|
* addSQLiteExtension: boolean,
|
|
1756
|
-
* memoryDatabase: string,
|
|
1761
|
+
* memoryDatabase: string|null|undefined,
|
|
1757
1762
|
* deleteDatabaseFiles: boolean,
|
|
1758
1763
|
* databaseBasePath: string,
|
|
1759
1764
|
* sysDatabaseBasePath: string,
|
|
@@ -1896,13 +1901,27 @@
|
|
|
1896
1901
|
// Various types of in-memory databases that can auto-delete
|
|
1897
1902
|
['memoryDatabase',
|
|
1898
1903
|
/**
|
|
1899
|
-
*
|
|
1904
|
+
* `null`/`undefined` are accepted (and left unvalidated against the
|
|
1905
|
+
* regex below) specifically so this can be reset back to its
|
|
1906
|
+
* unset/disabled state after being set: unlike other `CFG`
|
|
1907
|
+
* boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
|
|
1908
|
+
* with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
|
|
1909
|
+
* usage sites check `typeof CFG.memoryDatabase === 'string'`, so
|
|
1910
|
+
* even the empty string counts as "on" (it's a distinct, valid
|
|
1911
|
+
* in-memory mode of its own -- an unnamed private temporary
|
|
1912
|
+
* database -- not an "off" state). Without this, once set to any
|
|
1913
|
+
* string there would be no value passable back through this same
|
|
1914
|
+
* validator that turns `useMemoryDatabase` false again.
|
|
1915
|
+
* @param {string|null|undefined} val
|
|
1900
1916
|
* @throws {TypeError}
|
|
1901
1917
|
* @returns {void}
|
|
1902
1918
|
*/
|
|
1903
1919
|
function (val) {
|
|
1920
|
+
if (val === null || val === undefined) {
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1904
1923
|
if (!/^(?::memory:|file::memory:(\?(?:[\0-"\$-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?(#(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*)?)?$/.test(/** @type {string} */val)) {
|
|
1905
|
-
throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a
|
|
1924
|
+
throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
|
|
1906
1925
|
}
|
|
1907
1926
|
}],
|
|
1908
1927
|
// NODE-SPECIFIC CONFIG
|
|
@@ -1956,10 +1975,7 @@
|
|
|
1956
1975
|
return arg.replaceAll(/((?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])))(?!(?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|(^|(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))((?:(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/g, function (_, unmatchedHighSurrogate, precedingLow, unmatchedLowSurrogate) {
|
|
1957
1976
|
// Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
|
|
1958
1977
|
// but Chrome having problems
|
|
1959
|
-
|
|
1960
|
-
return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1961
|
-
}
|
|
1962
|
-
return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1978
|
+
return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1963
1979
|
});
|
|
1964
1980
|
}
|
|
1965
1981
|
|
|
@@ -2626,7 +2642,8 @@
|
|
|
2626
2642
|
function createNativeDOMException(name, message) {
|
|
2627
2643
|
// @ts-expect-error It's ok
|
|
2628
2644
|
// eslint-disable-next-line new-cap -- Ok
|
|
2629
|
-
return new DOMException.prototype.constructor(message,
|
|
2645
|
+
return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
|
|
2646
|
+
name || 'DOMException');
|
|
2630
2647
|
}
|
|
2631
2648
|
|
|
2632
2649
|
// From web-platform-tests testharness.js name_code_map (though not in new spec)
|
|
@@ -2790,8 +2807,10 @@
|
|
|
2790
2807
|
*/
|
|
2791
2808
|
get: function get() {
|
|
2792
2809
|
if (!(this instanceof DOMException ||
|
|
2810
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2793
2811
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2794
2812
|
this instanceof DummyDOMException ||
|
|
2813
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2795
2814
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2796
2815
|
this instanceof Error)) {
|
|
2797
2816
|
throw new TypeError('Illegal invocation');
|
|
@@ -2850,6 +2869,7 @@
|
|
|
2850
2869
|
value: DOMException
|
|
2851
2870
|
});
|
|
2852
2871
|
|
|
2872
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2853
2873
|
// @ts-ignore We don't need all its properties; needed under some TS versions
|
|
2854
2874
|
return DOMException;
|
|
2855
2875
|
}
|
|
@@ -2862,6 +2882,7 @@
|
|
|
2862
2882
|
* @returns {Error}
|
|
2863
2883
|
*/
|
|
2864
2884
|
function createNonNativeDOMException(name, message) {
|
|
2885
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2865
2886
|
// @ts-ignore It's ok; needed under some TS versions
|
|
2866
2887
|
return new ShimNonNativeDOMException(message, name);
|
|
2867
2888
|
}
|
|
@@ -2884,6 +2905,8 @@
|
|
|
2884
2905
|
return;
|
|
2885
2906
|
}
|
|
2886
2907
|
var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
|
|
2908
|
+
|
|
2909
|
+
/* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
|
|
2887
2910
|
var method = typeof console.error === 'function' ? 'error' : 'log';
|
|
2888
2911
|
console[method](name + ': ' + message + '. ' + (msg || ''));
|
|
2889
2912
|
if (console.trace) {
|
|
@@ -3069,8 +3092,10 @@
|
|
|
3069
3092
|
*/
|
|
3070
3093
|
IDBRequest.__super = function IDBRequest() {
|
|
3071
3094
|
var _this = this;
|
|
3095
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3072
3096
|
// @ts-ignore It's ok
|
|
3073
3097
|
this[Symbol.toStringTag] = 'IDBRequest';
|
|
3098
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3074
3099
|
// @ts-ignore Part of `ShimEventTarget`
|
|
3075
3100
|
this.__setOptions({
|
|
3076
3101
|
legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
|
|
@@ -3128,10 +3153,7 @@
|
|
|
3128
3153
|
* @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
|
|
3129
3154
|
*/
|
|
3130
3155
|
IDBRequest.prototype.__getParent = function () {
|
|
3131
|
-
|
|
3132
|
-
return null;
|
|
3133
|
-
}
|
|
3134
|
-
return this.__transaction;
|
|
3156
|
+
return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
|
|
3135
3157
|
};
|
|
3136
3158
|
|
|
3137
3159
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
@@ -3190,8 +3212,10 @@
|
|
|
3190
3212
|
function IDBOpenDBRequest() {
|
|
3191
3213
|
IDBRequest.__super.call(this);
|
|
3192
3214
|
|
|
3215
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3193
3216
|
// @ts-ignore It's ok
|
|
3194
3217
|
this[Symbol.toStringTag] = 'IDBOpenDBRequest';
|
|
3218
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3195
3219
|
// @ts-ignore It's ok
|
|
3196
3220
|
this.__setOptions({
|
|
3197
3221
|
legacyOutputDidListenersThrowFlag: true,
|
|
@@ -4061,6 +4085,33 @@
|
|
|
4061
4085
|
return convertValueToKeyValueDecoded(input, null, true, true);
|
|
4062
4086
|
}
|
|
4063
4087
|
|
|
4088
|
+
/**
|
|
4089
|
+
* @param {BufferSource|ArrayBufferLike} buffer
|
|
4090
|
+
* @returns {boolean}
|
|
4091
|
+
*/
|
|
4092
|
+
function isBufferDetached(buffer) {
|
|
4093
|
+
// Use the standard property if available
|
|
4094
|
+
// @ts-expect-error - More recent API
|
|
4095
|
+
if (typeof buffer.detached === 'boolean') {
|
|
4096
|
+
// @ts-expect-error - More recent API
|
|
4097
|
+
return buffer.detached;
|
|
4098
|
+
}
|
|
4099
|
+
/* c8 ignore next 14 -- Older browsers */
|
|
4100
|
+
|
|
4101
|
+
// Fallback check via byteLength and constructor test
|
|
4102
|
+
if (buffer.byteLength !== 0) {
|
|
4103
|
+
return false;
|
|
4104
|
+
}
|
|
4105
|
+
try {
|
|
4106
|
+
// @ts-expect-error Ok
|
|
4107
|
+
// eslint-disable-next-line no-new -- Throwaway
|
|
4108
|
+
new Uint8Array(buffer);
|
|
4109
|
+
return false;
|
|
4110
|
+
} catch (_unused) {
|
|
4111
|
+
return true;
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
|
|
4064
4115
|
/**
|
|
4065
4116
|
*
|
|
4066
4117
|
* @param {BufferSource} O
|
|
@@ -4073,15 +4124,16 @@
|
|
|
4073
4124
|
var length;
|
|
4074
4125
|
if (ArrayBuffer.isView(O)) {
|
|
4075
4126
|
// Has [[ViewedArrayBuffer]] internal slot
|
|
4076
|
-
var arrayBuffer = O.buffer;
|
|
4077
|
-
if (arrayBuffer === undefined) {
|
|
4078
|
-
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was undefined.');
|
|
4079
|
-
}
|
|
4080
4127
|
offset = O.byteOffset; // [[ByteOffset]] (will also throw as desired if detached)
|
|
4081
4128
|
length = O.byteLength; // [[ByteLength]] (will also throw as desired if detached)
|
|
4082
4129
|
} else {
|
|
4083
4130
|
length = O.byteLength; // [[ArrayBufferByteLength]] on ArrayBuffer (will also throw as desired if detached)
|
|
4084
4131
|
}
|
|
4132
|
+
var arrayBuffer = ArrayBuffer.isView(O) ? O.buffer : O;
|
|
4133
|
+
if (isBufferDetached(arrayBuffer)) {
|
|
4134
|
+
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was detached.');
|
|
4135
|
+
}
|
|
4136
|
+
|
|
4085
4137
|
// const octets = new Uint8Array(input);
|
|
4086
4138
|
// const octets = types.binary.decode(types.binary.encode(input));
|
|
4087
4139
|
return new Uint8Array(
|
|
@@ -4153,7 +4205,7 @@
|
|
|
4153
4205
|
var octets;
|
|
4154
4206
|
try {
|
|
4155
4207
|
octets = getCopyBytesHeldByBufferSource(/** @type {BufferSource} */input);
|
|
4156
|
-
} catch (
|
|
4208
|
+
} catch (_unused2) {
|
|
4157
4209
|
return {
|
|
4158
4210
|
type: type,
|
|
4159
4211
|
invalid: true,
|
|
@@ -4202,8 +4254,14 @@
|
|
|
4202
4254
|
}
|
|
4203
4255
|
if (!multiEntry || !fullKeys && keys.every(function (k) {
|
|
4204
4256
|
return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
|
|
4205
|
-
}) ||
|
|
4206
|
-
|
|
4257
|
+
}) ||
|
|
4258
|
+
// `keys` holds full `{type, value}` objects here (see
|
|
4259
|
+
// `safePush` below), so -- like the sibling branch
|
|
4260
|
+
// above -- `cmp` (which expects raw `Value`s, not
|
|
4261
|
+
// decoded key objects) must compare their `.value`s,
|
|
4262
|
+
// not the wrapper objects themselves.
|
|
4263
|
+
fullKeys && keys.every(function (k) {
|
|
4264
|
+
return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
|
|
4207
4265
|
})) {
|
|
4208
4266
|
safePush(keys, fullKeys ? key : key.value);
|
|
4209
4267
|
}
|
|
@@ -4228,12 +4286,9 @@
|
|
|
4228
4286
|
{
|
|
4229
4287
|
var date = /** @type {Date} */input;
|
|
4230
4288
|
if (!Number.isNaN(date.getTime())) {
|
|
4231
|
-
return
|
|
4232
|
-
type: type,
|
|
4233
|
-
value: date.getTime()
|
|
4234
|
-
} : {
|
|
4289
|
+
return {
|
|
4235
4290
|
type: type,
|
|
4236
|
-
value: new Date(date)
|
|
4291
|
+
value: fullKeys ? date.getTime() : new Date(date)
|
|
4237
4292
|
};
|
|
4238
4293
|
}
|
|
4239
4294
|
return {
|
|
@@ -4321,10 +4376,7 @@
|
|
|
4321
4376
|
if (r.failure) {
|
|
4322
4377
|
return r;
|
|
4323
4378
|
}
|
|
4324
|
-
|
|
4325
|
-
return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
|
|
4326
|
-
}
|
|
4327
|
-
return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4379
|
+
return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4328
4380
|
}
|
|
4329
4381
|
|
|
4330
4382
|
/**
|
|
@@ -4505,10 +4557,7 @@
|
|
|
4505
4557
|
*/
|
|
4506
4558
|
function isMultiEntryMatch(encodedEntry, encodedKey) {
|
|
4507
4559
|
var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
|
|
4508
|
-
|
|
4509
|
-
return encodedKey.indexOf(encodedEntry) > 1;
|
|
4510
|
-
}
|
|
4511
|
-
return encodedKey === encodedEntry;
|
|
4560
|
+
return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
|
|
4512
4561
|
}
|
|
4513
4562
|
|
|
4514
4563
|
/**
|
|
@@ -4626,10 +4675,7 @@
|
|
|
4626
4675
|
* @returns {undefined|ValueType}
|
|
4627
4676
|
*/
|
|
4628
4677
|
function _decode(key, inArray) {
|
|
4629
|
-
|
|
4630
|
-
return undefined;
|
|
4631
|
-
}
|
|
4632
|
-
return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4678
|
+
return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4633
4679
|
}
|
|
4634
4680
|
|
|
4635
4681
|
/**
|
|
@@ -5035,10 +5081,11 @@
|
|
|
5035
5081
|
if (hasLower && hasUpper) {
|
|
5036
5082
|
sql.push('AND');
|
|
5037
5083
|
}
|
|
5038
|
-
if (hasUpper) {
|
|
5039
|
-
|
|
5040
|
-
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5084
|
+
if (!hasUpper) {
|
|
5085
|
+
return;
|
|
5041
5086
|
}
|
|
5087
|
+
sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
|
|
5088
|
+
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5042
5089
|
}
|
|
5043
5090
|
|
|
5044
5091
|
/**
|
|
@@ -5051,10 +5098,7 @@
|
|
|
5051
5098
|
if (instanceOf(value, IDBKeyRange)) {
|
|
5052
5099
|
// We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
|
|
5053
5100
|
var range = /** @type {IDBKeyRangeFull} */value;
|
|
5054
|
-
|
|
5055
|
-
return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
|
|
5056
|
-
}
|
|
5057
|
-
return range;
|
|
5101
|
+
return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
|
|
5058
5102
|
}
|
|
5059
5103
|
if (isNullish(value)) {
|
|
5060
5104
|
if (nullDisallowed) {
|
|
@@ -5099,9 +5143,11 @@
|
|
|
5099
5143
|
if (testObject.test) {
|
|
5100
5144
|
cleanInterface = true;
|
|
5101
5145
|
}
|
|
5146
|
+
/* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5102
5147
|
} catch (err) {
|
|
5103
5148
|
// Object.defineProperty does not work as intended.
|
|
5104
5149
|
}
|
|
5150
|
+
/* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5105
5151
|
}
|
|
5106
5152
|
|
|
5107
5153
|
/**
|
|
@@ -5302,6 +5348,7 @@
|
|
|
5302
5348
|
this._length = 0;
|
|
5303
5349
|
};
|
|
5304
5350
|
DOMStringList.prototype = DOMStringListAlias.prototype;
|
|
5351
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
5305
5352
|
// @ts-ignore It's ok; needed under some TS versions
|
|
5306
5353
|
return /** @type {DOMStringListFull} */new DOMStringList();
|
|
5307
5354
|
}
|
|
@@ -5601,12 +5648,14 @@
|
|
|
5601
5648
|
*/
|
|
5602
5649
|
IDBTransaction.prototype.__executeRequests = function () {
|
|
5603
5650
|
var me = this;
|
|
5651
|
+
/* c8 ignore start -- Dead code: `__executeRequests` has exactly one caller (a single `setTimeout` scheduled once per transaction), so `me.__running` can never already be `true` when this function starts. */
|
|
5604
5652
|
if (me.__running) {
|
|
5605
5653
|
if (CFG.DEBUG) {
|
|
5606
5654
|
console.log('Looks like the request set is already running', me.mode);
|
|
5607
5655
|
}
|
|
5608
5656
|
return;
|
|
5609
5657
|
}
|
|
5658
|
+
/* c8 ignore stop -- see comment above */
|
|
5610
5659
|
|
|
5611
5660
|
// The synchronous script that created this transaction (and
|
|
5612
5661
|
// synchronously queued whatever requests it wanted to) has now
|
|
@@ -5656,6 +5705,7 @@
|
|
|
5656
5705
|
queueMicrotask(cb);
|
|
5657
5706
|
return;
|
|
5658
5707
|
}
|
|
5708
|
+
/* c8 ignore start -- Browser-only path: in every automated test environment (Node's websql-configurable/better-sqlite3 driver, and the fake/mock drivers modeled after it) `__usesStandardDriver()` is always `false` (they support the 4-arg `nonstandardTransCb` signature), so `isStandardDriver` is never `true` and this branch is never reached. Only a real standard (3-arg) WebSQL driver, as found in an actual browser, would exercise it. */
|
|
5659
5709
|
try {
|
|
5660
5710
|
tx.executeSql('SELECT 1', [], function () {
|
|
5661
5711
|
cb();
|
|
@@ -5669,6 +5719,7 @@
|
|
|
5669
5719
|
// abort the transaction here.
|
|
5670
5720
|
me.__abortTransaction(/** @type {Error|DOMException} */err);
|
|
5671
5721
|
}
|
|
5722
|
+
/* c8 ignore stop -- see comment above */
|
|
5672
5723
|
}
|
|
5673
5724
|
|
|
5674
5725
|
/**
|
|
@@ -5681,21 +5732,26 @@
|
|
|
5681
5732
|
* @returns {void}
|
|
5682
5733
|
*/
|
|
5683
5734
|
function success(result, req) {
|
|
5735
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path (e.g. a driver-level failure or explicit `abort()`) racing with this request's own in-flight SQL success callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
|
|
5684
5736
|
if (me.__errored || me.__requestsFinished) {
|
|
5685
5737
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5686
5738
|
return;
|
|
5687
5739
|
}
|
|
5740
|
+
/* c8 ignore stop -- see comment above */
|
|
5688
5741
|
if (req) {
|
|
5689
5742
|
q.req = req; // Need to do this in case of cursors
|
|
5690
5743
|
}
|
|
5744
|
+
/* c8 ignore start -- Dead code: `launchQueuedOp` only ever passes `success` as a callback in the branch where `q.req` is already truthy, and a falsy `req` param here leaves `q.req` unchanged, so `q.req` can't be falsy at this point. */
|
|
5691
5745
|
if (!q.req) {
|
|
5692
|
-
// TS guard
|
|
5693
5746
|
return;
|
|
5694
5747
|
}
|
|
5748
|
+
/* c8 ignore stop -- see comment above */
|
|
5749
|
+
/* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's success callback more than once for the same queued op; not reliably reproducible without directly manipulating the SQL driver. */
|
|
5695
5750
|
if (q.req.__done) {
|
|
5696
5751
|
// Avoid continuing with aborted requests
|
|
5697
5752
|
return;
|
|
5698
5753
|
}
|
|
5754
|
+
/* c8 ignore stop -- see comment above */
|
|
5699
5755
|
q.req.__done = true;
|
|
5700
5756
|
q.req.__result = result;
|
|
5701
5757
|
q.req.__error = null;
|
|
@@ -5712,6 +5768,7 @@
|
|
|
5712
5768
|
// is what actually resets `__handlerActive`, once it's
|
|
5713
5769
|
// confirmed (across its own bounded microtask wait) that no
|
|
5714
5770
|
// such continuation queued anything.
|
|
5771
|
+
/* c8 ignore start -- Deliberately not tested: throwing from a request's `onsuccess` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
|
|
5715
5772
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
5716
5773
|
logError('Error', 'An error occurred in a success handler attached to request chain', e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
|
|
5717
5774
|
if (!me.__committed) {
|
|
@@ -5721,6 +5778,7 @@
|
|
|
5721
5778
|
return;
|
|
5722
5779
|
}
|
|
5723
5780
|
}
|
|
5781
|
+
/* c8 ignore stop -- see comment above */
|
|
5724
5782
|
runContinuationSafely(advanceAfterDispatch);
|
|
5725
5783
|
}
|
|
5726
5784
|
|
|
@@ -5732,15 +5790,19 @@
|
|
|
5732
5790
|
* @returns {void}
|
|
5733
5791
|
*/
|
|
5734
5792
|
function error() {
|
|
5793
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this request's own in-flight SQL error callback; not reliably reproducible without directly manipulating the SQL driver's callback timing. */
|
|
5735
5794
|
if (me.__errored || me.__requestsFinished) {
|
|
5736
5795
|
// We've already called "onerror", "onabort", or thrown within
|
|
5737
5796
|
// the transaction, so don't do it again.
|
|
5738
5797
|
return;
|
|
5739
5798
|
}
|
|
5799
|
+
/* c8 ignore stop -- see comment above */
|
|
5800
|
+
/* c8 ignore start -- Defensive: only reached if the SQL driver invoked this request's error callback more than once, or after its success callback already ran; not reliably reproducible without directly manipulating the SQL driver. */
|
|
5740
5801
|
if (q.req && q.req.__done) {
|
|
5741
5802
|
// Avoid continuing with aborted requests
|
|
5742
5803
|
return;
|
|
5743
5804
|
}
|
|
5805
|
+
/* c8 ignore stop -- see comment above */
|
|
5744
5806
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
5745
5807
|
args[_key] = arguments[_key];
|
|
5746
5808
|
}
|
|
@@ -5765,10 +5827,11 @@
|
|
|
5765
5827
|
}
|
|
5766
5828
|
});
|
|
5767
5829
|
q.req.addDefaultEventListener('error', function () {
|
|
5830
|
+
/* c8 ignore start -- Defensive: this default listener is skipped entirely by `eventtargeter` whenever the event was `preventDefault()`-ed (the only case in which the shared `q` variable above could have already advanced to a different, non-request queue entry by the time a default listener runs); not reachable via the public API under normal (synchronous) dispatch. */
|
|
5768
5831
|
if (!q.req) {
|
|
5769
|
-
// TS guard
|
|
5770
5832
|
return;
|
|
5771
5833
|
}
|
|
5834
|
+
/* c8 ignore stop -- see comment above */
|
|
5772
5835
|
me.__abortTransaction(q.req.__error);
|
|
5773
5836
|
});
|
|
5774
5837
|
me.__active = true;
|
|
@@ -5780,16 +5843,19 @@
|
|
|
5780
5843
|
q.req.dispatchEvent(e);
|
|
5781
5844
|
// Do not set __active or __handlerActive flags to false yet --
|
|
5782
5845
|
// see the matching comment in `success`, above.
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5846
|
+
/* 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. */
|
|
5847
|
+
if (!e.__legacyOutputDidListenersThrowError) {
|
|
5848
|
+
return;
|
|
5849
|
+
}
|
|
5850
|
+
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
|
|
5851
|
+
e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
|
|
5852
|
+
if (me.__committed) {
|
|
5853
|
+
// An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
|
|
5854
|
+
runContinuationSafely(advanceAfterDispatch);
|
|
5855
|
+
return;
|
|
5792
5856
|
}
|
|
5857
|
+
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
|
|
5858
|
+
/* c8 ignore stop -- see comment above */
|
|
5793
5859
|
}
|
|
5794
5860
|
|
|
5795
5861
|
/**
|
|
@@ -5813,10 +5879,12 @@
|
|
|
5813
5879
|
// (not reset here).
|
|
5814
5880
|
return true;
|
|
5815
5881
|
}
|
|
5882
|
+
/* c8 ignore start -- Defensive: reaching this queue entry via the normal advancement path after it was independently marked `__done` (e.g. by `__abortTransaction`'s own separate, async per-request error dispatch) requires a narrow race between that async cleanup and this synchronous advancement; not reliably reproducible without directly manipulating that timing. */
|
|
5816
5883
|
if (q.req.__done) {
|
|
5817
5884
|
// Avoid continuing with aborted requests
|
|
5818
5885
|
return false;
|
|
5819
5886
|
}
|
|
5887
|
+
/* c8 ignore stop -- see comment above */
|
|
5820
5888
|
// We're now handing off to (possibly async) work for
|
|
5821
5889
|
// this request, so the transaction is no longer active
|
|
5822
5890
|
// until its own `success`/`error` dispatch (below)
|
|
@@ -5841,18 +5909,22 @@
|
|
|
5841
5909
|
return;
|
|
5842
5910
|
}
|
|
5843
5911
|
q.op(tx, q.args, success, error, executeNextRequest);
|
|
5912
|
+
/* c8 ignore start -- Defensive: `q.op` (the SQL driver callback) is expected to report failures via its own `error`/`failure` callback argument rather than throwing synchronously; not reliably reproducible without directly forcing the driver to throw. */
|
|
5844
5913
|
} catch (e) {
|
|
5845
5914
|
error(/** @type {Error} */e);
|
|
5846
5915
|
}
|
|
5916
|
+
/* c8 ignore stop -- see comment above */
|
|
5847
5917
|
}
|
|
5848
5918
|
|
|
5849
5919
|
/**
|
|
5850
5920
|
* @returns {void}
|
|
5851
5921
|
*/
|
|
5852
5922
|
function runQueuedRequest() {
|
|
5923
|
+
/* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
|
|
5853
5924
|
if (!prepareNextRequest()) {
|
|
5854
5925
|
return;
|
|
5855
5926
|
}
|
|
5927
|
+
/* c8 ignore stop -- see comment above */
|
|
5856
5928
|
launchQueuedOp();
|
|
5857
5929
|
}
|
|
5858
5930
|
|
|
@@ -5883,9 +5955,11 @@
|
|
|
5883
5955
|
* @returns {void}
|
|
5884
5956
|
*/
|
|
5885
5957
|
function checkQueueEntry(attemptsLeft) {
|
|
5958
|
+
/* c8 ignore start -- Defensive: only reached if the transaction is independently errored/finished (e.g. an explicit `abort()`) during this function's keep-alive polling wait; not reliably reproducible without a contrived timing race. */
|
|
5886
5959
|
if (me.__errored || me.__requestsFinished) {
|
|
5887
5960
|
return;
|
|
5888
5961
|
}
|
|
5962
|
+
/* c8 ignore stop -- see comment above */
|
|
5889
5963
|
if (i < me.__requests.length) {
|
|
5890
5964
|
runQueuedRequest();
|
|
5891
5965
|
return;
|
|
@@ -5907,10 +5981,12 @@
|
|
|
5907
5981
|
* @returns {void}
|
|
5908
5982
|
*/
|
|
5909
5983
|
function executeNextRequest() {
|
|
5984
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
|
|
5910
5985
|
if (me.__errored || me.__requestsFinished) {
|
|
5911
5986
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5912
5987
|
return;
|
|
5913
5988
|
}
|
|
5989
|
+
/* c8 ignore stop -- see comment above */
|
|
5914
5990
|
i++;
|
|
5915
5991
|
if (i >= me.__requests.length) {
|
|
5916
5992
|
checkQueueEntry(keepAliveAttempts);
|
|
@@ -5945,31 +6021,34 @@
|
|
|
5945
6021
|
* @returns {void}
|
|
5946
6022
|
*/
|
|
5947
6023
|
function advanceAfterDispatch() {
|
|
6024
|
+
/* c8 ignore start -- Defensive: only reached if the transaction was independently errored/finished by a concurrent path racing with this continuation; not reliably reproducible without a contrived timing race. */
|
|
5948
6025
|
if (me.__errored || me.__requestsFinished) {
|
|
5949
6026
|
return;
|
|
5950
6027
|
}
|
|
6028
|
+
/* c8 ignore stop -- see comment above */
|
|
5951
6029
|
i++;
|
|
5952
6030
|
if (i >= me.__requests.length) {
|
|
5953
6031
|
checkQueueEntry(keepAliveAttempts);
|
|
5954
6032
|
return;
|
|
5955
6033
|
}
|
|
5956
6034
|
keepAliveAndWait(function () {
|
|
5957
|
-
if (
|
|
5958
|
-
|
|
5959
|
-
}
|
|
5960
|
-
if (!prepareNextRequest()) {
|
|
6035
|
+
/* 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. */
|
|
6036
|
+
if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
|
|
5961
6037
|
return;
|
|
5962
6038
|
}
|
|
6039
|
+
/* c8 ignore stop -- see comment above */
|
|
5963
6040
|
launchQueuedOp();
|
|
5964
6041
|
});
|
|
5965
6042
|
}
|
|
5966
6043
|
executeNextRequest();
|
|
5967
6044
|
}, function webSQLError(webSQLErr) {
|
|
6045
|
+
/* c8 ignore start -- Dead code: the underlying websql-configurable driver's `_onTransactionComplete` always passes either `null` or a genuine `Error`/`DOMException` as this callback's argument, never the literal value `true`, under any driver used by the test suite. */
|
|
5968
6046
|
// @ts-expect-error It's ok
|
|
5969
6047
|
if (webSQLErr === true) {
|
|
5970
6048
|
// Not a genuine SQL error
|
|
5971
6049
|
return;
|
|
5972
6050
|
}
|
|
6051
|
+
/* c8 ignore stop -- see comment above */
|
|
5973
6052
|
var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
|
|
5974
6053
|
me.__abortTransaction(err);
|
|
5975
6054
|
}, function () {
|
|
@@ -5980,18 +6059,25 @@
|
|
|
5980
6059
|
// Node
|
|
5981
6060
|
return;
|
|
5982
6061
|
}
|
|
6062
|
+
/* c8 ignore start -- Defensive: reaching this callback before `requestsFinished` has already set `__transactionEndCallback` (or finished) would require the underlying driver's own "queue empty" signal to race ahead of this codebase's own request-completion tracking; not observed (nor reliably reproducible) in this test suite, where the latter always wins. */
|
|
5983
6063
|
if (!me.__transactionEndCallback && !me.__requestsFinished) {
|
|
5984
6064
|
me.__transactionFinished = true;
|
|
5985
6065
|
return;
|
|
5986
6066
|
}
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
6067
|
+
/* c8 ignore stop -- see comment above */
|
|
6068
|
+
/* 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. */
|
|
6069
|
+
if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
|
|
6070
|
+
return;
|
|
5990
6071
|
}
|
|
6072
|
+
me.__transFinishedCbFired = true;
|
|
6073
|
+
me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
|
|
6074
|
+
/* c8 ignore stop -- see comment above */
|
|
5991
6075
|
}, function (currentTask, err, done, rollback, commit) {
|
|
6076
|
+
/* c8 ignore start -- Defensive: `err` here would mean the underlying WebSQL/SQLite driver reported a genuine unhandled SQL error bubbling out of this transaction's own executed statements -- every `executeSql` error callback in this codebase already handles/reports its own errors (returning `false`), so this is not reliably reproducible without mocking the SQL layer. */
|
|
5992
6077
|
if (err) {
|
|
5993
6078
|
return true;
|
|
5994
6079
|
}
|
|
6080
|
+
/* c8 ignore stop -- see comment above */
|
|
5995
6081
|
// `readonly` transactions never hold a real SQL transaction open
|
|
5996
6082
|
// (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
|
|
5997
6083
|
// them), so there's no commit/rollback round trip to defer --
|
|
@@ -6040,6 +6126,7 @@
|
|
|
6040
6126
|
*/
|
|
6041
6127
|
function complete() {
|
|
6042
6128
|
me.__completed = true;
|
|
6129
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6043
6130
|
if (CFG.DEBUG) {
|
|
6044
6131
|
console.log('Transaction completed');
|
|
6045
6132
|
}
|
|
@@ -6049,6 +6136,7 @@
|
|
|
6049
6136
|
me.dispatchEvent(evt);
|
|
6050
6137
|
me.__internal = false;
|
|
6051
6138
|
me.dispatchEvent(createEvent('__complete'));
|
|
6139
|
+
/* c8 ignore start -- Deliberately not tested: throwing from an `oncomplete`/`__complete` handler to exercise this branch would surface as an uncaught error through this test suite's `window.onerror` shim, which (per `retention-spec.js`'s `assertLater` comment) can trigger unbounded recursion here; not safe to trigger directly. */
|
|
6052
6140
|
} catch (e) {
|
|
6053
6141
|
me.__internal = false;
|
|
6054
6142
|
// An error occurred in the "oncomplete" handler.
|
|
@@ -6056,6 +6144,7 @@
|
|
|
6056
6144
|
// (this may seem odd/bad, but it's how all native IndexedDB implementations work)
|
|
6057
6145
|
me.__errored = true;
|
|
6058
6146
|
throw e;
|
|
6147
|
+
/* c8 ignore stop -- see comment above */
|
|
6059
6148
|
} finally {
|
|
6060
6149
|
activeTransactions.delete(me);
|
|
6061
6150
|
me.__storeHandles = {};
|
|
@@ -6063,10 +6152,12 @@
|
|
|
6063
6152
|
}
|
|
6064
6153
|
}
|
|
6065
6154
|
if (me.mode === 'readwrite' || me.mode === 'readonly') {
|
|
6155
|
+
/* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described above (also `c8 ignore`d there), which is not observed in this test suite. */
|
|
6066
6156
|
if (me.__transactionFinished) {
|
|
6067
6157
|
complete();
|
|
6068
6158
|
return;
|
|
6069
6159
|
}
|
|
6160
|
+
/* c8 ignore stop -- see comment above */
|
|
6070
6161
|
me.__transactionEndCallback = complete;
|
|
6071
6162
|
// The underlying SQL driver's own "queue empty" check
|
|
6072
6163
|
// (`nonstandardTransCb`, above) typically already ran and
|
|
@@ -6102,6 +6193,7 @@
|
|
|
6102
6193
|
IDBTransaction.prototype.__createRequest = function (source) {
|
|
6103
6194
|
var me = this;
|
|
6104
6195
|
var request = IDBRequest.__createInstance();
|
|
6196
|
+
/* c8 ignore next -- Defensive: every call site (via `__addToTransactionQueue` or directly) always passes an explicit `source`, so the `me.db` fallback is not reachable via the public API. */
|
|
6105
6197
|
request.__source = source !== undefined ? source : me.db;
|
|
6106
6198
|
request.__transaction = me;
|
|
6107
6199
|
return request;
|
|
@@ -6171,9 +6263,11 @@
|
|
|
6171
6263
|
* @returns {void}
|
|
6172
6264
|
*/
|
|
6173
6265
|
IDBTransaction.prototype.__assertActive = function () {
|
|
6266
|
+
/* c8 ignore start -- Defensive: every call site (via `__addToTransactionQueue`/`__addNonRequestToTransactionQueue`) either already performed the static `IDBTransaction.__assertActive(tx)` check synchronously just beforehand, or queues against a transaction just created fresh (necessarily active), so this redundant instance-level check is not reachable via the public API. */
|
|
6174
6267
|
if (!this.__active || !this.__handlerActive || this.__committed) {
|
|
6175
6268
|
throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
|
|
6176
6269
|
}
|
|
6270
|
+
/* c8 ignore stop -- see comment above */
|
|
6177
6271
|
};
|
|
6178
6272
|
|
|
6179
6273
|
/**
|
|
@@ -6187,6 +6281,7 @@
|
|
|
6187
6281
|
}
|
|
6188
6282
|
};
|
|
6189
6283
|
|
|
6284
|
+
/* c8 ignore start -- Dead code: this instance method has no callers anywhere in src/ (confirmed via grep); every real call site uses the static `IDBTransaction.__assertVersionChange(tx)` directly instead. */
|
|
6190
6285
|
/**
|
|
6191
6286
|
* @this {IDBTransactionFull}
|
|
6192
6287
|
* @returns {void}
|
|
@@ -6194,6 +6289,7 @@
|
|
|
6194
6289
|
IDBTransaction.prototype.__assertVersionChange = function () {
|
|
6195
6290
|
IDBTransaction.__assertVersionChange(this);
|
|
6196
6291
|
};
|
|
6292
|
+
/* c8 ignore stop -- see comment above */
|
|
6197
6293
|
|
|
6198
6294
|
/**
|
|
6199
6295
|
* Returns the specified object store.
|
|
@@ -6215,9 +6311,12 @@
|
|
|
6215
6311
|
throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
|
|
6216
6312
|
}
|
|
6217
6313
|
var store = me.db.__objectStores[objectStoreName];
|
|
6314
|
+
/* c8 ignore start -- Defensive: `me.__objectStoreNames` (checked just above) and `me.db.__objectStores` are always kept in sync by every code path that adds/renames/removes a store, so a name that passes the participation check above should always also be found here; not reliably reproducible via the public API. */
|
|
6218
6315
|
if (!store) {
|
|
6219
6316
|
throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
|
|
6220
6317
|
}
|
|
6318
|
+
/* c8 ignore stop -- see comment above */
|
|
6319
|
+
|
|
6221
6320
|
if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
|
|
6222
6321
|
// These latter conditions are to allow store
|
|
6223
6322
|
// recreation to create new clone object
|
|
@@ -6236,10 +6335,12 @@
|
|
|
6236
6335
|
IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
6237
6336
|
var me = this;
|
|
6238
6337
|
logError('Error', 'An error occurred in a transaction', err);
|
|
6338
|
+
/* c8 ignore start -- Defensive re-entrancy guard: only reached if `__abortTransaction` is invoked a second time on the same transaction after `__errored` is already `true` (e.g. two independent internal error paths racing); not reliably reproducible without a contrived timing race. */
|
|
6239
6339
|
if (me.__errored) {
|
|
6240
6340
|
// We've already called "onerror", "onabort", or thrown, so don't do it again.
|
|
6241
6341
|
return;
|
|
6242
6342
|
}
|
|
6343
|
+
/* c8 ignore stop -- see comment above */
|
|
6243
6344
|
me.__errored = true;
|
|
6244
6345
|
if (me.mode === 'versionchange') {
|
|
6245
6346
|
// Steps for aborting an upgrade transaction
|
|
@@ -6269,19 +6370,16 @@
|
|
|
6269
6370
|
if (err !== null) {
|
|
6270
6371
|
me.__error = err;
|
|
6271
6372
|
}
|
|
6373
|
+
|
|
6374
|
+
/* c8 ignore start -- Defense in depth: `err` is only ever `null` here via `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)` call, which now checks `__requestsFinished` itself first and throws `InvalidStateError` synchronously before ever reaching this point -- so this guard should not see a non-null `err` in practice. */
|
|
6272
6375
|
if (me.__requestsFinished && err !== null) {
|
|
6273
6376
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
6274
|
-
// So throw the error instead.
|
|
6275
|
-
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
6276
|
-
// call, which now checks `__requestsFinished` itself first and
|
|
6277
|
-
// throws `InvalidStateError` synchronously before ever reaching
|
|
6278
|
-
// this point -- so this guard is just defense in depth against
|
|
6279
|
-
// `err` somehow being `null` some other way, not something this
|
|
6280
|
-
// path should see in practice.
|
|
6377
|
+
// So throw the error instead.
|
|
6281
6378
|
setTimeout(function () {
|
|
6282
6379
|
throw err;
|
|
6283
6380
|
}, 0);
|
|
6284
6381
|
}
|
|
6382
|
+
/* c8 ignore stop -- see comment above */
|
|
6285
6383
|
|
|
6286
6384
|
/**
|
|
6287
6385
|
* @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
|
|
@@ -6290,13 +6388,17 @@
|
|
|
6290
6388
|
*/
|
|
6291
6389
|
function abort(tx, errOrResult) {
|
|
6292
6390
|
if (!tx) {
|
|
6391
|
+
/* c8 ignore next -- Debug-only log; only reached via the no-op `abort()` calls below (rare paths), and requires `CFG.DEBUG` to have any effect anyway. */
|
|
6293
6392
|
if (CFG.DEBUG) {
|
|
6294
6393
|
console.log('Rollback not possible due to missing transaction', me);
|
|
6295
6394
|
}
|
|
6395
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver erroring on the manual `ROLLBACK` executed below (with a result object exposing a numeric `code`) is not reliably reproducible without mocking the SQL layer. */
|
|
6296
6396
|
} else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
|
|
6297
6397
|
if (CFG.DEBUG) {
|
|
6298
6398
|
console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
|
|
6299
6399
|
}
|
|
6400
|
+
/* c8 ignore stop -- see comment above */
|
|
6401
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6300
6402
|
} else if (CFG.DEBUG) {
|
|
6301
6403
|
console.log('Rollback succeeded', me);
|
|
6302
6404
|
}
|
|
@@ -6312,10 +6414,11 @@
|
|
|
6312
6414
|
// behaves first-in-first-out with the same timeout so we could
|
|
6313
6415
|
// just use a `forEach`.
|
|
6314
6416
|
return promises.then(function () {
|
|
6417
|
+
/* c8 ignore start -- Dead code: the preceding `.filter()` only keeps entries with a truthy `q.req`, and nothing ever resets `q.req` back to a falsy value afterward, so this invariant can't actually be violated. */
|
|
6315
6418
|
if (!q.req) {
|
|
6316
|
-
// TS guard
|
|
6317
6419
|
throw new Error('Missing request');
|
|
6318
6420
|
}
|
|
6421
|
+
/* c8 ignore stop -- see comment above */
|
|
6319
6422
|
q.req.__done = true;
|
|
6320
6423
|
q.req.__result = undefined;
|
|
6321
6424
|
q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
|
|
@@ -6326,10 +6429,11 @@
|
|
|
6326
6429
|
return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
|
|
6327
6430
|
function (resolve) {
|
|
6328
6431
|
setTimeout(function () {
|
|
6432
|
+
/* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
|
|
6329
6433
|
if (!q.req) {
|
|
6330
|
-
// TS guard
|
|
6331
6434
|
throw new Error('Missing request');
|
|
6332
6435
|
}
|
|
6436
|
+
/* c8 ignore stop -- see comment above */
|
|
6333
6437
|
q.req.dispatchEvent(reqEvt); // No need to catch errors
|
|
6334
6438
|
resolve();
|
|
6335
6439
|
}, 0);
|
|
@@ -6349,10 +6453,12 @@
|
|
|
6349
6453
|
releaseFinishedTransaction(me);
|
|
6350
6454
|
}, 0);
|
|
6351
6455
|
return undefined;
|
|
6456
|
+
/* c8 ignore start -- Diagnostic safety net: nothing in the preceding promise chain normally rejects (the only throws it could catch are the dead invariant-violation checks above), so this handler is not reachable in practice. */
|
|
6352
6457
|
}).catch(function (err) {
|
|
6353
6458
|
console.log('Abort error');
|
|
6354
6459
|
throw err;
|
|
6355
6460
|
});
|
|
6461
|
+
/* c8 ignore stop -- see comment above */
|
|
6356
6462
|
}
|
|
6357
6463
|
me.__transFinishedCb(true, function (rollback) {
|
|
6358
6464
|
if (rollback && me.__tx) {
|
|
@@ -6360,20 +6466,24 @@
|
|
|
6360
6466
|
// rollback automatically), but for Node.js, etc., we give chance for
|
|
6361
6467
|
// manual aborts which would otherwise not work.
|
|
6362
6468
|
if (me.mode === 'readwrite') {
|
|
6469
|
+
/* c8 ignore start -- Dead code in practice: `__transactionFinished` is only ever set by the driver-queue-idle-races-ahead scenario described earlier in this file (also `c8 ignore`d there), which is not observed in this test suite. */
|
|
6363
6470
|
if (me.__transactionFinished) {
|
|
6364
6471
|
abort();
|
|
6365
6472
|
return;
|
|
6366
6473
|
}
|
|
6474
|
+
/* c8 ignore stop -- see comment above */
|
|
6367
6475
|
me.__transactionEndCallback = abort;
|
|
6368
6476
|
return;
|
|
6369
6477
|
}
|
|
6370
6478
|
try {
|
|
6371
6479
|
me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
|
|
6480
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
|
|
6372
6481
|
} catch (err) {
|
|
6373
6482
|
// Browser errs when transaction has ended and since it most likely already erred here,
|
|
6374
6483
|
// we call to abort
|
|
6375
6484
|
abort();
|
|
6376
6485
|
}
|
|
6486
|
+
/* c8 ignore stop -- see comment above */
|
|
6377
6487
|
} else {
|
|
6378
6488
|
abort(null, {
|
|
6379
6489
|
code: 0
|
|
@@ -6391,6 +6501,7 @@
|
|
|
6391
6501
|
if (!(me instanceof IDBTransaction)) {
|
|
6392
6502
|
throw new TypeError('Illegal invocation');
|
|
6393
6503
|
}
|
|
6504
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6394
6505
|
if (CFG.DEBUG) {
|
|
6395
6506
|
console.log('The transaction was aborted', me);
|
|
6396
6507
|
}
|
|
@@ -6422,6 +6533,7 @@
|
|
|
6422
6533
|
if (!me.__active || !me.__handlerActive || me.__committed) {
|
|
6423
6534
|
throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
|
|
6424
6535
|
}
|
|
6536
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6425
6537
|
if (CFG.DEBUG) {
|
|
6426
6538
|
console.log('The transaction was explicitly committed', me);
|
|
6427
6539
|
}
|
|
@@ -6464,6 +6576,7 @@
|
|
|
6464
6576
|
};
|
|
6465
6577
|
|
|
6466
6578
|
// object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
|
|
6579
|
+
/* c8 ignore start -- Dead code: this function has no callers anywhere in src/ (confirmed via grep); object store methods use `IDBTransaction.__assertActive`/`__assertNotFinished` directly instead. */
|
|
6467
6580
|
/**
|
|
6468
6581
|
*
|
|
6469
6582
|
* @param {IDBTransactionFull} tx
|
|
@@ -6479,6 +6592,7 @@
|
|
|
6479
6592
|
throw err;
|
|
6480
6593
|
}
|
|
6481
6594
|
};
|
|
6595
|
+
/* c8 ignore stop -- see comment above */
|
|
6482
6596
|
|
|
6483
6597
|
/**
|
|
6484
6598
|
*
|
|
@@ -7576,7 +7690,7 @@
|
|
|
7576
7690
|
return Number.isNaN(t) ? "NaN" : t;
|
|
7577
7691
|
},
|
|
7578
7692
|
revive: function revive(e) {
|
|
7579
|
-
return "NaN" === e ?
|
|
7693
|
+
return new Date("NaN" === e ? NaN : e);
|
|
7580
7694
|
}
|
|
7581
7695
|
}
|
|
7582
7696
|
},
|
|
@@ -8436,9 +8550,12 @@
|
|
|
8436
8550
|
}).find(function (preset) {
|
|
8437
8551
|
return preset && !Array.isArray(preset) && 'filelist' in preset;
|
|
8438
8552
|
});
|
|
8439
|
-
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8440
|
-
|
|
8441
|
-
var
|
|
8553
|
+
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8554
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8555
|
+
var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
|
|
8556
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
|
|
8557
|
+
var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
|
|
8558
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
|
|
8442
8559
|
var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
|
|
8443
8560
|
/**
|
|
8444
8561
|
* @param {unknown} x
|
|
@@ -8446,10 +8563,7 @@
|
|
|
8446
8563
|
* @returns {boolean}
|
|
8447
8564
|
*/
|
|
8448
8565
|
test: function test(x, state) {
|
|
8449
|
-
|
|
8450
|
-
return x instanceof FileList;
|
|
8451
|
-
}
|
|
8452
|
-
return typeof origTest === 'function' ? origTest(x, state) : false;
|
|
8566
|
+
return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
|
|
8453
8567
|
},
|
|
8454
8568
|
/**
|
|
8455
8569
|
* @param {unknown} x
|
|
@@ -8460,10 +8574,12 @@
|
|
|
8460
8574
|
if (typeof FileList !== 'undefined') {
|
|
8461
8575
|
return Reflect.construct(FileList, [x]);
|
|
8462
8576
|
}
|
|
8577
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
|
|
8463
8578
|
return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
|
|
8464
8579
|
}
|
|
8465
|
-
}) : undefined;
|
|
8466
|
-
var typeson = new Typeson().register([fe,
|
|
8580
|
+
}) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8581
|
+
var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
|
|
8582
|
+
customFileList ? {
|
|
8467
8583
|
filelist: customFileList
|
|
8468
8584
|
} : {}]);
|
|
8469
8585
|
|
|
@@ -8619,7 +8735,6 @@
|
|
|
8619
8735
|
* __unique: boolean,
|
|
8620
8736
|
* __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
8621
8737
|
* __keyPath: import('./Key.js').KeyPath,
|
|
8622
|
-
* __recreated?: boolean,
|
|
8623
8738
|
* __fetchIndexData: (
|
|
8624
8739
|
* range: Query,
|
|
8625
8740
|
* opType: "value"|"key"|"count",
|
|
@@ -8713,6 +8828,7 @@
|
|
|
8713
8828
|
storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
|
|
8714
8829
|
me.__pendingName = oldName;
|
|
8715
8830
|
var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
|
|
8831
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
8716
8832
|
// @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
|
|
8717
8833
|
_toConsumableArray(objectStore.indexNames).filter(function (indexName) {
|
|
8718
8834
|
return indexName !== newName;
|
|
@@ -8764,7 +8880,7 @@
|
|
|
8764
8880
|
}
|
|
8765
8881
|
});
|
|
8766
8882
|
/** @type {const} */
|
|
8767
|
-
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'
|
|
8883
|
+
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
|
|
8768
8884
|
// @ts-expect-error Why is this type "never"?
|
|
8769
8885
|
idx[p] = index[p];
|
|
8770
8886
|
});
|
|
@@ -8796,11 +8912,12 @@
|
|
|
8796
8912
|
var transaction = store.transaction;
|
|
8797
8913
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8798
8914
|
transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
|
|
8799
|
-
var columnExists = idx &&
|
|
8915
|
+
var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
|
|
8800
8916
|
|
|
8801
8917
|
/** @type {{[key: string]: boolean}} */
|
|
8802
8918
|
var indexValues = {};
|
|
8803
8919
|
|
|
8920
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8804
8921
|
/**
|
|
8805
8922
|
* @param {WebSQLTransaction} tx
|
|
8806
8923
|
* @param {(Error & {code?: number})} err
|
|
@@ -8809,6 +8926,7 @@
|
|
|
8809
8926
|
function error(tx, err) {
|
|
8810
8927
|
failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
|
|
8811
8928
|
}
|
|
8929
|
+
/* c8 ignore stop -- see comment above */
|
|
8812
8930
|
|
|
8813
8931
|
/**
|
|
8814
8932
|
* @param {WebSQLTransaction} tx
|
|
@@ -8858,12 +8976,6 @@
|
|
|
8858
8976
|
} else {
|
|
8859
8977
|
delete index.__pendingCreate;
|
|
8860
8978
|
delete indexHandle.__pendingCreate;
|
|
8861
|
-
if (index.__deleted) {
|
|
8862
|
-
delete index.__deleted;
|
|
8863
|
-
delete indexHandle.__deleted;
|
|
8864
|
-
index.__recreated = true;
|
|
8865
|
-
indexHandle.__recreated = true;
|
|
8866
|
-
}
|
|
8867
8979
|
indexValues = {};
|
|
8868
8980
|
success(store);
|
|
8869
8981
|
}
|
|
@@ -8872,7 +8984,7 @@
|
|
|
8872
8984
|
}, /** @type {SqlErrorCallback} */error);
|
|
8873
8985
|
}
|
|
8874
8986
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
8875
|
-
var escapedIndexNameSQL = escapeIndexNameForSQL(
|
|
8987
|
+
var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
|
|
8876
8988
|
|
|
8877
8989
|
/**
|
|
8878
8990
|
* @param {WebSQLTransaction} tx
|
|
@@ -8924,6 +9036,7 @@
|
|
|
8924
9036
|
var transaction = store.transaction;
|
|
8925
9037
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8926
9038
|
transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
|
|
9039
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8927
9040
|
/**
|
|
8928
9041
|
* @param {WebSQLTransaction} tx
|
|
8929
9042
|
* @param {(Error & {code?: number})} err
|
|
@@ -8932,6 +9045,7 @@
|
|
|
8932
9045
|
function error(tx, err) {
|
|
8933
9046
|
failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
|
|
8934
9047
|
}
|
|
9048
|
+
/* c8 ignore stop -- see comment above */
|
|
8935
9049
|
|
|
8936
9050
|
/**
|
|
8937
9051
|
* @returns {void}
|
|
@@ -8940,7 +9054,6 @@
|
|
|
8940
9054
|
// Update the object store's index list
|
|
8941
9055
|
IDBIndex.__updateIndexList(store, tx, function (store) {
|
|
8942
9056
|
delete index.__pendingDelete;
|
|
8943
|
-
delete index.__recreated;
|
|
8944
9057
|
index.__deleted = true;
|
|
8945
9058
|
if (indexHandle) {
|
|
8946
9059
|
indexHandle.__deleted = true;
|
|
@@ -9001,20 +9114,18 @@
|
|
|
9001
9114
|
* @param {Query} range
|
|
9002
9115
|
* @param {"value"|"key"|"count"} opType
|
|
9003
9116
|
* @param {boolean} nullDisallowed
|
|
9004
|
-
* @param {number} [count]
|
|
9005
9117
|
* @this {IDBIndexFull}
|
|
9006
9118
|
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
9007
9119
|
*/
|
|
9008
|
-
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed
|
|
9120
|
+
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
|
|
9009
9121
|
var me = this;
|
|
9010
|
-
if (count !== undefined) {
|
|
9011
|
-
count = enforceRange(count, 'unsigned long');
|
|
9012
|
-
}
|
|
9013
9122
|
IDBIndex.__invalidStateIfDeleted(me);
|
|
9014
9123
|
IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
|
|
9124
|
+
/* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
|
|
9015
9125
|
if (me.objectStore.__deleted) {
|
|
9016
9126
|
throw createDOMException('InvalidStateError', "This index's object store has been deleted");
|
|
9017
9127
|
}
|
|
9128
|
+
/* c8 ignore stop -- see comment above */
|
|
9018
9129
|
IDBTransaction.__assertActive(me.objectStore.transaction);
|
|
9019
9130
|
if (nullDisallowed && isNullish(range)) {
|
|
9020
9131
|
throw createDOMException('DataError', 'No key or range was specified');
|
|
@@ -9024,7 +9135,7 @@
|
|
|
9024
9135
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
9025
9136
|
args[_key] = arguments[_key];
|
|
9026
9137
|
}
|
|
9027
|
-
executeFetchIndexData.apply(void 0,
|
|
9138
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
|
|
9028
9139
|
}, undefined, me);
|
|
9029
9140
|
};
|
|
9030
9141
|
|
|
@@ -9183,13 +9294,16 @@
|
|
|
9183
9294
|
var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
|
|
9184
9295
|
return colInfo.join(' ');
|
|
9185
9296
|
});
|
|
9297
|
+
/* c8 ignore next -- Defensive: the sole caller always supplies a non-empty `colInfoToPreserveArr` (seeded with `key`/`value` column info), so the empty-array fallback is unreachable. */
|
|
9186
9298
|
var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
|
|
9299
|
+
/* c8 ignore next -- Defensive: see comment above. */
|
|
9187
9300
|
var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
|
|
9188
9301
|
|
|
9189
9302
|
// We could adapt the approach at https://stackoverflow.com/a/8430746/271577
|
|
9190
9303
|
// to make the approach reusable without passing column names, but it is a bit fragile
|
|
9191
9304
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
9192
9305
|
store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
|
|
9306
|
+
/* c8 ignore start -- Defensive: only reached if one of the chained `CREATE TABLE`/`INSERT`/`DROP TABLE`/`ALTER TABLE` statements below fails, which is not reliably reproducible without mocking the SQL layer. */
|
|
9193
9307
|
/**
|
|
9194
9308
|
* @param {WebSQLTransaction} tx
|
|
9195
9309
|
* @param {(Error & {code?: number})} err
|
|
@@ -9198,6 +9312,7 @@
|
|
|
9198
9312
|
function sqlError(tx, err) {
|
|
9199
9313
|
error(err);
|
|
9200
9314
|
}
|
|
9315
|
+
/* c8 ignore stop -- see comment above */
|
|
9201
9316
|
/**
|
|
9202
9317
|
* @returns {void}
|
|
9203
9318
|
*/
|
|
@@ -9206,8 +9321,14 @@
|
|
|
9206
9321
|
cb(tx, success);
|
|
9207
9322
|
return;
|
|
9208
9323
|
}
|
|
9324
|
+
/* c8 ignore start -- Defensive: `__renameIndex`'s only caller (the `IDBIndex.prototype.name` setter) always supplies a `cb`, so this fallback is dead with the current call graph. */
|
|
9209
9325
|
success();
|
|
9210
9326
|
}
|
|
9327
|
+
/* c8 ignore stop -- see comment above */
|
|
9328
|
+
if (!CFG.useSQLiteIndexes) {
|
|
9329
|
+
finish();
|
|
9330
|
+
return;
|
|
9331
|
+
}
|
|
9211
9332
|
// See https://www.sqlite.org/lang_altertable.html#otheralter
|
|
9212
9333
|
// We don't query for indexes as we already have the info
|
|
9213
9334
|
// This approach has the advantage of auto-deleting indexes via the DROP TABLE
|
|
@@ -9231,10 +9352,6 @@
|
|
|
9231
9352
|
console.log(sql);
|
|
9232
9353
|
}
|
|
9233
9354
|
tx.executeSql(sql, [], function (tx) {
|
|
9234
|
-
if (!CFG.useSQLiteIndexes) {
|
|
9235
|
-
finish();
|
|
9236
|
-
return;
|
|
9237
|
-
}
|
|
9238
9355
|
var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
|
|
9239
9356
|
.map(function (escapedIndexNameSQL) {
|
|
9240
9357
|
return new SyncPromise(function (resolve, reject) {
|
|
@@ -9243,13 +9360,16 @@
|
|
|
9243
9360
|
// if (CFG.DEBUG) { console.log(sql); }
|
|
9244
9361
|
// tx.executeSql(sql, [], function () {
|
|
9245
9362
|
var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
|
|
9363
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
9246
9364
|
if (CFG.DEBUG) {
|
|
9247
9365
|
console.log(sql);
|
|
9248
9366
|
}
|
|
9249
|
-
tx.executeSql(sql, [], resolve,
|
|
9367
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9368
|
+
/** @type {SqlErrorCallback} */
|
|
9250
9369
|
function (tx, err) {
|
|
9251
9370
|
reject(err);
|
|
9252
|
-
}
|
|
9371
|
+
}
|
|
9372
|
+
/* c8 ignore stop -- see comment above */);
|
|
9253
9373
|
// }, function (tx, err) {
|
|
9254
9374
|
// reject(err);
|
|
9255
9375
|
// });
|
|
@@ -9267,19 +9387,25 @@
|
|
|
9267
9387
|
if (CFG.DEBUG) {
|
|
9268
9388
|
console.log(sql);
|
|
9269
9389
|
}
|
|
9270
|
-
tx.executeSql(sql, [], resolve,
|
|
9390
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9391
|
+
/** @type {SqlErrorCallback} */
|
|
9271
9392
|
function (tx, err) {
|
|
9272
9393
|
reject(err);
|
|
9273
|
-
}
|
|
9274
|
-
|
|
9394
|
+
}
|
|
9395
|
+
/* c8 ignore stop -- see comment above */);
|
|
9396
|
+
}, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9397
|
+
/** @type {SqlErrorCallback} */
|
|
9275
9398
|
function (tx, err) {
|
|
9276
9399
|
reject(err);
|
|
9277
|
-
}
|
|
9400
|
+
}
|
|
9401
|
+
/* c8 ignore stop -- see comment above */);
|
|
9278
9402
|
}));
|
|
9279
9403
|
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
|
|
9280
9404
|
error).catch(function (err) {
|
|
9405
|
+
/* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
|
|
9281
9406
|
console.log('Index rename error');
|
|
9282
9407
|
throw err;
|
|
9408
|
+
/* c8 ignore stop -- see comment above */
|
|
9283
9409
|
});
|
|
9284
9410
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
9285
9411
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
@@ -9308,7 +9434,6 @@
|
|
|
9308
9434
|
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
9309
9435
|
|
|
9310
9436
|
/**
|
|
9311
|
-
* @param {number|null} count
|
|
9312
9437
|
* @param {boolean} unboundedDisallowed
|
|
9313
9438
|
* @param {IDBIndexFull} index
|
|
9314
9439
|
* @param {boolean} hasKey
|
|
@@ -9325,12 +9450,9 @@
|
|
|
9325
9450
|
* @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
|
|
9326
9451
|
* @returns {void}
|
|
9327
9452
|
*/
|
|
9328
|
-
function executeFetchIndexData(
|
|
9453
|
+
function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
|
|
9329
9454
|
if (unboundedDisallowed) {
|
|
9330
|
-
|
|
9331
|
-
}
|
|
9332
|
-
if (count) {
|
|
9333
|
-
sql.push('LIMIT', String(count));
|
|
9455
|
+
sql.push('LIMIT', '1');
|
|
9334
9456
|
}
|
|
9335
9457
|
var isCount = opType === 'count';
|
|
9336
9458
|
if (CFG.DEBUG) {
|
|
@@ -9368,41 +9490,48 @@
|
|
|
9368
9490
|
var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
|
|
9369
9491
|
var encodedKey = _encode(range, index.multiEntry);
|
|
9370
9492
|
var _loop = function _loop() {
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
record = row;
|
|
9391
|
-
} else if (!hasKey && !multiChecks) {
|
|
9392
|
-
if (rowKey !== undefined) {
|
|
9393
|
-
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9493
|
+
var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
|
|
9494
|
+
var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
|
|
9495
|
+
_decode(row[escapedIndexNameForKeyCol]);
|
|
9496
|
+
var record;
|
|
9497
|
+
if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
|
|
9498
|
+
/**
|
|
9499
|
+
* @param {import('./Key.js').ValueType} check
|
|
9500
|
+
* @returns {boolean}
|
|
9501
|
+
*/
|
|
9502
|
+
function (check) {
|
|
9503
|
+
return rowKey.includes(check);
|
|
9504
|
+
}) ||
|
|
9505
|
+
// More precise than our SQL
|
|
9506
|
+
isMultiEntryMatch(
|
|
9507
|
+
// Added `JSON.stringify` as was having problems with
|
|
9508
|
+
// `JSON.stringify` encoding added to nested
|
|
9509
|
+
// array keys
|
|
9510
|
+
JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
|
|
9511
|
+
recordCount++;
|
|
9394
9512
|
record = row;
|
|
9513
|
+
} else if (!hasKey && !multiChecks) {
|
|
9514
|
+
if (rowKey !== undefined) {
|
|
9515
|
+
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9516
|
+
record = row;
|
|
9517
|
+
}
|
|
9395
9518
|
}
|
|
9396
|
-
|
|
9397
|
-
|
|
9519
|
+
/* 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. */
|
|
9520
|
+
if (!record) {
|
|
9521
|
+
return 0; // continue
|
|
9522
|
+
}
|
|
9523
|
+
/* c8 ignore stop -- see comment above */
|
|
9524
|
+
|
|
9398
9525
|
records.push(decode$1(record));
|
|
9399
9526
|
if (unboundedDisallowed) {
|
|
9400
9527
|
return 1; // break
|
|
9401
9528
|
}
|
|
9402
|
-
}
|
|
9403
|
-
|
|
9529
|
+
},
|
|
9530
|
+
_ret;
|
|
9404
9531
|
for (var i = 0; i < data.rows.length; i++) {
|
|
9405
|
-
|
|
9532
|
+
_ret = _loop();
|
|
9533
|
+
if (_ret === 0) continue;
|
|
9534
|
+
if (_ret === 1) break;
|
|
9406
9535
|
}
|
|
9407
9536
|
} else {
|
|
9408
9537
|
for (var _i = 0; _i < data.rows.length; _i++) {
|
|
@@ -9416,8 +9545,16 @@
|
|
|
9416
9545
|
if (isCount) {
|
|
9417
9546
|
success(recordCount);
|
|
9418
9547
|
} else if (recordCount === 0) {
|
|
9548
|
+
// `unboundedDisallowed` is always `true` here: this function is only reached (for
|
|
9549
|
+
// non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
|
|
9550
|
+
// through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
|
|
9551
|
+
// different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
|
|
9552
|
+
// (returning `[]` here) is unreachable given current callers.
|
|
9553
|
+
/* c8 ignore next -- see comment above */
|
|
9419
9554
|
success(unboundedDisallowed ? undefined : []);
|
|
9420
9555
|
} else {
|
|
9556
|
+
// `unboundedDisallowed` is always `true` here; see comment above.
|
|
9557
|
+
/* c8 ignore next -- see comment above */
|
|
9421
9558
|
success(unboundedDisallowed ? records[0] : records);
|
|
9422
9559
|
}
|
|
9423
9560
|
}, /** @type {SqlErrorCallback} */error);
|
|
@@ -9661,6 +9798,7 @@
|
|
|
9661
9798
|
tx.executeSql(sql, sqlValues, function (tx) {
|
|
9662
9799
|
// This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
|
|
9663
9800
|
var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
|
|
9801
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
|
|
9664
9802
|
if (CFG.DEBUG) {
|
|
9665
9803
|
console.log(sql);
|
|
9666
9804
|
}
|
|
@@ -9669,8 +9807,10 @@
|
|
|
9669
9807
|
success();
|
|
9670
9808
|
});
|
|
9671
9809
|
}, function (tx, err) {
|
|
9810
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9672
9811
|
error(err);
|
|
9673
9812
|
return false;
|
|
9813
|
+
/* c8 ignore stop -- see comment above */
|
|
9674
9814
|
});
|
|
9675
9815
|
});
|
|
9676
9816
|
}
|
|
@@ -9744,6 +9884,7 @@
|
|
|
9744
9884
|
storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
|
|
9745
9885
|
}
|
|
9746
9886
|
transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
|
|
9887
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9747
9888
|
/**
|
|
9748
9889
|
* @param {WebSQLTransaction} tx
|
|
9749
9890
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9756,6 +9897,8 @@
|
|
|
9756
9897
|
failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
|
|
9757
9898
|
return false;
|
|
9758
9899
|
}
|
|
9900
|
+
/* c8 ignore stop -- see comment above */
|
|
9901
|
+
|
|
9759
9902
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
9760
9903
|
// key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
|
|
9761
9904
|
var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
|
|
@@ -9810,6 +9953,7 @@
|
|
|
9810
9953
|
|
|
9811
9954
|
// Remove the object store from WebSQL
|
|
9812
9955
|
transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
|
|
9956
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9813
9957
|
/**
|
|
9814
9958
|
* @param {WebSQLTransaction} tx
|
|
9815
9959
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9822,6 +9966,8 @@
|
|
|
9822
9966
|
failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
|
|
9823
9967
|
return false;
|
|
9824
9968
|
}
|
|
9969
|
+
/* c8 ignore stop -- see comment above */
|
|
9970
|
+
|
|
9825
9971
|
tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
|
|
9826
9972
|
if (data.rows.length > 0) {
|
|
9827
9973
|
tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
|
|
@@ -10001,13 +10147,15 @@
|
|
|
10001
10147
|
return;
|
|
10002
10148
|
}
|
|
10003
10149
|
var indexKeyValue = indexKey.value;
|
|
10150
|
+
/* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
|
|
10004
10151
|
if (indexKeyValue === undefined) {
|
|
10005
10152
|
resolve(undefined);
|
|
10006
10153
|
return;
|
|
10007
10154
|
}
|
|
10155
|
+
/* c8 ignore stop -- see comment above */
|
|
10008
10156
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
10009
10157
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
10010
|
-
executeFetchIndexData.apply(void 0,
|
|
10158
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
10011
10159
|
if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
|
|
10012
10160
|
resolve(undefined);
|
|
10013
10161
|
return;
|
|
@@ -10087,16 +10235,18 @@
|
|
|
10087
10235
|
* @returns {void}
|
|
10088
10236
|
*/
|
|
10089
10237
|
function setIndexInfo(index) {
|
|
10238
|
+
/* c8 ignore start -- Defensive: unreachable given the current `Key.js` implementation, where a keyPath evaluation that would resolve to `undefined` always instead reports `invalid`/`failure` (caught above, causing an earlier `return`) rather than succeeding with an `undefined` value. */
|
|
10090
10239
|
if (indexKeyValue === undefined) {
|
|
10091
10240
|
return;
|
|
10092
10241
|
}
|
|
10242
|
+
/* c8 ignore stop -- see comment above */
|
|
10093
10243
|
paramMap[index.__currentName] = /** @type {string} */
|
|
10094
10244
|
_encode(indexKeyValue, index.multiEntry);
|
|
10095
10245
|
}
|
|
10096
10246
|
if (index.unique) {
|
|
10097
10247
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
10098
10248
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
10099
|
-
executeFetchIndexData.apply(void 0,
|
|
10249
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
10100
10250
|
if (key === undefined) {
|
|
10101
10251
|
setIndexInfo(index);
|
|
10102
10252
|
resolve(undefined);
|
|
@@ -10187,6 +10337,7 @@
|
|
|
10187
10337
|
_me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
|
|
10188
10338
|
ky = _me$__validateKeyAndV2[0],
|
|
10189
10339
|
clonedValue = _me$__validateKeyAndV2[1];
|
|
10340
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10190
10341
|
// @ts-ignore -- Private API
|
|
10191
10342
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
|
|
10192
10343
|
return request;
|
|
@@ -10218,6 +10369,7 @@
|
|
|
10218
10369
|
_me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
|
|
10219
10370
|
ky = _me$__validateKeyAndV4[0],
|
|
10220
10371
|
clonedValue = _me$__validateKeyAndV4[1];
|
|
10372
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10221
10373
|
// @ts-ignore -- Private API
|
|
10222
10374
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
|
|
10223
10375
|
return request;
|
|
@@ -10244,8 +10396,10 @@
|
|
|
10244
10396
|
}
|
|
10245
10397
|
cb(tx);
|
|
10246
10398
|
}, function (tx, err) {
|
|
10399
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10247
10400
|
error(err);
|
|
10248
10401
|
return false;
|
|
10402
|
+
/* c8 ignore stop -- see comment above */
|
|
10249
10403
|
});
|
|
10250
10404
|
};
|
|
10251
10405
|
|
|
@@ -10354,16 +10508,20 @@
|
|
|
10354
10508
|
return;
|
|
10355
10509
|
}
|
|
10356
10510
|
ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
|
|
10511
|
+
/* c8 ignore start -- Defensive: catches unexpected decode failures (e.g. corrupted stored data); not reliably reproducible via the public API since encode/decode are always paired and never write undecodable data. */
|
|
10357
10512
|
} catch (e) {
|
|
10358
10513
|
// If no result is returned, or error occurs when parsing JSON
|
|
10359
10514
|
if (CFG.DEBUG) {
|
|
10360
10515
|
console.log(e);
|
|
10361
10516
|
}
|
|
10362
10517
|
}
|
|
10518
|
+
/* c8 ignore stop -- see comment above */
|
|
10363
10519
|
success(ret);
|
|
10364
10520
|
}, function (tx, err) {
|
|
10521
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10365
10522
|
error(err);
|
|
10366
10523
|
return false;
|
|
10524
|
+
/* c8 ignore stop -- see comment above */
|
|
10367
10525
|
});
|
|
10368
10526
|
}, undefined, me);
|
|
10369
10527
|
};
|
|
@@ -10475,8 +10633,10 @@
|
|
|
10475
10633
|
});
|
|
10476
10634
|
success();
|
|
10477
10635
|
}, function (tx, err) {
|
|
10636
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10478
10637
|
error(err);
|
|
10479
10638
|
return false;
|
|
10639
|
+
/* c8 ignore stop -- see comment above */
|
|
10480
10640
|
});
|
|
10481
10641
|
}, undefined, me);
|
|
10482
10642
|
};
|
|
@@ -10504,8 +10664,10 @@
|
|
|
10504
10664
|
});
|
|
10505
10665
|
success();
|
|
10506
10666
|
}, function (tx, err) {
|
|
10667
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10507
10668
|
error(err);
|
|
10508
10669
|
return false;
|
|
10670
|
+
/* c8 ignore stop -- see comment above */
|
|
10509
10671
|
});
|
|
10510
10672
|
}, undefined, me);
|
|
10511
10673
|
};
|
|
@@ -10840,7 +11002,7 @@
|
|
|
10840
11002
|
if (keyPath !== null && !isValidKeyPath(keyPath)) {
|
|
10841
11003
|
throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
|
|
10842
11004
|
}
|
|
10843
|
-
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
|
|
11005
|
+
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
|
|
10844
11006
|
throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
|
|
10845
11007
|
}
|
|
10846
11008
|
var autoInc = createOptions.autoIncrement;
|
|
@@ -10989,7 +11151,6 @@
|
|
|
10989
11151
|
}
|
|
10990
11152
|
};
|
|
10991
11153
|
|
|
10992
|
-
// Todo __forceClose: Add tests for `__forceClose`
|
|
10993
11154
|
/**
|
|
10994
11155
|
*
|
|
10995
11156
|
* @param {string} msg
|
|
@@ -10998,23 +11159,39 @@
|
|
|
10998
11159
|
*/
|
|
10999
11160
|
IDBDatabase.prototype.__forceClose = function (msg) {
|
|
11000
11161
|
var me = this;
|
|
11162
|
+
// `close()` (below) resets `me.__transactions` to `[]`, so the
|
|
11163
|
+
// transactions to abort -- and the total count the completion check
|
|
11164
|
+
// below needs -- must be captured before calling it, not read back off
|
|
11165
|
+
// `me.__transactions` afterward.
|
|
11166
|
+
var transactions = me.__transactions;
|
|
11001
11167
|
me.close();
|
|
11168
|
+
|
|
11169
|
+
/**
|
|
11170
|
+
* @returns {void}
|
|
11171
|
+
*/
|
|
11172
|
+
function dispatchClose() {
|
|
11173
|
+
// Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
|
|
11174
|
+
var evt = createEvent('close');
|
|
11175
|
+
setTimeout(function () {
|
|
11176
|
+
me.dispatchEvent(evt);
|
|
11177
|
+
}, 0);
|
|
11178
|
+
}
|
|
11179
|
+
if (!transactions.length) {
|
|
11180
|
+
dispatchClose();
|
|
11181
|
+
return;
|
|
11182
|
+
}
|
|
11002
11183
|
var ct = 0;
|
|
11003
|
-
|
|
11184
|
+
transactions.forEach(function (trans) {
|
|
11004
11185
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11005
11186
|
trans.on__abort = function () {
|
|
11006
11187
|
ct++;
|
|
11007
|
-
if (ct
|
|
11008
|
-
|
|
11009
|
-
var evt = createEvent('close');
|
|
11010
|
-
setTimeout(function () {
|
|
11011
|
-
me.dispatchEvent(evt);
|
|
11012
|
-
}, 0);
|
|
11188
|
+
if (ct !== transactions.length) {
|
|
11189
|
+
return;
|
|
11013
11190
|
}
|
|
11191
|
+
dispatchClose();
|
|
11014
11192
|
};
|
|
11015
11193
|
trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
|
|
11016
11194
|
});
|
|
11017
|
-
me.__transactions = [];
|
|
11018
11195
|
};
|
|
11019
11196
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
11020
11197
|
defineOuterInterface(IDBDatabase.prototype, listeners);
|
|
@@ -11181,6 +11358,7 @@
|
|
|
11181
11358
|
return undefined;
|
|
11182
11359
|
}
|
|
11183
11360
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11361
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11184
11362
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11185
11363
|
new IDBVersionChangeEvent('versionchange', {
|
|
11186
11364
|
oldVersion: oldVersion,
|
|
@@ -11228,6 +11406,7 @@
|
|
|
11228
11406
|
}
|
|
11229
11407
|
};
|
|
11230
11408
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11409
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11231
11410
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11232
11411
|
new IDBVersionChangeEvent('blocked', {
|
|
11233
11412
|
oldVersion: oldVersion,
|
|
@@ -11288,6 +11467,13 @@
|
|
|
11288
11467
|
|
|
11289
11468
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
11290
11469
|
var sysdb;
|
|
11470
|
+
// Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
|
|
11471
|
+
// later change to that config (e.g. toggling in-memory mode on and back
|
|
11472
|
+
// off) causes `sysdb` to be recreated for the new setting rather than
|
|
11473
|
+
// staying pinned, forever, to whatever it was the first time any database
|
|
11474
|
+
// was created in the process.
|
|
11475
|
+
/** @type {string|null|undefined} */
|
|
11476
|
+
var sysdbMemoryDatabaseSetting;
|
|
11291
11477
|
var nameCounter = 0;
|
|
11292
11478
|
|
|
11293
11479
|
/**
|
|
@@ -11369,12 +11555,20 @@
|
|
|
11369
11555
|
function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
|
|
11370
11556
|
var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
|
|
11371
11557
|
if (useMemoryDatabase) {
|
|
11558
|
+
/* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
|
|
11559
|
+
was initialized as an empty placeholder by `open()`'s connection-queue
|
|
11560
|
+
setup (`addRequestToConnectionQueue`, above `openDB`) but never
|
|
11561
|
+
populated with an actual instance -- e.g. `__openDatabase` throwing
|
|
11562
|
+
after a `dbVersions` row already existed for `name` from an earlier,
|
|
11563
|
+
successful `open()` -- or if `name` was never added to the cache at
|
|
11564
|
+
all. Not reachable via normal, non-tampered API usage. */
|
|
11372
11565
|
var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
|
|
11373
11566
|
if (!latestSQLiteDBCached) {
|
|
11374
11567
|
console.warn('Could not find a memory database instance to delete.');
|
|
11375
11568
|
databaseDeleted();
|
|
11376
11569
|
return;
|
|
11377
11570
|
}
|
|
11571
|
+
/* c8 ignore stop -- see comment above */
|
|
11378
11572
|
var _sqliteDB = latestSQLiteDBCached._db;
|
|
11379
11573
|
if (!_sqliteDB || !_sqliteDB.close) {
|
|
11380
11574
|
console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
|
|
@@ -11428,15 +11622,24 @@
|
|
|
11428
11622
|
tables.item(i).name)), [], function () {
|
|
11429
11623
|
deleteTables(i + 1);
|
|
11430
11624
|
}, function () {
|
|
11625
|
+
/* c8 ignore start -- Defensive: continues deleting the rest
|
|
11626
|
+
even if this specific store's table is already gone (e.g.
|
|
11627
|
+
duplicate `__sys__` rows for the same escaped table name, or
|
|
11628
|
+
external tampering); not reachable via normal API usage. */
|
|
11431
11629
|
deleteTables(i + 1);
|
|
11432
11630
|
return false;
|
|
11631
|
+
/* c8 ignore stop -- see comment above */
|
|
11433
11632
|
});
|
|
11434
11633
|
}
|
|
11435
11634
|
})(0);
|
|
11436
11635
|
}, function () {
|
|
11437
|
-
|
|
11636
|
+
/* c8 ignore start -- `__sys__` is always created by `openDB` before this
|
|
11637
|
+
database's `dbVersions` row (a prerequisite for reaching this code at
|
|
11638
|
+
all) is ever inserted; only reachable if the file was tampered with/
|
|
11639
|
+
removed externally afterward. */
|
|
11438
11640
|
databaseDeleted();
|
|
11439
11641
|
return false;
|
|
11642
|
+
/* c8 ignore stop -- see comment above */
|
|
11440
11643
|
});
|
|
11441
11644
|
});
|
|
11442
11645
|
}
|
|
@@ -11467,9 +11670,11 @@
|
|
|
11467
11670
|
}
|
|
11468
11671
|
failure(er);
|
|
11469
11672
|
}
|
|
11470
|
-
if (sysdb) {
|
|
11673
|
+
if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
|
|
11471
11674
|
success();
|
|
11472
11675
|
} else {
|
|
11676
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
|
|
11677
|
+
sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
|
|
11473
11678
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
|
|
11474
11679
|
sysdb = __openDatabase(typeof CFG.memoryDatabase === 'string' ? CFG.memoryDatabase : joinPath(typeof CFG.sysDatabaseBasePath === 'string' ? CFG.sysDatabaseBasePath : CFG.databaseBasePath || '', '__sysdb__' + (CFG.addSQLiteExtension !== false ? '.sqlite' : '')), '1', 'System Database', CFG.DEFAULT_DB_SIZE);
|
|
11475
11680
|
sysdb.transaction(function (systx) {
|
|
@@ -11649,6 +11854,17 @@
|
|
|
11649
11854
|
* @returns {void}
|
|
11650
11855
|
*/
|
|
11651
11856
|
var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11857
|
+
/* c8 ignore start -- This initial definition is always
|
|
11858
|
+
superseded before ever being invoked: the `sysdb.transaction(...)`
|
|
11859
|
+
call below always reaches its `nonstandardTransCb` (4th arg)
|
|
11860
|
+
after this same SQL batch finishes running (since `dbCreateError`
|
|
11861
|
+
always reports errors as "handled" and this call site is never
|
|
11862
|
+
a `readTransaction`), which unconditionally reassigns
|
|
11863
|
+
`sysdbFinishedCb` to a version using the library's own
|
|
11864
|
+
`rollback`/`commit` -- well before any real invocation from
|
|
11865
|
+
`on__beforecomplete`/`on__preabort`/`on__abort` below (those only
|
|
11866
|
+
fire once the upgrade transaction itself later completes/aborts).
|
|
11867
|
+
Kept as a defensive fallback in case that invariant ever changes. */
|
|
11652
11868
|
if (err) {
|
|
11653
11869
|
/**
|
|
11654
11870
|
* @param {unknown} [errorToShow]
|
|
@@ -11697,6 +11913,7 @@
|
|
|
11697
11913
|
}
|
|
11698
11914
|
// In browser, should auto-commit
|
|
11699
11915
|
cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11916
|
+
/* c8 ignore stop -- see comment above */
|
|
11700
11917
|
};
|
|
11701
11918
|
sysdb.transaction(function (systx) {
|
|
11702
11919
|
/**
|
|
@@ -11704,6 +11921,7 @@
|
|
|
11704
11921
|
*/
|
|
11705
11922
|
function versionSet() {
|
|
11706
11923
|
var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
|
|
11924
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11707
11925
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11708
11926
|
new IDBVersionChangeEvent('upgradeneeded', {
|
|
11709
11927
|
oldVersion: oldVersion,
|
|
@@ -11829,9 +12047,17 @@
|
|
|
11829
12047
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11830
12048
|
req.transaction.on__complete = function () {
|
|
11831
12049
|
var pos = connection.__transactions.indexOf(req.transaction);
|
|
12050
|
+
// `req.transaction` (the versionchange transaction) is created
|
|
12051
|
+
// directly via `IDBTransaction.__createInstance` above, never
|
|
12052
|
+
// via `IDBDatabase.prototype.transaction()` (the only place
|
|
12053
|
+
// that pushes onto `connection.__transactions`), so `pos` is
|
|
12054
|
+
// always -1 here.
|
|
12055
|
+
/* c8 ignore start -- see comment above */
|
|
11832
12056
|
if (pos !== -1) {
|
|
11833
12057
|
connection.__transactions.splice(pos, 1);
|
|
11834
12058
|
}
|
|
12059
|
+
/* c8 ignore stop -- see comment above */
|
|
12060
|
+
|
|
11835
12061
|
if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
|
|
11836
12062
|
req.__transaction = null;
|
|
11837
12063
|
var err = createDOMException('AbortError', 'The connection has been closed.');
|
|
@@ -11867,9 +12093,16 @@
|
|
|
11867
12093
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
|
|
11868
12094
|
}
|
|
11869
12095
|
}, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12096
|
+
// Defensive fallback, not reachable in practice: same reasoning
|
|
12097
|
+
// as `deleteDatabase`'s own `nonstandardTransCb` below
|
|
12098
|
+
// (`currentTask.readOnly` is always false here, and
|
|
12099
|
+
// `dbCreateError` always returns `false`, so `err` is never
|
|
12100
|
+
// truthy either).
|
|
12101
|
+
/* c8 ignore start -- see comment above */
|
|
11870
12102
|
if (currentTask.readOnly || err) {
|
|
11871
12103
|
return true;
|
|
11872
12104
|
}
|
|
12105
|
+
/* c8 ignore stop -- see comment above */
|
|
11873
12106
|
sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11874
12107
|
if (err) {
|
|
11875
12108
|
rollback(err,
|
|
@@ -11884,7 +12117,17 @@
|
|
|
11884
12117
|
} else {
|
|
11885
12118
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
|
|
11886
12119
|
}
|
|
11887
|
-
},
|
|
12120
|
+
},
|
|
12121
|
+
// Deeply-nested defensive path: only reached if
|
|
12122
|
+
// the *revert* SQL (undoing the `dbVersions`
|
|
12123
|
+
// INSERT/UPDATE after the original version-
|
|
12124
|
+
// upgrade itself already failed) fails a
|
|
12125
|
+
// *second* time. Not feasibly triggerable
|
|
12126
|
+
// without fault-injecting the underlying SQL
|
|
12127
|
+
// driver on this specific, already-failing
|
|
12128
|
+
// revert statement.
|
|
12129
|
+
function (sqlErr) {
|
|
12130
|
+
/* c8 ignore next 2 -- see comment above */
|
|
11888
12131
|
isRevertingSysdb = false;
|
|
11889
12132
|
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11890
12133
|
}, function () {
|
|
@@ -11900,8 +12143,20 @@
|
|
|
11900
12143
|
});
|
|
11901
12144
|
return undefined;
|
|
11902
12145
|
}).catch(function (err) {
|
|
12146
|
+
/* c8 ignore start -- Purely defensive: nothing in
|
|
12147
|
+
`triggerAnyVersionChangeAndBlockedEvents`'s promise chain
|
|
12148
|
+
(or this `.then()` continuation above) ever rejects/throws
|
|
12149
|
+
under any reachable application-level condition -- all of
|
|
12150
|
+
its continuations resolve cleanly, and its `dispatchEvent`
|
|
12151
|
+
calls are deliberately fire-and-forget ("No need to catch
|
|
12152
|
+
errors"), running inside a `setTimeout` where a listener
|
|
12153
|
+
throwing becomes an uncaught exception in that macrotask
|
|
12154
|
+
rather than a promise rejection here. This exists solely
|
|
12155
|
+
to surface a truly-unexpected internal bug via the console
|
|
12156
|
+
before rethrowing, not to handle a real, testable error path. */
|
|
11903
12157
|
console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
|
|
11904
12158
|
throw err;
|
|
12159
|
+
/* c8 ignore stop -- see comment above */
|
|
11905
12160
|
});
|
|
11906
12161
|
} else {
|
|
11907
12162
|
finishRequest();
|
|
@@ -11929,11 +12184,19 @@
|
|
|
11929
12184
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
11930
12185
|
db = websqlDBCache[name][version];
|
|
11931
12186
|
} else {
|
|
11932
|
-
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
12187
|
+
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
11933
12188
|
if (useDatabaseCache) {
|
|
12189
|
+
/* c8 ignore start -- Defensive: by the time `openDB` runs,
|
|
12190
|
+
`websqlDBCache[name]` has always already been created by
|
|
12191
|
+
`addRequestToConnectionQueue`'s own callback above (guarded
|
|
12192
|
+
by this same `useDatabaseCache` condition), which always
|
|
12193
|
+
runs first and unconditionally ensures the entry exists
|
|
12194
|
+
before ever calling `openDB`. Kept as a safety net in case
|
|
12195
|
+
that invariant ever changes. */
|
|
11934
12196
|
if (!Object.hasOwn(websqlDBCache, name)) {
|
|
11935
12197
|
websqlDBCache[name] = {};
|
|
11936
12198
|
}
|
|
12199
|
+
/* c8 ignore stop -- see comment above */
|
|
11937
12200
|
websqlDBCache[name][version] = db;
|
|
11938
12201
|
}
|
|
11939
12202
|
}
|
|
@@ -12084,6 +12347,7 @@
|
|
|
12084
12347
|
req.__result = undefined;
|
|
12085
12348
|
req.__done = true;
|
|
12086
12349
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
12350
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12087
12351
|
// @ts-ignore It's ok; needed under some TS versions
|
|
12088
12352
|
new IDBVersionChangeEvent('success', {
|
|
12089
12353
|
oldVersion: version,
|
|
@@ -12126,9 +12390,23 @@
|
|
|
12126
12390
|
cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
|
|
12127
12391
|
}, dbError);
|
|
12128
12392
|
}, dbError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12393
|
+
/* c8 ignore start -- Defensive fallback, not reachable in
|
|
12394
|
+
practice: `currentTask.readOnly` is always `false` here
|
|
12395
|
+
(this callback is only ever attached to the writable
|
|
12396
|
+
`sysdb.transaction(...)` call above, never to a
|
|
12397
|
+
`sysdb.readTransaction(...)`), and `err` can only be
|
|
12398
|
+
truthy if the `DELETE FROM dbVersions` statement's own
|
|
12399
|
+
error callback (`dbError`) reports the failure back to
|
|
12400
|
+
`websql-configurable` as unhandled -- but `dbError`
|
|
12401
|
+
deliberately always `return`s `false`, which tells the
|
|
12402
|
+
library the error was already handled (and to keep
|
|
12403
|
+
`err` falsy here), precisely so this custom
|
|
12404
|
+
`sysdbFinishedCbDelete` rollback/commit path below is
|
|
12405
|
+
used instead of the library's own default rollback. */
|
|
12129
12406
|
if (currentTask.readOnly || err) {
|
|
12130
12407
|
return true;
|
|
12131
12408
|
}
|
|
12409
|
+
/* c8 ignore stop -- see comment above */
|
|
12132
12410
|
sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
|
|
12133
12411
|
if (err) {
|
|
12134
12412
|
rollback(err, cb);
|
|
@@ -12254,10 +12532,9 @@
|
|
|
12254
12532
|
};
|
|
12255
12533
|
|
|
12256
12534
|
/**
|
|
12257
|
-
* @todo forceClose: Test
|
|
12258
12535
|
* This is provided to facilitate unit-testing of the
|
|
12259
12536
|
* closing of a database connection with a forced flag:
|
|
12260
|
-
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection
|
|
12537
|
+
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
|
|
12261
12538
|
* @param {string} dbName
|
|
12262
12539
|
* @param {Integer} connIdx
|
|
12263
12540
|
* @param {string} msg
|
|
@@ -12358,6 +12635,7 @@
|
|
|
12358
12635
|
* @this {IDBRecordFull}
|
|
12359
12636
|
*/
|
|
12360
12637
|
function IDBRecord() {
|
|
12638
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12361
12639
|
// @ts-ignore Should be ok
|
|
12362
12640
|
this[Symbol.toStringTag] = 'IDBRecord';
|
|
12363
12641
|
this.__key = key;
|
|
@@ -12394,6 +12672,7 @@
|
|
|
12394
12672
|
if (!(this instanceof IDBRecordAlias)) {
|
|
12395
12673
|
throw new TypeError('Illegal invocation');
|
|
12396
12674
|
}
|
|
12675
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12397
12676
|
// @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
|
|
12398
12677
|
return this['__' + prop];
|
|
12399
12678
|
});
|
|
@@ -12736,6 +13015,7 @@
|
|
|
12736
13015
|
success(undefined, undefined, undefined);
|
|
12737
13016
|
}
|
|
12738
13017
|
}, function (tx, err) {
|
|
13018
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
12739
13019
|
if (CFG.DEBUG) {
|
|
12740
13020
|
console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12741
13021
|
}
|
|
@@ -12919,7 +13199,16 @@
|
|
|
12919
13199
|
if (a.key > b.key) {
|
|
12920
13200
|
return me.direction === 'prev' ? -1 : 1;
|
|
12921
13201
|
}
|
|
13202
|
+
/* c8 ignore start -- Defensive: only reachable if two matches
|
|
13203
|
+
in the same batch shared both the same `matchingKey` and
|
|
13204
|
+
the same primary `key`, which would require the same
|
|
13205
|
+
record's multi-entry array to contain a duplicate value.
|
|
13206
|
+
`Key.js`'s array-to-key conversion already drops duplicate
|
|
13207
|
+
values when a multi-entry index entry is built, so this
|
|
13208
|
+
can never happen in practice; kept only to satisfy the
|
|
13209
|
+
`Array.prototype.sort` comparator contract. */
|
|
12922
13210
|
return 0;
|
|
13211
|
+
/* c8 ignore stop -- see comment above */
|
|
12923
13212
|
});
|
|
12924
13213
|
me.__prefetchedIndex = 0;
|
|
12925
13214
|
me.__prefetchedData = {
|
|
@@ -12938,13 +13227,19 @@
|
|
|
12938
13227
|
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
12939
13228
|
}
|
|
12940
13229
|
me.__decode(rows[0], success);
|
|
12941
|
-
},
|
|
13230
|
+
},
|
|
13231
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13232
|
+
execution error (e.g. I/O error, corruption) while querying for
|
|
13233
|
+
multi-entry cursor matches; not reliably reproducible without
|
|
13234
|
+
mocking the SQL layer. */
|
|
13235
|
+
function (tx, err) {
|
|
12942
13236
|
if (CFG.DEBUG) {
|
|
12943
13237
|
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12944
13238
|
}
|
|
12945
13239
|
error(err);
|
|
12946
13240
|
return false;
|
|
12947
13241
|
});
|
|
13242
|
+
/* c8 ignore stop -- see comment above */
|
|
12948
13243
|
}
|
|
12949
13244
|
runQuery();
|
|
12950
13245
|
};
|
|
@@ -13053,6 +13348,7 @@
|
|
|
13053
13348
|
* @returns {void}
|
|
13054
13349
|
*/
|
|
13055
13350
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
13351
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13056
13352
|
// @ts-ignore Why is this not being found?; needed under some TS versions
|
|
13057
13353
|
this.__prefetchedData = null;
|
|
13058
13354
|
this.__multiEntryExhausted = false;
|
|
@@ -13077,7 +13373,7 @@
|
|
|
13077
13373
|
convertValueToKeyRethrowingAndIfInvalid(key);
|
|
13078
13374
|
var cmpResult = cmp(key, me.key);
|
|
13079
13375
|
if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
|
|
13080
|
-
throw createDOMException('DataError', 'Cannot
|
|
13376
|
+
throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
|
|
13081
13377
|
}
|
|
13082
13378
|
}
|
|
13083
13379
|
this.__continueFinish(key, undefined, advanceState);
|
|
@@ -13334,6 +13630,7 @@
|
|
|
13334
13630
|
// continuation logic in `__findBasic` to see this update's
|
|
13335
13631
|
// effect on ordering (see "Modify records during cursor
|
|
13336
13632
|
// iteration" in idbcursor_update_index.any.js).
|
|
13633
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13337
13634
|
// @ts-ignore -- API (not erring in TS 6)
|
|
13338
13635
|
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
13339
13636
|
}
|
|
@@ -13383,14 +13680,33 @@
|
|
|
13383
13680
|
// We don't invalidate the cache (as we don't access it anymore
|
|
13384
13681
|
// and it will set the index off)
|
|
13385
13682
|
success(undefined);
|
|
13683
|
+
/* c8 ignore start -- Defensive: `__find` (invoked just above) has
|
|
13684
|
+
already confirmed a row exists for this primary key within the
|
|
13685
|
+
same transaction queue, so `rowsAffected` should always be 1 in
|
|
13686
|
+
normal usage. This branch would only be reached if the underlying
|
|
13687
|
+
row were removed by another request queued in the same
|
|
13688
|
+
transaction between `__find`'s check and this DELETE actually
|
|
13689
|
+
running (e.g. deleting the same record directly via the object
|
|
13690
|
+
store while a cursor over it is mid-iteration); attempts to
|
|
13691
|
+
construct such a scenario instead trigger a transaction abort
|
|
13692
|
+
(`AbortError`) before this callback ever runs, since the default
|
|
13693
|
+
action of an unhandled request error is to abort the
|
|
13694
|
+
transaction. */
|
|
13386
13695
|
} else {
|
|
13387
13696
|
// @ts-expect-error Apparently ok
|
|
13388
13697
|
error('No rows with key found' + key);
|
|
13389
13698
|
}
|
|
13390
|
-
|
|
13699
|
+
/* c8 ignore stop -- see comment above */
|
|
13700
|
+
},
|
|
13701
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13702
|
+
execution error (e.g. I/O error, corruption) while deleting the
|
|
13703
|
+
current row; not reliably reproducible without mocking the SQL
|
|
13704
|
+
layer. */
|
|
13705
|
+
function (tx, data) {
|
|
13391
13706
|
error(data);
|
|
13392
13707
|
return false;
|
|
13393
13708
|
});
|
|
13709
|
+
/* c8 ignore stop -- see comment above */
|
|
13394
13710
|
}, error);
|
|
13395
13711
|
}, undefined, me);
|
|
13396
13712
|
};
|
|
@@ -13798,7 +14114,7 @@
|
|
|
13798
14114
|
*/
|
|
13799
14115
|
function setGlobalVars(idb, initialConfig) {
|
|
13800
14116
|
var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
|
|
13801
|
-
/** @type {unknown} */globalThis
|
|
14117
|
+
/** @type {unknown} */globalThis;
|
|
13802
14118
|
/**
|
|
13803
14119
|
* @param {string} name
|
|
13804
14120
|
* @param {unknown} value
|
|
@@ -13889,80 +14205,87 @@
|
|
|
13889
14205
|
});
|
|
13890
14206
|
}
|
|
13891
14207
|
var shimIDBFactory = IDBFactory;
|
|
13892
|
-
if (CFG.win.openDatabase
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
14208
|
+
if (CFG.win.openDatabase === undefined) {
|
|
14209
|
+
return;
|
|
14210
|
+
}
|
|
14211
|
+
shimIndexedDB$1.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
|
|
14212
|
+
// Polyfill ALL of IndexedDB, using WebSQL
|
|
14213
|
+
shim('indexedDB', shimIndexedDB$1, {
|
|
14214
|
+
enumerable: true,
|
|
14215
|
+
configurable: true,
|
|
14216
|
+
get: function get() {
|
|
14217
|
+
if (this !== IDB && !isNullish(this) && !this.shimNS) {
|
|
14218
|
+
// Latter is hack for test environment
|
|
14219
|
+
throw new TypeError('Illegal invocation');
|
|
13904
14220
|
}
|
|
13905
|
-
|
|
13906
|
-
/** @type {[string, unknown][]} */
|
|
13907
|
-
[['IDBFactory', shimIDBFactory], ['IDBDatabase', IDBDatabase], ['IDBObjectStore', IDBObjectStore], ['IDBIndex', IDBIndex], ['IDBTransaction', IDBTransaction], ['IDBCursor', IDBCursor], ['IDBCursorWithValue', IDBCursorWithValue], ['IDBRecord', IDBRecord], ['IDBKeyRange', IDBKeyRange], ['IDBRequest', IDBRequest], ['IDBOpenDBRequest', IDBOpenDBRequest], ['IDBVersionChangeEvent', IDBVersionChangeEvent]].forEach(function (_ref3) {
|
|
13908
|
-
var _ref4 = _slicedToArray(_ref3, 2),
|
|
13909
|
-
prop = _ref4[0],
|
|
13910
|
-
obj = _ref4[1];
|
|
13911
|
-
shim(prop, obj, {
|
|
13912
|
-
enumerable: false,
|
|
13913
|
-
configurable: true
|
|
13914
|
-
});
|
|
13915
|
-
});
|
|
13916
|
-
// For Node environments
|
|
13917
|
-
if (CFG.fs) {
|
|
13918
|
-
setFS(CFG.fs);
|
|
14221
|
+
return shimIndexedDB$1;
|
|
13919
14222
|
}
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
14223
|
+
});
|
|
14224
|
+
/** @type {[string, unknown][]} */
|
|
14225
|
+
[['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) {
|
|
14226
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
14227
|
+
prop = _ref4[0],
|
|
14228
|
+
obj = _ref4[1];
|
|
14229
|
+
shim(prop, obj, {
|
|
14230
|
+
enumerable: false,
|
|
14231
|
+
configurable: true
|
|
14232
|
+
});
|
|
14233
|
+
});
|
|
14234
|
+
// For Node environments
|
|
14235
|
+
if (CFG.fs) {
|
|
14236
|
+
setFS(CFG.fs);
|
|
14237
|
+
}
|
|
14238
|
+
if (CFG.fullIDLSupport) {
|
|
14239
|
+
// Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
|
|
14240
|
+
|
|
14241
|
+
Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
|
|
14242
|
+
Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
|
|
14243
|
+
Object.setPrototypeOf(IDBDatabase, EventTarget);
|
|
14244
|
+
Object.setPrototypeOf(IDBRequest, EventTarget);
|
|
14245
|
+
Object.setPrototypeOf(IDBTransaction, EventTarget);
|
|
14246
|
+
Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
|
|
14247
|
+
// `ShimDOMException` is the real native `DOMException` when one
|
|
14248
|
+
// is available (see `DOMException.js`'s `useNativeDOMException`)
|
|
14249
|
+
// -- which, unlike the shim classes above, is a single,
|
|
14250
|
+
// process-wide singleton shared by reference across every
|
|
14251
|
+
// sandbox this library gets installed into (see
|
|
14252
|
+
// `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
|
|
14253
|
+
// already has the correct prototype chain out of the box
|
|
14254
|
+
// (`Object.getPrototypeOf(DOMException) === Function.prototype`,
|
|
14255
|
+
// not `Error`), so forcing it here isn't just unneeded but
|
|
14256
|
+
// actively wrong -- and, because it's shared, permanently
|
|
14257
|
+
// wrong for every later use of `DOMException` in the same
|
|
14258
|
+
// process (e.g. a later WPT test file's own idlharness-style
|
|
14259
|
+
// check that `DOMException` does *not* inherit from `Error`
|
|
14260
|
+
// on the class side), not just this one shim install.
|
|
14261
|
+
if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
|
|
14262
|
+
Object.setPrototypeOf(ShimDOMException, Error);
|
|
14263
|
+
Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
|
|
13947
14264
|
}
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
if (CFG.replaceNonIDBGlobals) {
|
|
13956
|
-
setNonIDBGlobals();
|
|
13957
|
-
}
|
|
14265
|
+
}
|
|
14266
|
+
if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
|
|
14267
|
+
if (CFG.addNonIDBGlobals) {
|
|
14268
|
+
// As `DOMStringList` exists per IDL (and Chrome) in the global
|
|
14269
|
+
// thread (but not in workers), we prefix the name to avoid
|
|
14270
|
+
// shadowing or conflicts
|
|
14271
|
+
setNonIDBGlobals('Shim');
|
|
13958
14272
|
}
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
return;
|
|
14273
|
+
if (CFG.replaceNonIDBGlobals) {
|
|
14274
|
+
setNonIDBGlobals();
|
|
13962
14275
|
}
|
|
13963
|
-
/* c8 ignore stop -- TS guard */
|
|
13964
|
-
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13965
14276
|
}
|
|
14277
|
+
/* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
|
|
14278
|
+
confirmed truthy just before this function (`__useShim`) was
|
|
14279
|
+
defined and immediately invoked (see the `if ('shimIndexedDB'
|
|
14280
|
+
in IDB && IDB.shimIndexedDB)` guard above), and nothing in
|
|
14281
|
+
this function's body reassigns or deletes it. Only reachable
|
|
14282
|
+
if `IDB` is some unusual object (e.g. a Proxy) whose
|
|
14283
|
+
`shimIndexedDB` property value changes between reads. */
|
|
14284
|
+
if (!IDB.shimIndexedDB) {
|
|
14285
|
+
return;
|
|
14286
|
+
}
|
|
14287
|
+
/* c8 ignore stop -- see comment above */
|
|
14288
|
+
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13966
14289
|
};
|
|
13967
14290
|
IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
|
|
13968
14291
|
CFG.DEBUG = val;
|