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 (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -481,6 +481,7 @@
|
|
|
481
481
|
var ShimDOMException$1 = typeof DOMException === 'undefined'
|
|
482
482
|
// Todo: Better polyfill (if even needed here)
|
|
483
483
|
/* eslint-disable no-shadow -- Polyfill */
|
|
484
|
+
/* 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) */
|
|
484
485
|
// eslint-disable-next-line @stylistic/operator-linebreak -- TS/JSDoc needs
|
|
485
486
|
?
|
|
486
487
|
/**
|
|
@@ -498,9 +499,10 @@
|
|
|
498
499
|
configurable: true
|
|
499
500
|
});
|
|
500
501
|
return err;
|
|
501
|
-
}
|
|
502
|
+
}
|
|
503
|
+
/* c8 ignore stop */ : DOMException;
|
|
502
504
|
|
|
503
|
-
/** @type {WeakMap<object,
|
|
505
|
+
/** @type {WeakMap<object, EventWithProps>} */
|
|
504
506
|
var ev = new WeakMap();
|
|
505
507
|
/** @type {WeakMap<object, EventWithProps>} */
|
|
506
508
|
var evCfg = new WeakMap();
|
|
@@ -546,11 +548,12 @@
|
|
|
546
548
|
obj[prop] = {
|
|
547
549
|
configurable: true,
|
|
548
550
|
get: function get() {
|
|
549
|
-
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
551
|
+
return Object.hasOwn(_evCfg, prop) ? _evCfg[prop] : Reflect.has(_ev, prop) ? _ev[prop] : ['bubbles', 'cancelable', 'composed'].includes(prop) ? false
|
|
552
|
+
/* 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;
|
|
550
553
|
}
|
|
551
554
|
};
|
|
552
555
|
return obj;
|
|
553
|
-
}, /** @type {
|
|
556
|
+
}, /** @type {PropertyDescriptorMap} */{}));
|
|
554
557
|
}
|
|
555
558
|
|
|
556
559
|
/**
|
|
@@ -573,8 +576,9 @@
|
|
|
573
576
|
throw new TypeError('Illegal invocation');
|
|
574
577
|
}
|
|
575
578
|
var _evCfg = getEvCfg(this);
|
|
576
|
-
var _ev = ev.get(this);
|
|
577
|
-
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
579
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
580
|
+
return Boolean(Object.hasOwn(_evCfg, 'isTrusted')
|
|
581
|
+
/* 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);
|
|
578
582
|
}
|
|
579
583
|
|
|
580
584
|
/**
|
|
@@ -725,15 +729,15 @@
|
|
|
725
729
|
// this untyped alias, rather than `ShimEvent.prototype` directly, keeps
|
|
726
730
|
// that dynamic-augmentation pattern working without a `@ts-expect-error`
|
|
727
731
|
// on every single line below.
|
|
728
|
-
|
|
729
|
-
var ShimEventProto = ShimEvent.prototype;
|
|
732
|
+
|
|
733
|
+
var ShimEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimEvent.prototype;
|
|
730
734
|
|
|
731
735
|
/** @this {EventWithProps} */
|
|
732
736
|
ShimEventProto.preventDefault = function preventDefault() {
|
|
733
737
|
if (!(this instanceof ShimEvent)) {
|
|
734
738
|
throw new TypeError('Illegal invocation');
|
|
735
739
|
}
|
|
736
|
-
var _ev = ev.get(this);
|
|
740
|
+
var _ev = /** @type {EventWithProps} */ /** @type {EventWithProps} */ev.get(this);
|
|
737
741
|
var _evCfg = getEvCfg(this);
|
|
738
742
|
if (this.cancelable && !_evCfg._passive) {
|
|
739
743
|
_evCfg.defaultPrevented = true;
|
|
@@ -931,13 +935,12 @@
|
|
|
931
935
|
return _createClass(CustomEvent);
|
|
932
936
|
}(Event);
|
|
933
937
|
var ShimCustomEvent = CustomEvent;
|
|
934
|
-
/** @type {
|
|
935
|
-
var ShimCustomEventProto = ShimCustomEvent.prototype;
|
|
938
|
+
var ShimCustomEventProto = /** @type {Record<PropertyKey, unknown>} */ /** @type {unknown} */ShimCustomEvent.prototype;
|
|
936
939
|
/**
|
|
937
940
|
* @param {string} type
|
|
938
941
|
* @param {boolean} [bubbles]
|
|
939
942
|
* @param {boolean} [cancelable]
|
|
940
|
-
* @param {
|
|
943
|
+
* @param {unknown} [detail]
|
|
941
944
|
* @this {EventWithProps}
|
|
942
945
|
*/
|
|
943
946
|
ShimCustomEventProto.initCustomEvent = function initCustomEvent(type) {
|
|
@@ -949,6 +952,10 @@
|
|
|
949
952
|
throw new TypeError('Illegal invocation');
|
|
950
953
|
}
|
|
951
954
|
var _evCfg = getEvCfg(this);
|
|
955
|
+
if (_evCfg._dispatched) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
|
|
952
959
|
// @ts-expect-error `detail` isn't part of `EventInit`, only used internally here
|
|
953
960
|
// eslint-disable-next-line prefer-rest-params -- Keep signature
|
|
954
961
|
initEventInternal(this, type, {
|
|
@@ -956,16 +963,13 @@
|
|
|
956
963
|
cancelable: cancelable,
|
|
957
964
|
detail: detail
|
|
958
965
|
}, arguments[4]);
|
|
959
|
-
if (_evCfg._dispatched) {
|
|
960
|
-
return;
|
|
961
|
-
}
|
|
962
966
|
if (detail !== undefined) {
|
|
963
967
|
_evCfg.detail = detail;
|
|
964
968
|
}
|
|
965
969
|
// `initCustomEvent` deliberately excluded -- see the matching comment
|
|
966
970
|
// in `initEventInternal` for `initEvent`, above; the same reasoning
|
|
967
971
|
// applies here.
|
|
968
|
-
definePassthroughProps(this, ['detail'], _evCfg, ev.get(this));
|
|
972
|
+
definePassthroughProps(this, ['detail'], _evCfg, /** @type {EventWithProps} */ev.get(this));
|
|
969
973
|
};
|
|
970
974
|
// @ts-expect-error Not part of the class body itself
|
|
971
975
|
ShimCustomEvent[Symbol.toStringTag] = 'Function';
|
|
@@ -1372,7 +1376,7 @@
|
|
|
1372
1376
|
/** @type {string[]} */
|
|
1373
1377
|
this._extraProperties.forEach(function (prop) {
|
|
1374
1378
|
if (Reflect.has(e, prop)) {
|
|
1375
|
-
/** @type {
|
|
1379
|
+
/** @type {PropertyDescriptorMap} */eventCopy[prop] = /** @type {PropertyDescriptorMap} */e[prop]; // Todo: Put internal to `ShimEvent`?
|
|
1376
1380
|
}
|
|
1377
1381
|
});
|
|
1378
1382
|
}
|
|
@@ -1451,6 +1455,7 @@
|
|
|
1451
1455
|
if (child) {
|
|
1452
1456
|
child._defaultSync = this._defaultSync;
|
|
1453
1457
|
}
|
|
1458
|
+
/* 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 */
|
|
1454
1459
|
return (child || this)._dispatchEvent(eventCopy, false);
|
|
1455
1460
|
}
|
|
1456
1461
|
case phases.AT_TARGET:
|
|
@@ -1748,7 +1753,7 @@
|
|
|
1748
1753
|
* databaseNameLengthLimit: number|false,
|
|
1749
1754
|
* escapeNFDForDatabaseNames: boolean,
|
|
1750
1755
|
* addSQLiteExtension: boolean,
|
|
1751
|
-
* memoryDatabase: string,
|
|
1756
|
+
* memoryDatabase: string|null|undefined,
|
|
1752
1757
|
* deleteDatabaseFiles: boolean,
|
|
1753
1758
|
* databaseBasePath: string,
|
|
1754
1759
|
* sysDatabaseBasePath: string,
|
|
@@ -1891,13 +1896,27 @@
|
|
|
1891
1896
|
// Various types of in-memory databases that can auto-delete
|
|
1892
1897
|
['memoryDatabase',
|
|
1893
1898
|
/**
|
|
1894
|
-
*
|
|
1899
|
+
* `null`/`undefined` are accepted (and left unvalidated against the
|
|
1900
|
+
* regex below) specifically so this can be reset back to its
|
|
1901
|
+
* unset/disabled state after being set: unlike other `CFG`
|
|
1902
|
+
* boolean-ish switches (e.g. `sqlMemoryQuota`, which is checked
|
|
1903
|
+
* with a falsy `if (CFG.sqlMemoryQuota)`), `memoryDatabase`'s own
|
|
1904
|
+
* usage sites check `typeof CFG.memoryDatabase === 'string'`, so
|
|
1905
|
+
* even the empty string counts as "on" (it's a distinct, valid
|
|
1906
|
+
* in-memory mode of its own -- an unnamed private temporary
|
|
1907
|
+
* database -- not an "off" state). Without this, once set to any
|
|
1908
|
+
* string there would be no value passable back through this same
|
|
1909
|
+
* validator that turns `useMemoryDatabase` false again.
|
|
1910
|
+
* @param {string|null|undefined} val
|
|
1895
1911
|
* @throws {TypeError}
|
|
1896
1912
|
* @returns {void}
|
|
1897
1913
|
*/
|
|
1898
1914
|
function (val) {
|
|
1915
|
+
if (val === null || val === undefined) {
|
|
1916
|
+
return;
|
|
1917
|
+
}
|
|
1899
1918
|
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)) {
|
|
1900
|
-
throw new TypeError('`memoryDatabase` must be the empty string, ":memory:", or a
|
|
1919
|
+
throw new TypeError('`memoryDatabase` must be `null`/`undefined` (to reset it to disabled), the empty string, ' + '":memory:", or a "file::memory:[?queryString][#hash] URL".');
|
|
1901
1920
|
}
|
|
1902
1921
|
}],
|
|
1903
1922
|
// NODE-SPECIFIC CONFIG
|
|
@@ -1951,10 +1970,7 @@
|
|
|
1951
1970
|
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) {
|
|
1952
1971
|
// Could add a corresponding surrogate for compatibility with `node-sqlite3`: https://bugs.python.org/issue12569 and https://stackoverflow.com/a/6701665/271577
|
|
1953
1972
|
// but Chrome having problems
|
|
1954
|
-
|
|
1955
|
-
return '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1956
|
-
}
|
|
1957
|
-
return (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1973
|
+
return unmatchedHighSurrogate ? '^2' + unmatchedHighSurrogate.codePointAt().toString(16).padStart(4, '0') : (precedingLow || '') + '^3' + unmatchedLowSurrogate.codePointAt().toString(16).padStart(4, '0');
|
|
1958
1974
|
});
|
|
1959
1975
|
}
|
|
1960
1976
|
|
|
@@ -2621,7 +2637,8 @@
|
|
|
2621
2637
|
function createNativeDOMException(name, message) {
|
|
2622
2638
|
// @ts-expect-error It's ok
|
|
2623
2639
|
// eslint-disable-next-line new-cap -- Ok
|
|
2624
|
-
return new DOMException.prototype.constructor(message,
|
|
2640
|
+
return new DOMException.prototype.constructor(message, /* c8 ignore next -- Defensive fallback; every call site in this codebase always supplies a `name` */
|
|
2641
|
+
name || 'DOMException');
|
|
2625
2642
|
}
|
|
2626
2643
|
|
|
2627
2644
|
// From web-platform-tests testharness.js name_code_map (though not in new spec)
|
|
@@ -2785,8 +2802,10 @@
|
|
|
2785
2802
|
*/
|
|
2786
2803
|
get: function get() {
|
|
2787
2804
|
if (!(this instanceof DOMException ||
|
|
2805
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2788
2806
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2789
2807
|
this instanceof DummyDOMException ||
|
|
2808
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2790
2809
|
// @ts-ignore Just checking; needed under some TS versions
|
|
2791
2810
|
this instanceof Error)) {
|
|
2792
2811
|
throw new TypeError('Illegal invocation');
|
|
@@ -2845,6 +2864,7 @@
|
|
|
2845
2864
|
value: DOMException
|
|
2846
2865
|
});
|
|
2847
2866
|
|
|
2867
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2848
2868
|
// @ts-ignore We don't need all its properties; needed under some TS versions
|
|
2849
2869
|
return DOMException;
|
|
2850
2870
|
}
|
|
@@ -2857,6 +2877,7 @@
|
|
|
2857
2877
|
* @returns {Error}
|
|
2858
2878
|
*/
|
|
2859
2879
|
function createNonNativeDOMException(name, message) {
|
|
2880
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
2860
2881
|
// @ts-ignore It's ok; needed under some TS versions
|
|
2861
2882
|
return new ShimNonNativeDOMException(message, name);
|
|
2862
2883
|
}
|
|
@@ -2879,6 +2900,8 @@
|
|
|
2879
2900
|
return;
|
|
2880
2901
|
}
|
|
2881
2902
|
var msg = error && _typeof(error) === 'object' && error.message ? error.message : (/** @type {string} */error);
|
|
2903
|
+
|
|
2904
|
+
/* c8 ignore next -- Defensive fallback for an environment lacking `console.error` */
|
|
2882
2905
|
var method = typeof console.error === 'function' ? 'error' : 'log';
|
|
2883
2906
|
console[method](name + ': ' + message + '. ' + (msg || ''));
|
|
2884
2907
|
if (console.trace) {
|
|
@@ -3064,8 +3087,10 @@
|
|
|
3064
3087
|
*/
|
|
3065
3088
|
IDBRequest.__super = function IDBRequest() {
|
|
3066
3089
|
var _this = this;
|
|
3090
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3067
3091
|
// @ts-ignore It's ok
|
|
3068
3092
|
this[Symbol.toStringTag] = 'IDBRequest';
|
|
3093
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3069
3094
|
// @ts-ignore Part of `ShimEventTarget`
|
|
3070
3095
|
this.__setOptions({
|
|
3071
3096
|
legacyOutputDidListenersThrowFlag: true // Event hook for IndexedB
|
|
@@ -3123,10 +3148,7 @@
|
|
|
3123
3148
|
* @returns {import('./IDBTransaction.js').IDBTransactionFull|null|undefined}
|
|
3124
3149
|
*/
|
|
3125
3150
|
IDBRequest.prototype.__getParent = function () {
|
|
3126
|
-
|
|
3127
|
-
return null;
|
|
3128
|
-
}
|
|
3129
|
-
return this.__transaction;
|
|
3151
|
+
return this.toString() === '[object IDBOpenDBRequest]' ? null : this.__transaction;
|
|
3130
3152
|
};
|
|
3131
3153
|
|
|
3132
3154
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
@@ -3185,8 +3207,10 @@
|
|
|
3185
3207
|
function IDBOpenDBRequest() {
|
|
3186
3208
|
IDBRequest.__super.call(this);
|
|
3187
3209
|
|
|
3210
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3188
3211
|
// @ts-ignore It's ok
|
|
3189
3212
|
this[Symbol.toStringTag] = 'IDBOpenDBRequest';
|
|
3213
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
3190
3214
|
// @ts-ignore It's ok
|
|
3191
3215
|
this.__setOptions({
|
|
3192
3216
|
legacyOutputDidListenersThrowFlag: true,
|
|
@@ -4056,6 +4080,33 @@
|
|
|
4056
4080
|
return convertValueToKeyValueDecoded(input, null, true, true);
|
|
4057
4081
|
}
|
|
4058
4082
|
|
|
4083
|
+
/**
|
|
4084
|
+
* @param {BufferSource|ArrayBufferLike} buffer
|
|
4085
|
+
* @returns {boolean}
|
|
4086
|
+
*/
|
|
4087
|
+
function isBufferDetached(buffer) {
|
|
4088
|
+
// Use the standard property if available
|
|
4089
|
+
// @ts-expect-error - More recent API
|
|
4090
|
+
if (typeof buffer.detached === 'boolean') {
|
|
4091
|
+
// @ts-expect-error - More recent API
|
|
4092
|
+
return buffer.detached;
|
|
4093
|
+
}
|
|
4094
|
+
/* c8 ignore next 14 -- Older browsers */
|
|
4095
|
+
|
|
4096
|
+
// Fallback check via byteLength and constructor test
|
|
4097
|
+
if (buffer.byteLength !== 0) {
|
|
4098
|
+
return false;
|
|
4099
|
+
}
|
|
4100
|
+
try {
|
|
4101
|
+
// @ts-expect-error Ok
|
|
4102
|
+
// eslint-disable-next-line no-new -- Throwaway
|
|
4103
|
+
new Uint8Array(buffer);
|
|
4104
|
+
return false;
|
|
4105
|
+
} catch (_unused) {
|
|
4106
|
+
return true;
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4059
4110
|
/**
|
|
4060
4111
|
*
|
|
4061
4112
|
* @param {BufferSource} O
|
|
@@ -4068,15 +4119,16 @@
|
|
|
4068
4119
|
var length;
|
|
4069
4120
|
if (ArrayBuffer.isView(O)) {
|
|
4070
4121
|
// Has [[ViewedArrayBuffer]] internal slot
|
|
4071
|
-
var arrayBuffer = O.buffer;
|
|
4072
|
-
if (arrayBuffer === undefined) {
|
|
4073
|
-
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was undefined.');
|
|
4074
|
-
}
|
|
4075
4122
|
offset = O.byteOffset; // [[ByteOffset]] (will also throw as desired if detached)
|
|
4076
4123
|
length = O.byteLength; // [[ByteLength]] (will also throw as desired if detached)
|
|
4077
4124
|
} else {
|
|
4078
4125
|
length = O.byteLength; // [[ArrayBufferByteLength]] on ArrayBuffer (will also throw as desired if detached)
|
|
4079
4126
|
}
|
|
4127
|
+
var arrayBuffer = ArrayBuffer.isView(O) ? O.buffer : O;
|
|
4128
|
+
if (isBufferDetached(arrayBuffer)) {
|
|
4129
|
+
throw new TypeError('Could not copy the bytes held by a buffer source as the buffer was detached.');
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4080
4132
|
// const octets = new Uint8Array(input);
|
|
4081
4133
|
// const octets = types.binary.decode(types.binary.encode(input));
|
|
4082
4134
|
return new Uint8Array(
|
|
@@ -4148,7 +4200,7 @@
|
|
|
4148
4200
|
var octets;
|
|
4149
4201
|
try {
|
|
4150
4202
|
octets = getCopyBytesHeldByBufferSource(/** @type {BufferSource} */input);
|
|
4151
|
-
} catch (
|
|
4203
|
+
} catch (_unused2) {
|
|
4152
4204
|
return {
|
|
4153
4205
|
type: type,
|
|
4154
4206
|
invalid: true,
|
|
@@ -4197,8 +4249,14 @@
|
|
|
4197
4249
|
}
|
|
4198
4250
|
if (!multiEntry || !fullKeys && keys.every(function (k) {
|
|
4199
4251
|
return cmp(/** @type {Key} */k, /** @type {Key} */key.value) !== 0;
|
|
4200
|
-
}) ||
|
|
4201
|
-
|
|
4252
|
+
}) ||
|
|
4253
|
+
// `keys` holds full `{type, value}` objects here (see
|
|
4254
|
+
// `safePush` below), so -- like the sibling branch
|
|
4255
|
+
// above -- `cmp` (which expects raw `Value`s, not
|
|
4256
|
+
// decoded key objects) must compare their `.value`s,
|
|
4257
|
+
// not the wrapper objects themselves.
|
|
4258
|
+
fullKeys && keys.every(function (k) {
|
|
4259
|
+
return cmp(/** @type {Key} */ /** @type {KeyValueObject} */k.value, /** @type {Key} */key.value) !== 0;
|
|
4202
4260
|
})) {
|
|
4203
4261
|
safePush(keys, fullKeys ? key : key.value);
|
|
4204
4262
|
}
|
|
@@ -4223,12 +4281,9 @@
|
|
|
4223
4281
|
{
|
|
4224
4282
|
var date = /** @type {Date} */input;
|
|
4225
4283
|
if (!Number.isNaN(date.getTime())) {
|
|
4226
|
-
return
|
|
4227
|
-
type: type,
|
|
4228
|
-
value: date.getTime()
|
|
4229
|
-
} : {
|
|
4284
|
+
return {
|
|
4230
4285
|
type: type,
|
|
4231
|
-
value: new Date(date)
|
|
4286
|
+
value: fullKeys ? date.getTime() : new Date(date)
|
|
4232
4287
|
};
|
|
4233
4288
|
}
|
|
4234
4289
|
return {
|
|
@@ -4316,10 +4371,7 @@
|
|
|
4316
4371
|
if (r.failure) {
|
|
4317
4372
|
return r;
|
|
4318
4373
|
}
|
|
4319
|
-
|
|
4320
|
-
return convertValueToKeyValueDecoded(r.value, null, false, fullKeys);
|
|
4321
|
-
}
|
|
4322
|
-
return convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4374
|
+
return !multiEntry ? convertValueToKeyValueDecoded(r.value, null, false, fullKeys) : convertValueToMultiEntryKeyDecoded(r.value, fullKeys);
|
|
4323
4375
|
}
|
|
4324
4376
|
|
|
4325
4377
|
/**
|
|
@@ -4500,10 +4552,7 @@
|
|
|
4500
4552
|
*/
|
|
4501
4553
|
function isMultiEntryMatch(encodedEntry, encodedKey) {
|
|
4502
4554
|
var keyType = encodedCharToKeyType[encodedKey.slice(0, 1)];
|
|
4503
|
-
|
|
4504
|
-
return encodedKey.indexOf(encodedEntry) > 1;
|
|
4505
|
-
}
|
|
4506
|
-
return encodedKey === encodedEntry;
|
|
4555
|
+
return keyType === 'array' ? encodedKey.indexOf(encodedEntry) > 1 : encodedKey === encodedEntry;
|
|
4507
4556
|
}
|
|
4508
4557
|
|
|
4509
4558
|
/**
|
|
@@ -4621,10 +4670,7 @@
|
|
|
4621
4670
|
* @returns {undefined|ValueType}
|
|
4622
4671
|
*/
|
|
4623
4672
|
function _decode(key, inArray) {
|
|
4624
|
-
|
|
4625
|
-
return undefined;
|
|
4626
|
-
}
|
|
4627
|
-
return types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4673
|
+
return typeof key !== 'string' ? undefined : types[encodedCharToKeyType[key.slice(0, 1)]].decode(key, inArray);
|
|
4628
4674
|
}
|
|
4629
4675
|
|
|
4630
4676
|
/**
|
|
@@ -5030,10 +5076,11 @@
|
|
|
5030
5076
|
if (hasLower && hasUpper) {
|
|
5031
5077
|
sql.push('AND');
|
|
5032
5078
|
}
|
|
5033
|
-
if (hasUpper) {
|
|
5034
|
-
|
|
5035
|
-
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5079
|
+
if (!hasUpper) {
|
|
5080
|
+
return;
|
|
5036
5081
|
}
|
|
5082
|
+
sql.push(quotedKeyColumnName, range.upperOpen ? '<' : '<=', '?');
|
|
5083
|
+
sqlValues.push(escapeSQLiteStatement(/** @type {string} */encodedUpperKey));
|
|
5037
5084
|
}
|
|
5038
5085
|
|
|
5039
5086
|
/**
|
|
@@ -5046,10 +5093,7 @@
|
|
|
5046
5093
|
if (instanceOf(value, IDBKeyRange)) {
|
|
5047
5094
|
// We still need to validate IDBKeyRange-like objects (the above check is based on loose duck-typing)
|
|
5048
5095
|
var range = /** @type {IDBKeyRangeFull} */value;
|
|
5049
|
-
|
|
5050
|
-
return IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen);
|
|
5051
|
-
}
|
|
5052
|
-
return range;
|
|
5096
|
+
return range.toString() !== '[object IDBKeyRange]' ? IDBKeyRange.__createInstance(range.lower, range.upper, range.lowerOpen, range.upperOpen) : range;
|
|
5053
5097
|
}
|
|
5054
5098
|
if (isNullish(value)) {
|
|
5055
5099
|
if (nullDisallowed) {
|
|
@@ -5094,9 +5138,11 @@
|
|
|
5094
5138
|
if (testObject.test) {
|
|
5095
5139
|
cleanInterface = true;
|
|
5096
5140
|
}
|
|
5141
|
+
/* c8 ignore start -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5097
5142
|
} catch (err) {
|
|
5098
5143
|
// Object.defineProperty does not work as intended.
|
|
5099
5144
|
}
|
|
5145
|
+
/* c8 ignore stop -- Defensive fallback for an engine with a broken `Object.defineProperty` */
|
|
5100
5146
|
}
|
|
5101
5147
|
|
|
5102
5148
|
/**
|
|
@@ -5297,6 +5343,7 @@
|
|
|
5297
5343
|
this._length = 0;
|
|
5298
5344
|
};
|
|
5299
5345
|
DOMStringList.prototype = DOMStringListAlias.prototype;
|
|
5346
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
5300
5347
|
// @ts-ignore It's ok; needed under some TS versions
|
|
5301
5348
|
return /** @type {DOMStringListFull} */new DOMStringList();
|
|
5302
5349
|
}
|
|
@@ -5596,12 +5643,14 @@
|
|
|
5596
5643
|
*/
|
|
5597
5644
|
IDBTransaction.prototype.__executeRequests = function () {
|
|
5598
5645
|
var me = this;
|
|
5646
|
+
/* 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. */
|
|
5599
5647
|
if (me.__running) {
|
|
5600
5648
|
if (CFG.DEBUG) {
|
|
5601
5649
|
console.log('Looks like the request set is already running', me.mode);
|
|
5602
5650
|
}
|
|
5603
5651
|
return;
|
|
5604
5652
|
}
|
|
5653
|
+
/* c8 ignore stop -- see comment above */
|
|
5605
5654
|
|
|
5606
5655
|
// The synchronous script that created this transaction (and
|
|
5607
5656
|
// synchronously queued whatever requests it wanted to) has now
|
|
@@ -5651,6 +5700,7 @@
|
|
|
5651
5700
|
queueMicrotask(cb);
|
|
5652
5701
|
return;
|
|
5653
5702
|
}
|
|
5703
|
+
/* 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. */
|
|
5654
5704
|
try {
|
|
5655
5705
|
tx.executeSql('SELECT 1', [], function () {
|
|
5656
5706
|
cb();
|
|
@@ -5664,6 +5714,7 @@
|
|
|
5664
5714
|
// abort the transaction here.
|
|
5665
5715
|
me.__abortTransaction(/** @type {Error|DOMException} */err);
|
|
5666
5716
|
}
|
|
5717
|
+
/* c8 ignore stop -- see comment above */
|
|
5667
5718
|
}
|
|
5668
5719
|
|
|
5669
5720
|
/**
|
|
@@ -5676,21 +5727,26 @@
|
|
|
5676
5727
|
* @returns {void}
|
|
5677
5728
|
*/
|
|
5678
5729
|
function success(result, req) {
|
|
5730
|
+
/* 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. */
|
|
5679
5731
|
if (me.__errored || me.__requestsFinished) {
|
|
5680
5732
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5681
5733
|
return;
|
|
5682
5734
|
}
|
|
5735
|
+
/* c8 ignore stop -- see comment above */
|
|
5683
5736
|
if (req) {
|
|
5684
5737
|
q.req = req; // Need to do this in case of cursors
|
|
5685
5738
|
}
|
|
5739
|
+
/* 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. */
|
|
5686
5740
|
if (!q.req) {
|
|
5687
|
-
// TS guard
|
|
5688
5741
|
return;
|
|
5689
5742
|
}
|
|
5743
|
+
/* c8 ignore stop -- see comment above */
|
|
5744
|
+
/* 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. */
|
|
5690
5745
|
if (q.req.__done) {
|
|
5691
5746
|
// Avoid continuing with aborted requests
|
|
5692
5747
|
return;
|
|
5693
5748
|
}
|
|
5749
|
+
/* c8 ignore stop -- see comment above */
|
|
5694
5750
|
q.req.__done = true;
|
|
5695
5751
|
q.req.__result = result;
|
|
5696
5752
|
q.req.__error = null;
|
|
@@ -5707,6 +5763,7 @@
|
|
|
5707
5763
|
// is what actually resets `__handlerActive`, once it's
|
|
5708
5764
|
// confirmed (across its own bounded microtask wait) that no
|
|
5709
5765
|
// such continuation queued anything.
|
|
5766
|
+
/* 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. */
|
|
5710
5767
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
5711
5768
|
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
|
|
5712
5769
|
if (!me.__committed) {
|
|
@@ -5716,6 +5773,7 @@
|
|
|
5716
5773
|
return;
|
|
5717
5774
|
}
|
|
5718
5775
|
}
|
|
5776
|
+
/* c8 ignore stop -- see comment above */
|
|
5719
5777
|
runContinuationSafely(advanceAfterDispatch);
|
|
5720
5778
|
}
|
|
5721
5779
|
|
|
@@ -5727,15 +5785,19 @@
|
|
|
5727
5785
|
* @returns {void}
|
|
5728
5786
|
*/
|
|
5729
5787
|
function error() {
|
|
5788
|
+
/* 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. */
|
|
5730
5789
|
if (me.__errored || me.__requestsFinished) {
|
|
5731
5790
|
// We've already called "onerror", "onabort", or thrown within
|
|
5732
5791
|
// the transaction, so don't do it again.
|
|
5733
5792
|
return;
|
|
5734
5793
|
}
|
|
5794
|
+
/* c8 ignore stop -- see comment above */
|
|
5795
|
+
/* 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. */
|
|
5735
5796
|
if (q.req && q.req.__done) {
|
|
5736
5797
|
// Avoid continuing with aborted requests
|
|
5737
5798
|
return;
|
|
5738
5799
|
}
|
|
5800
|
+
/* c8 ignore stop -- see comment above */
|
|
5739
5801
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
5740
5802
|
args[_key] = arguments[_key];
|
|
5741
5803
|
}
|
|
@@ -5760,10 +5822,11 @@
|
|
|
5760
5822
|
}
|
|
5761
5823
|
});
|
|
5762
5824
|
q.req.addDefaultEventListener('error', function () {
|
|
5825
|
+
/* 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. */
|
|
5763
5826
|
if (!q.req) {
|
|
5764
|
-
// TS guard
|
|
5765
5827
|
return;
|
|
5766
5828
|
}
|
|
5829
|
+
/* c8 ignore stop -- see comment above */
|
|
5767
5830
|
me.__abortTransaction(q.req.__error);
|
|
5768
5831
|
});
|
|
5769
5832
|
me.__active = true;
|
|
@@ -5775,16 +5838,19 @@
|
|
|
5775
5838
|
q.req.dispatchEvent(e);
|
|
5776
5839
|
// Do not set __active or __handlerActive flags to false yet --
|
|
5777
5840
|
// see the matching comment in `success`, above.
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5841
|
+
/* 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. */
|
|
5842
|
+
if (!e.__legacyOutputDidListenersThrowError) {
|
|
5843
|
+
return;
|
|
5844
|
+
}
|
|
5845
|
+
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
|
|
5846
|
+
e.preventDefault(); // Prevent 'error' default as steps indicate we should abort with `AbortError` even without cancellation
|
|
5847
|
+
if (me.__committed) {
|
|
5848
|
+
// An explicit `commit()` locks in the commit, so errors thrown afterward must not abort it
|
|
5849
|
+
runContinuationSafely(advanceAfterDispatch);
|
|
5850
|
+
return;
|
|
5787
5851
|
}
|
|
5852
|
+
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after error).'));
|
|
5853
|
+
/* c8 ignore stop -- see comment above */
|
|
5788
5854
|
}
|
|
5789
5855
|
|
|
5790
5856
|
/**
|
|
@@ -5808,10 +5874,12 @@
|
|
|
5808
5874
|
// (not reset here).
|
|
5809
5875
|
return true;
|
|
5810
5876
|
}
|
|
5877
|
+
/* 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. */
|
|
5811
5878
|
if (q.req.__done) {
|
|
5812
5879
|
// Avoid continuing with aborted requests
|
|
5813
5880
|
return false;
|
|
5814
5881
|
}
|
|
5882
|
+
/* c8 ignore stop -- see comment above */
|
|
5815
5883
|
// We're now handing off to (possibly async) work for
|
|
5816
5884
|
// this request, so the transaction is no longer active
|
|
5817
5885
|
// until its own `success`/`error` dispatch (below)
|
|
@@ -5836,18 +5904,22 @@
|
|
|
5836
5904
|
return;
|
|
5837
5905
|
}
|
|
5838
5906
|
q.op(tx, q.args, success, error, executeNextRequest);
|
|
5907
|
+
/* 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. */
|
|
5839
5908
|
} catch (e) {
|
|
5840
5909
|
error(/** @type {Error} */e);
|
|
5841
5910
|
}
|
|
5911
|
+
/* c8 ignore stop -- see comment above */
|
|
5842
5912
|
}
|
|
5843
5913
|
|
|
5844
5914
|
/**
|
|
5845
5915
|
* @returns {void}
|
|
5846
5916
|
*/
|
|
5847
5917
|
function runQueuedRequest() {
|
|
5918
|
+
/* c8 ignore start -- Defensive: only reached if `prepareNextRequest` returns `false` (see its own ignore comment above for why that's not reliably reproducible). */
|
|
5848
5919
|
if (!prepareNextRequest()) {
|
|
5849
5920
|
return;
|
|
5850
5921
|
}
|
|
5922
|
+
/* c8 ignore stop -- see comment above */
|
|
5851
5923
|
launchQueuedOp();
|
|
5852
5924
|
}
|
|
5853
5925
|
|
|
@@ -5878,9 +5950,11 @@
|
|
|
5878
5950
|
* @returns {void}
|
|
5879
5951
|
*/
|
|
5880
5952
|
function checkQueueEntry(attemptsLeft) {
|
|
5953
|
+
/* 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. */
|
|
5881
5954
|
if (me.__errored || me.__requestsFinished) {
|
|
5882
5955
|
return;
|
|
5883
5956
|
}
|
|
5957
|
+
/* c8 ignore stop -- see comment above */
|
|
5884
5958
|
if (i < me.__requests.length) {
|
|
5885
5959
|
runQueuedRequest();
|
|
5886
5960
|
return;
|
|
@@ -5902,10 +5976,12 @@
|
|
|
5902
5976
|
* @returns {void}
|
|
5903
5977
|
*/
|
|
5904
5978
|
function executeNextRequest() {
|
|
5979
|
+
/* 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. */
|
|
5905
5980
|
if (me.__errored || me.__requestsFinished) {
|
|
5906
5981
|
// We've already called "onerror", "onabort", or thrown within the transaction, so don't do it again.
|
|
5907
5982
|
return;
|
|
5908
5983
|
}
|
|
5984
|
+
/* c8 ignore stop -- see comment above */
|
|
5909
5985
|
i++;
|
|
5910
5986
|
if (i >= me.__requests.length) {
|
|
5911
5987
|
checkQueueEntry(keepAliveAttempts);
|
|
@@ -5940,31 +6016,34 @@
|
|
|
5940
6016
|
* @returns {void}
|
|
5941
6017
|
*/
|
|
5942
6018
|
function advanceAfterDispatch() {
|
|
6019
|
+
/* 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. */
|
|
5943
6020
|
if (me.__errored || me.__requestsFinished) {
|
|
5944
6021
|
return;
|
|
5945
6022
|
}
|
|
6023
|
+
/* c8 ignore stop -- see comment above */
|
|
5946
6024
|
i++;
|
|
5947
6025
|
if (i >= me.__requests.length) {
|
|
5948
6026
|
checkQueueEntry(keepAliveAttempts);
|
|
5949
6027
|
return;
|
|
5950
6028
|
}
|
|
5951
6029
|
keepAliveAndWait(function () {
|
|
5952
|
-
if (
|
|
5953
|
-
|
|
5954
|
-
}
|
|
5955
|
-
if (!prepareNextRequest()) {
|
|
6030
|
+
/* 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. */
|
|
6031
|
+
if (me.__errored || me.__requestsFinished || !prepareNextRequest()) {
|
|
5956
6032
|
return;
|
|
5957
6033
|
}
|
|
6034
|
+
/* c8 ignore stop -- see comment above */
|
|
5958
6035
|
launchQueuedOp();
|
|
5959
6036
|
});
|
|
5960
6037
|
}
|
|
5961
6038
|
executeNextRequest();
|
|
5962
6039
|
}, function webSQLError(webSQLErr) {
|
|
6040
|
+
/* 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. */
|
|
5963
6041
|
// @ts-expect-error It's ok
|
|
5964
6042
|
if (webSQLErr === true) {
|
|
5965
6043
|
// Not a genuine SQL error
|
|
5966
6044
|
return;
|
|
5967
6045
|
}
|
|
6046
|
+
/* c8 ignore stop -- see comment above */
|
|
5968
6047
|
var err = webSQLErrback(/** @type {Error & {code?: number}} */webSQLErr);
|
|
5969
6048
|
me.__abortTransaction(err);
|
|
5970
6049
|
}, function () {
|
|
@@ -5975,18 +6054,25 @@
|
|
|
5975
6054
|
// Node
|
|
5976
6055
|
return;
|
|
5977
6056
|
}
|
|
6057
|
+
/* 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. */
|
|
5978
6058
|
if (!me.__transactionEndCallback && !me.__requestsFinished) {
|
|
5979
6059
|
me.__transactionFinished = true;
|
|
5980
6060
|
return;
|
|
5981
6061
|
}
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
6062
|
+
/* c8 ignore stop -- see comment above */
|
|
6063
|
+
/* 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. */
|
|
6064
|
+
if (!me.__transactionEndCallback || me.__completed || me.__transFinishedCbFired) {
|
|
6065
|
+
return;
|
|
5985
6066
|
}
|
|
6067
|
+
me.__transFinishedCbFired = true;
|
|
6068
|
+
me.__transFinishedCb(me.__errored, me.__transactionEndCallback);
|
|
6069
|
+
/* c8 ignore stop -- see comment above */
|
|
5986
6070
|
}, function (currentTask, err, done, rollback, commit) {
|
|
6071
|
+
/* 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. */
|
|
5987
6072
|
if (err) {
|
|
5988
6073
|
return true;
|
|
5989
6074
|
}
|
|
6075
|
+
/* c8 ignore stop -- see comment above */
|
|
5990
6076
|
// `readonly` transactions never hold a real SQL transaction open
|
|
5991
6077
|
// (see `WebSQLTransaction`'s constructor skipping `BEGIN;` for
|
|
5992
6078
|
// them), so there's no commit/rollback round trip to defer --
|
|
@@ -6035,6 +6121,7 @@
|
|
|
6035
6121
|
*/
|
|
6036
6122
|
function complete() {
|
|
6037
6123
|
me.__completed = true;
|
|
6124
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6038
6125
|
if (CFG.DEBUG) {
|
|
6039
6126
|
console.log('Transaction completed');
|
|
6040
6127
|
}
|
|
@@ -6044,6 +6131,7 @@
|
|
|
6044
6131
|
me.dispatchEvent(evt);
|
|
6045
6132
|
me.__internal = false;
|
|
6046
6133
|
me.dispatchEvent(createEvent('__complete'));
|
|
6134
|
+
/* 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. */
|
|
6047
6135
|
} catch (e) {
|
|
6048
6136
|
me.__internal = false;
|
|
6049
6137
|
// An error occurred in the "oncomplete" handler.
|
|
@@ -6051,6 +6139,7 @@
|
|
|
6051
6139
|
// (this may seem odd/bad, but it's how all native IndexedDB implementations work)
|
|
6052
6140
|
me.__errored = true;
|
|
6053
6141
|
throw e;
|
|
6142
|
+
/* c8 ignore stop -- see comment above */
|
|
6054
6143
|
} finally {
|
|
6055
6144
|
activeTransactions.delete(me);
|
|
6056
6145
|
me.__storeHandles = {};
|
|
@@ -6058,10 +6147,12 @@
|
|
|
6058
6147
|
}
|
|
6059
6148
|
}
|
|
6060
6149
|
if (me.mode === 'readwrite' || me.mode === 'readonly') {
|
|
6150
|
+
/* 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. */
|
|
6061
6151
|
if (me.__transactionFinished) {
|
|
6062
6152
|
complete();
|
|
6063
6153
|
return;
|
|
6064
6154
|
}
|
|
6155
|
+
/* c8 ignore stop -- see comment above */
|
|
6065
6156
|
me.__transactionEndCallback = complete;
|
|
6066
6157
|
// The underlying SQL driver's own "queue empty" check
|
|
6067
6158
|
// (`nonstandardTransCb`, above) typically already ran and
|
|
@@ -6097,6 +6188,7 @@
|
|
|
6097
6188
|
IDBTransaction.prototype.__createRequest = function (source) {
|
|
6098
6189
|
var me = this;
|
|
6099
6190
|
var request = IDBRequest.__createInstance();
|
|
6191
|
+
/* 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. */
|
|
6100
6192
|
request.__source = source !== undefined ? source : me.db;
|
|
6101
6193
|
request.__transaction = me;
|
|
6102
6194
|
return request;
|
|
@@ -6166,9 +6258,11 @@
|
|
|
6166
6258
|
* @returns {void}
|
|
6167
6259
|
*/
|
|
6168
6260
|
IDBTransaction.prototype.__assertActive = function () {
|
|
6261
|
+
/* 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. */
|
|
6169
6262
|
if (!this.__active || !this.__handlerActive || this.__committed) {
|
|
6170
6263
|
throw createDOMException('TransactionInactiveError', 'A request was placed against a transaction which is currently not active, or which is finished');
|
|
6171
6264
|
}
|
|
6265
|
+
/* c8 ignore stop -- see comment above */
|
|
6172
6266
|
};
|
|
6173
6267
|
|
|
6174
6268
|
/**
|
|
@@ -6182,6 +6276,7 @@
|
|
|
6182
6276
|
}
|
|
6183
6277
|
};
|
|
6184
6278
|
|
|
6279
|
+
/* 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. */
|
|
6185
6280
|
/**
|
|
6186
6281
|
* @this {IDBTransactionFull}
|
|
6187
6282
|
* @returns {void}
|
|
@@ -6189,6 +6284,7 @@
|
|
|
6189
6284
|
IDBTransaction.prototype.__assertVersionChange = function () {
|
|
6190
6285
|
IDBTransaction.__assertVersionChange(this);
|
|
6191
6286
|
};
|
|
6287
|
+
/* c8 ignore stop -- see comment above */
|
|
6192
6288
|
|
|
6193
6289
|
/**
|
|
6194
6290
|
* Returns the specified object store.
|
|
@@ -6210,9 +6306,12 @@
|
|
|
6210
6306
|
throw createDOMException('NotFoundError', objectStoreName + ' is not participating in this transaction');
|
|
6211
6307
|
}
|
|
6212
6308
|
var store = me.db.__objectStores[objectStoreName];
|
|
6309
|
+
/* 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. */
|
|
6213
6310
|
if (!store) {
|
|
6214
6311
|
throw createDOMException('NotFoundError', objectStoreName + ' does not exist in ' + me.db.name);
|
|
6215
6312
|
}
|
|
6313
|
+
/* c8 ignore stop -- see comment above */
|
|
6314
|
+
|
|
6216
6315
|
if (!Object.hasOwn(me.__storeHandles, objectStoreName) ||
|
|
6217
6316
|
// These latter conditions are to allow store
|
|
6218
6317
|
// recreation to create new clone object
|
|
@@ -6231,10 +6330,12 @@
|
|
|
6231
6330
|
IDBTransaction.prototype.__abortTransaction = function (err) {
|
|
6232
6331
|
var me = this;
|
|
6233
6332
|
logError('Error', 'An error occurred in a transaction', err);
|
|
6333
|
+
/* 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. */
|
|
6234
6334
|
if (me.__errored) {
|
|
6235
6335
|
// We've already called "onerror", "onabort", or thrown, so don't do it again.
|
|
6236
6336
|
return;
|
|
6237
6337
|
}
|
|
6338
|
+
/* c8 ignore stop -- see comment above */
|
|
6238
6339
|
me.__errored = true;
|
|
6239
6340
|
if (me.mode === 'versionchange') {
|
|
6240
6341
|
// Steps for aborting an upgrade transaction
|
|
@@ -6264,19 +6365,16 @@
|
|
|
6264
6365
|
if (err !== null) {
|
|
6265
6366
|
me.__error = err;
|
|
6266
6367
|
}
|
|
6368
|
+
|
|
6369
|
+
/* 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. */
|
|
6267
6370
|
if (me.__requestsFinished && err !== null) {
|
|
6268
6371
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
6269
|
-
// So throw the error instead.
|
|
6270
|
-
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
6271
|
-
// call, which now checks `__requestsFinished` itself first and
|
|
6272
|
-
// throws `InvalidStateError` synchronously before ever reaching
|
|
6273
|
-
// this point -- so this guard is just defense in depth against
|
|
6274
|
-
// `err` somehow being `null` some other way, not something this
|
|
6275
|
-
// path should see in practice.
|
|
6372
|
+
// So throw the error instead.
|
|
6276
6373
|
setTimeout(function () {
|
|
6277
6374
|
throw err;
|
|
6278
6375
|
}, 0);
|
|
6279
6376
|
}
|
|
6377
|
+
/* c8 ignore stop -- see comment above */
|
|
6280
6378
|
|
|
6281
6379
|
/**
|
|
6282
6380
|
* @param {import('websql-configurable/lib/websql/WebSQLTransaction.js').default|null} [tx]
|
|
@@ -6285,13 +6383,17 @@
|
|
|
6285
6383
|
*/
|
|
6286
6384
|
function abort(tx, errOrResult) {
|
|
6287
6385
|
if (!tx) {
|
|
6386
|
+
/* 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. */
|
|
6288
6387
|
if (CFG.DEBUG) {
|
|
6289
6388
|
console.log('Rollback not possible due to missing transaction', me);
|
|
6290
6389
|
}
|
|
6390
|
+
/* 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. */
|
|
6291
6391
|
} else if (errOrResult && 'code' in errOrResult && typeof errOrResult.code === 'number') {
|
|
6292
6392
|
if (CFG.DEBUG) {
|
|
6293
6393
|
console.log('Rollback erred; feature is probably not supported as per WebSQL', me);
|
|
6294
6394
|
}
|
|
6395
|
+
/* c8 ignore stop -- see comment above */
|
|
6396
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6295
6397
|
} else if (CFG.DEBUG) {
|
|
6296
6398
|
console.log('Rollback succeeded', me);
|
|
6297
6399
|
}
|
|
@@ -6307,10 +6409,11 @@
|
|
|
6307
6409
|
// behaves first-in-first-out with the same timeout so we could
|
|
6308
6410
|
// just use a `forEach`.
|
|
6309
6411
|
return promises.then(function () {
|
|
6412
|
+
/* 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. */
|
|
6310
6413
|
if (!q.req) {
|
|
6311
|
-
// TS guard
|
|
6312
6414
|
throw new Error('Missing request');
|
|
6313
6415
|
}
|
|
6416
|
+
/* c8 ignore stop -- see comment above */
|
|
6314
6417
|
q.req.__done = true;
|
|
6315
6418
|
q.req.__result = undefined;
|
|
6316
6419
|
q.req.__error = createDOMException('AbortError', 'A request was aborted (an unfinished request).');
|
|
@@ -6321,10 +6424,11 @@
|
|
|
6321
6424
|
return new SyncPromise(/** @type {(resolve: (value?: unknown) => void) => void} */
|
|
6322
6425
|
function (resolve) {
|
|
6323
6426
|
setTimeout(function () {
|
|
6427
|
+
/* c8 ignore start -- Dead code: same invariant as above -- `q.req` was already confirmed truthy by the outer `.filter()` and is never reset. */
|
|
6324
6428
|
if (!q.req) {
|
|
6325
|
-
// TS guard
|
|
6326
6429
|
throw new Error('Missing request');
|
|
6327
6430
|
}
|
|
6431
|
+
/* c8 ignore stop -- see comment above */
|
|
6328
6432
|
q.req.dispatchEvent(reqEvt); // No need to catch errors
|
|
6329
6433
|
resolve();
|
|
6330
6434
|
}, 0);
|
|
@@ -6344,10 +6448,12 @@
|
|
|
6344
6448
|
releaseFinishedTransaction(me);
|
|
6345
6449
|
}, 0);
|
|
6346
6450
|
return undefined;
|
|
6451
|
+
/* 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. */
|
|
6347
6452
|
}).catch(function (err) {
|
|
6348
6453
|
console.log('Abort error');
|
|
6349
6454
|
throw err;
|
|
6350
6455
|
});
|
|
6456
|
+
/* c8 ignore stop -- see comment above */
|
|
6351
6457
|
}
|
|
6352
6458
|
me.__transFinishedCb(true, function (rollback) {
|
|
6353
6459
|
if (rollback && me.__tx) {
|
|
@@ -6355,20 +6461,24 @@
|
|
|
6355
6461
|
// rollback automatically), but for Node.js, etc., we give chance for
|
|
6356
6462
|
// manual aborts which would otherwise not work.
|
|
6357
6463
|
if (me.mode === 'readwrite') {
|
|
6464
|
+
/* 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. */
|
|
6358
6465
|
if (me.__transactionFinished) {
|
|
6359
6466
|
abort();
|
|
6360
6467
|
return;
|
|
6361
6468
|
}
|
|
6469
|
+
/* c8 ignore stop -- see comment above */
|
|
6362
6470
|
me.__transactionEndCallback = abort;
|
|
6363
6471
|
return;
|
|
6364
6472
|
}
|
|
6365
6473
|
try {
|
|
6366
6474
|
me.__tx.executeSql('ROLLBACK', [], abort, /** @type {import('websql-configurable/lib/websql/WebSQLTransaction.js').SqlErrorCallback} */abort); // Not working in some circumstances, even in Node
|
|
6475
|
+
/* c8 ignore start -- Defensive: the underlying WebSQL/SQLite driver throwing synchronously on `ROLLBACK` is not reliably reproducible without mocking the SQL layer. */
|
|
6367
6476
|
} catch (err) {
|
|
6368
6477
|
// Browser errs when transaction has ended and since it most likely already erred here,
|
|
6369
6478
|
// we call to abort
|
|
6370
6479
|
abort();
|
|
6371
6480
|
}
|
|
6481
|
+
/* c8 ignore stop -- see comment above */
|
|
6372
6482
|
} else {
|
|
6373
6483
|
abort(null, {
|
|
6374
6484
|
code: 0
|
|
@@ -6386,6 +6496,7 @@
|
|
|
6386
6496
|
if (!(me instanceof IDBTransaction)) {
|
|
6387
6497
|
throw new TypeError('Illegal invocation');
|
|
6388
6498
|
}
|
|
6499
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6389
6500
|
if (CFG.DEBUG) {
|
|
6390
6501
|
console.log('The transaction was aborted', me);
|
|
6391
6502
|
}
|
|
@@ -6417,6 +6528,7 @@
|
|
|
6417
6528
|
if (!me.__active || !me.__handlerActive || me.__committed) {
|
|
6418
6529
|
throw createDOMException('InvalidStateError', 'Failed to execute \'commit\' on \'IDBTransaction\': The transaction is not active.');
|
|
6419
6530
|
}
|
|
6531
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
6420
6532
|
if (CFG.DEBUG) {
|
|
6421
6533
|
console.log('The transaction was explicitly committed', me);
|
|
6422
6534
|
}
|
|
@@ -6459,6 +6571,7 @@
|
|
|
6459
6571
|
};
|
|
6460
6572
|
|
|
6461
6573
|
// object store methods behave differently: see https://github.com/w3c/IndexedDB/issues/192
|
|
6574
|
+
/* 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. */
|
|
6462
6575
|
/**
|
|
6463
6576
|
*
|
|
6464
6577
|
* @param {IDBTransactionFull} tx
|
|
@@ -6474,6 +6587,7 @@
|
|
|
6474
6587
|
throw err;
|
|
6475
6588
|
}
|
|
6476
6589
|
};
|
|
6590
|
+
/* c8 ignore stop -- see comment above */
|
|
6477
6591
|
|
|
6478
6592
|
/**
|
|
6479
6593
|
*
|
|
@@ -7571,7 +7685,7 @@
|
|
|
7571
7685
|
return Number.isNaN(t) ? "NaN" : t;
|
|
7572
7686
|
},
|
|
7573
7687
|
revive: function revive(e) {
|
|
7574
|
-
return "NaN" === e ?
|
|
7688
|
+
return new Date("NaN" === e ? NaN : e);
|
|
7575
7689
|
}
|
|
7576
7690
|
}
|
|
7577
7691
|
},
|
|
@@ -8431,9 +8545,12 @@
|
|
|
8431
8545
|
}).find(function (preset) {
|
|
8432
8546
|
return preset && !Array.isArray(preset) && 'filelist' in preset;
|
|
8433
8547
|
});
|
|
8434
|
-
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8435
|
-
|
|
8436
|
-
var
|
|
8548
|
+
var origFileList = specSet && !Array.isArray(specSet) && 'filelist' in specSet ? specSet.filelist
|
|
8549
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8550
|
+
var origTest = origFileList && _typeof(origFileList) === 'object' && 'test' in origFileList && typeof origFileList.test === 'function' ? origFileList.test
|
|
8551
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.test` ever goes missing */ : undefined;
|
|
8552
|
+
var origRevive = origFileList && _typeof(origFileList) === 'object' && 'revive' in origFileList && typeof origFileList.revive === 'function' ? origFileList.revive
|
|
8553
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */ : undefined;
|
|
8437
8554
|
var customFileList = origFileList ? _objectSpread2(_objectSpread2({}, origFileList), {}, {
|
|
8438
8555
|
/**
|
|
8439
8556
|
* @param {unknown} x
|
|
@@ -8441,10 +8558,7 @@
|
|
|
8441
8558
|
* @returns {boolean}
|
|
8442
8559
|
*/
|
|
8443
8560
|
test: function test(x, state) {
|
|
8444
|
-
|
|
8445
|
-
return x instanceof FileList;
|
|
8446
|
-
}
|
|
8447
|
-
return typeof origTest === 'function' ? origTest(x, state) : false;
|
|
8561
|
+
return typeof FileList !== 'undefined' ? x instanceof FileList : typeof origTest === 'function' && origTest(x, state);
|
|
8448
8562
|
},
|
|
8449
8563
|
/**
|
|
8450
8564
|
* @param {unknown} x
|
|
@@ -8455,10 +8569,12 @@
|
|
|
8455
8569
|
if (typeof FileList !== 'undefined') {
|
|
8456
8570
|
return Reflect.construct(FileList, [x]);
|
|
8457
8571
|
}
|
|
8572
|
+
/* c8 ignore next -- Defensive fallback if typeson-registry's `filelist.revive` ever goes missing */
|
|
8458
8573
|
return typeof origRevive === 'function' ? origRevive(x, state) : undefined;
|
|
8459
8574
|
}
|
|
8460
|
-
}) : undefined;
|
|
8461
|
-
var typeson = new Typeson().register([fe,
|
|
8575
|
+
}) /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */ : undefined;
|
|
8576
|
+
var typeson = new Typeson().register([fe, /* c8 ignore next -- Defensive fallback if typeson-registry's `filelist` preset entry ever goes missing */
|
|
8577
|
+
customFileList ? {
|
|
8462
8578
|
filelist: customFileList
|
|
8463
8579
|
} : {}]);
|
|
8464
8580
|
|
|
@@ -8614,7 +8730,6 @@
|
|
|
8614
8730
|
* __unique: boolean,
|
|
8615
8731
|
* __objectStore: import('./IDBObjectStore.js').IDBObjectStoreFull,
|
|
8616
8732
|
* __keyPath: import('./Key.js').KeyPath,
|
|
8617
|
-
* __recreated?: boolean,
|
|
8618
8733
|
* __fetchIndexData: (
|
|
8619
8734
|
* range: Query,
|
|
8620
8735
|
* opType: "value"|"key"|"count",
|
|
@@ -8708,6 +8823,7 @@
|
|
|
8708
8823
|
storeHandle.__indexHandles[newName] = oldIndexHandle; // Ensure new reference accessible
|
|
8709
8824
|
me.__pendingName = oldName;
|
|
8710
8825
|
var colInfoToPreserveArr = [['key', 'BLOB ' + (objectStore.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY')], ['value', 'BLOB']].concat(
|
|
8826
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
8711
8827
|
// @ts-ignore Has numeric indexes instead of iterator; needed under some TS versions
|
|
8712
8828
|
_toConsumableArray(objectStore.indexNames).filter(function (indexName) {
|
|
8713
8829
|
return indexName !== newName;
|
|
@@ -8759,7 +8875,7 @@
|
|
|
8759
8875
|
}
|
|
8760
8876
|
});
|
|
8761
8877
|
/** @type {const} */
|
|
8762
|
-
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'
|
|
8878
|
+
['__pendingCreate', '__pendingDelete', '__deleted', '__originalName'].forEach(function (p) {
|
|
8763
8879
|
// @ts-expect-error Why is this type "never"?
|
|
8764
8880
|
idx[p] = index[p];
|
|
8765
8881
|
});
|
|
@@ -8791,11 +8907,12 @@
|
|
|
8791
8907
|
var transaction = store.transaction;
|
|
8792
8908
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8793
8909
|
transaction.__addNonRequestToTransactionQueue(function createIndex(tx, args, success, failure) {
|
|
8794
|
-
var columnExists = idx &&
|
|
8910
|
+
var columnExists = idx && idx.__deleted; // This check must occur here rather than earlier as properties may not have been set yet otherwise
|
|
8795
8911
|
|
|
8796
8912
|
/** @type {{[key: string]: boolean}} */
|
|
8797
8913
|
var indexValues = {};
|
|
8798
8914
|
|
|
8915
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8799
8916
|
/**
|
|
8800
8917
|
* @param {WebSQLTransaction} tx
|
|
8801
8918
|
* @param {(Error & {code?: number})} err
|
|
@@ -8804,6 +8921,7 @@
|
|
|
8804
8921
|
function error(tx, err) {
|
|
8805
8922
|
failure(createDOMException('UnknownError', 'Could not create index "' + indexName + '"' + err.code + '::' + err.message, err));
|
|
8806
8923
|
}
|
|
8924
|
+
/* c8 ignore stop -- see comment above */
|
|
8807
8925
|
|
|
8808
8926
|
/**
|
|
8809
8927
|
* @param {WebSQLTransaction} tx
|
|
@@ -8853,12 +8971,6 @@
|
|
|
8853
8971
|
} else {
|
|
8854
8972
|
delete index.__pendingCreate;
|
|
8855
8973
|
delete indexHandle.__pendingCreate;
|
|
8856
|
-
if (index.__deleted) {
|
|
8857
|
-
delete index.__deleted;
|
|
8858
|
-
delete indexHandle.__deleted;
|
|
8859
|
-
index.__recreated = true;
|
|
8860
|
-
indexHandle.__recreated = true;
|
|
8861
|
-
}
|
|
8862
8974
|
indexValues = {};
|
|
8863
8975
|
success(store);
|
|
8864
8976
|
}
|
|
@@ -8867,7 +8979,7 @@
|
|
|
8867
8979
|
}, /** @type {SqlErrorCallback} */error);
|
|
8868
8980
|
}
|
|
8869
8981
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
8870
|
-
var escapedIndexNameSQL = escapeIndexNameForSQL(
|
|
8982
|
+
var escapedIndexNameSQL = escapeIndexNameForSQL(indexName);
|
|
8871
8983
|
|
|
8872
8984
|
/**
|
|
8873
8985
|
* @param {WebSQLTransaction} tx
|
|
@@ -8919,6 +9031,7 @@
|
|
|
8919
9031
|
var transaction = store.transaction;
|
|
8920
9032
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
8921
9033
|
transaction.__addNonRequestToTransactionQueue(function deleteIndex(tx, args, success, failure) {
|
|
9034
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
8922
9035
|
/**
|
|
8923
9036
|
* @param {WebSQLTransaction} tx
|
|
8924
9037
|
* @param {(Error & {code?: number})} err
|
|
@@ -8927,6 +9040,7 @@
|
|
|
8927
9040
|
function error(tx, err) {
|
|
8928
9041
|
failure(createDOMException('UnknownError', 'Could not delete index "' + index.name + '"', err));
|
|
8929
9042
|
}
|
|
9043
|
+
/* c8 ignore stop -- see comment above */
|
|
8930
9044
|
|
|
8931
9045
|
/**
|
|
8932
9046
|
* @returns {void}
|
|
@@ -8935,7 +9049,6 @@
|
|
|
8935
9049
|
// Update the object store's index list
|
|
8936
9050
|
IDBIndex.__updateIndexList(store, tx, function (store) {
|
|
8937
9051
|
delete index.__pendingDelete;
|
|
8938
|
-
delete index.__recreated;
|
|
8939
9052
|
index.__deleted = true;
|
|
8940
9053
|
if (indexHandle) {
|
|
8941
9054
|
indexHandle.__deleted = true;
|
|
@@ -8996,20 +9109,18 @@
|
|
|
8996
9109
|
* @param {Query} range
|
|
8997
9110
|
* @param {"value"|"key"|"count"} opType
|
|
8998
9111
|
* @param {boolean} nullDisallowed
|
|
8999
|
-
* @param {number} [count]
|
|
9000
9112
|
* @this {IDBIndexFull}
|
|
9001
9113
|
* @returns {import('./IDBRequest.js').IDBRequestFull}
|
|
9002
9114
|
*/
|
|
9003
|
-
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed
|
|
9115
|
+
IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed) {
|
|
9004
9116
|
var me = this;
|
|
9005
|
-
if (count !== undefined) {
|
|
9006
|
-
count = enforceRange(count, 'unsigned long');
|
|
9007
|
-
}
|
|
9008
9117
|
IDBIndex.__invalidStateIfDeleted(me);
|
|
9009
9118
|
IDBObjectStore.__invalidStateIfDeleted(me.objectStore);
|
|
9119
|
+
/* c8 ignore start -- Defensive: `IDBObjectStore.__invalidStateIfDeleted` just above already throws when `me.objectStore.__deleted` is true, so this identical check can never be reached. */
|
|
9010
9120
|
if (me.objectStore.__deleted) {
|
|
9011
9121
|
throw createDOMException('InvalidStateError', "This index's object store has been deleted");
|
|
9012
9122
|
}
|
|
9123
|
+
/* c8 ignore stop -- see comment above */
|
|
9013
9124
|
IDBTransaction.__assertActive(me.objectStore.transaction);
|
|
9014
9125
|
if (nullDisallowed && isNullish(range)) {
|
|
9015
9126
|
throw createDOMException('DataError', 'No key or range was specified');
|
|
@@ -9019,7 +9130,7 @@
|
|
|
9019
9130
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
9020
9131
|
args[_key] = arguments[_key];
|
|
9021
9132
|
}
|
|
9022
|
-
executeFetchIndexData.apply(void 0,
|
|
9133
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat(args));
|
|
9023
9134
|
}, undefined, me);
|
|
9024
9135
|
};
|
|
9025
9136
|
|
|
@@ -9178,13 +9289,16 @@
|
|
|
9178
9289
|
var colInfoToPreserve = colInfoToPreserveArr.map(function (colInfo) {
|
|
9179
9290
|
return colInfo.join(' ');
|
|
9180
9291
|
});
|
|
9292
|
+
/* 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. */
|
|
9181
9293
|
var listColInfoToPreserve = colInfoToPreserve.length ? colInfoToPreserve.join(', ') + ', ' : '';
|
|
9294
|
+
/* c8 ignore next -- Defensive: see comment above. */
|
|
9182
9295
|
var listColsToPreserve = colNamesToPreserve.length ? colNamesToPreserve.join(', ') + ', ' : '';
|
|
9183
9296
|
|
|
9184
9297
|
// We could adapt the approach at https://stackoverflow.com/a/8430746/271577
|
|
9185
9298
|
// to make the approach reusable without passing column names, but it is a bit fragile
|
|
9186
9299
|
/** @type {import('./IDBTransaction.js').IDBTransactionFull} */
|
|
9187
9300
|
store.transaction.__addNonRequestToTransactionQueue(function renameIndex(tx, args, success, error) {
|
|
9301
|
+
/* 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. */
|
|
9188
9302
|
/**
|
|
9189
9303
|
* @param {WebSQLTransaction} tx
|
|
9190
9304
|
* @param {(Error & {code?: number})} err
|
|
@@ -9193,6 +9307,7 @@
|
|
|
9193
9307
|
function sqlError(tx, err) {
|
|
9194
9308
|
error(err);
|
|
9195
9309
|
}
|
|
9310
|
+
/* c8 ignore stop -- see comment above */
|
|
9196
9311
|
/**
|
|
9197
9312
|
* @returns {void}
|
|
9198
9313
|
*/
|
|
@@ -9201,8 +9316,14 @@
|
|
|
9201
9316
|
cb(tx, success);
|
|
9202
9317
|
return;
|
|
9203
9318
|
}
|
|
9319
|
+
/* 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. */
|
|
9204
9320
|
success();
|
|
9205
9321
|
}
|
|
9322
|
+
/* c8 ignore stop -- see comment above */
|
|
9323
|
+
if (!CFG.useSQLiteIndexes) {
|
|
9324
|
+
finish();
|
|
9325
|
+
return;
|
|
9326
|
+
}
|
|
9206
9327
|
// See https://www.sqlite.org/lang_altertable.html#otheralter
|
|
9207
9328
|
// We don't query for indexes as we already have the info
|
|
9208
9329
|
// This approach has the advantage of auto-deleting indexes via the DROP TABLE
|
|
@@ -9226,10 +9347,6 @@
|
|
|
9226
9347
|
console.log(sql);
|
|
9227
9348
|
}
|
|
9228
9349
|
tx.executeSql(sql, [], function (tx) {
|
|
9229
|
-
if (!CFG.useSQLiteIndexes) {
|
|
9230
|
-
finish();
|
|
9231
|
-
return;
|
|
9232
|
-
}
|
|
9233
9350
|
var indexCreations = colNamesToPreserve.slice(2) // Doing `key` separately and no need for index on `value`
|
|
9234
9351
|
.map(function (escapedIndexNameSQL) {
|
|
9235
9352
|
return new SyncPromise(function (resolve, reject) {
|
|
@@ -9238,13 +9355,16 @@
|
|
|
9238
9355
|
// if (CFG.DEBUG) { console.log(sql); }
|
|
9239
9356
|
// tx.executeSql(sql, [], function () {
|
|
9240
9357
|
var sql = 'CREATE INDEX ' + escapedIndexToRecreate + ' ON ' + escapedStoreNameSQL + '(' + escapedIndexNameSQL + ')';
|
|
9358
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
9241
9359
|
if (CFG.DEBUG) {
|
|
9242
9360
|
console.log(sql);
|
|
9243
9361
|
}
|
|
9244
|
-
tx.executeSql(sql, [], resolve,
|
|
9362
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9363
|
+
/** @type {SqlErrorCallback} */
|
|
9245
9364
|
function (tx, err) {
|
|
9246
9365
|
reject(err);
|
|
9247
|
-
}
|
|
9366
|
+
}
|
|
9367
|
+
/* c8 ignore stop -- see comment above */);
|
|
9248
9368
|
// }, function (tx, err) {
|
|
9249
9369
|
// reject(err);
|
|
9250
9370
|
// });
|
|
@@ -9262,19 +9382,25 @@
|
|
|
9262
9382
|
if (CFG.DEBUG) {
|
|
9263
9383
|
console.log(sql);
|
|
9264
9384
|
}
|
|
9265
|
-
tx.executeSql(sql, [], resolve,
|
|
9385
|
+
tx.executeSql(sql, [], resolve, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9386
|
+
/** @type {SqlErrorCallback} */
|
|
9266
9387
|
function (tx, err) {
|
|
9267
9388
|
reject(err);
|
|
9268
|
-
}
|
|
9269
|
-
|
|
9389
|
+
}
|
|
9390
|
+
/* c8 ignore stop -- see comment above */);
|
|
9391
|
+
}, /* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9392
|
+
/** @type {SqlErrorCallback} */
|
|
9270
9393
|
function (tx, err) {
|
|
9271
9394
|
reject(err);
|
|
9272
|
-
}
|
|
9395
|
+
}
|
|
9396
|
+
/* c8 ignore stop -- see comment above */);
|
|
9273
9397
|
}));
|
|
9274
9398
|
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: unknown) => PromiseLike<never>} */
|
|
9275
9399
|
error).catch(function (err) {
|
|
9400
|
+
/* c8 ignore start -- Defensive: only reached if `finish` or the outer `error` callback itself throws; not reliably reproducible. */
|
|
9276
9401
|
console.log('Index rename error');
|
|
9277
9402
|
throw err;
|
|
9403
|
+
/* c8 ignore stop -- see comment above */
|
|
9278
9404
|
});
|
|
9279
9405
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
9280
9406
|
}, /** @type {SqlErrorCallback} */sqlError);
|
|
@@ -9303,7 +9429,6 @@
|
|
|
9303
9429
|
/* eslint-enable unicorn/no-top-level-side-effects -- Would be good */
|
|
9304
9430
|
|
|
9305
9431
|
/**
|
|
9306
|
-
* @param {number|null} count
|
|
9307
9432
|
* @param {boolean} unboundedDisallowed
|
|
9308
9433
|
* @param {IDBIndexFull} index
|
|
9309
9434
|
* @param {boolean} hasKey
|
|
@@ -9320,12 +9445,9 @@
|
|
|
9320
9445
|
* @param {(tx: WebSQLTransaction, err: (Error & {code?: number})) => void} error
|
|
9321
9446
|
* @returns {void}
|
|
9322
9447
|
*/
|
|
9323
|
-
function executeFetchIndexData(
|
|
9448
|
+
function executeFetchIndexData(unboundedDisallowed, index, hasKey, range, opType, multiChecks, sql, sqlValues, tx, args, success, error) {
|
|
9324
9449
|
if (unboundedDisallowed) {
|
|
9325
|
-
|
|
9326
|
-
}
|
|
9327
|
-
if (count) {
|
|
9328
|
-
sql.push('LIMIT', String(count));
|
|
9450
|
+
sql.push('LIMIT', '1');
|
|
9329
9451
|
}
|
|
9330
9452
|
var isCount = opType === 'count';
|
|
9331
9453
|
if (CFG.DEBUG) {
|
|
@@ -9363,41 +9485,48 @@
|
|
|
9363
9485
|
var escapedIndexNameForKeyCol = escapeIndexNameForSQLKeyColumn(index.name);
|
|
9364
9486
|
var encodedKey = _encode(range, index.multiEntry);
|
|
9365
9487
|
var _loop = function _loop() {
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
record = row;
|
|
9386
|
-
} else if (!hasKey && !multiChecks) {
|
|
9387
|
-
if (rowKey !== undefined) {
|
|
9388
|
-
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9488
|
+
var row = /** @type {{key: string, value: string, [k: string]: string}} */data.rows.item(i);
|
|
9489
|
+
var rowKey = /** @type {import('./Key.js').ValueTypeArray} */
|
|
9490
|
+
_decode(row[escapedIndexNameForKeyCol]);
|
|
9491
|
+
var record;
|
|
9492
|
+
if (hasKey && (multiChecks && /** @type {import('./Key.js').ValueType[]} */range.some(
|
|
9493
|
+
/**
|
|
9494
|
+
* @param {import('./Key.js').ValueType} check
|
|
9495
|
+
* @returns {boolean}
|
|
9496
|
+
*/
|
|
9497
|
+
function (check) {
|
|
9498
|
+
return rowKey.includes(check);
|
|
9499
|
+
}) ||
|
|
9500
|
+
// More precise than our SQL
|
|
9501
|
+
isMultiEntryMatch(
|
|
9502
|
+
// Added `JSON.stringify` as was having problems with
|
|
9503
|
+
// `JSON.stringify` encoding added to nested
|
|
9504
|
+
// array keys
|
|
9505
|
+
JSON.stringify(encodedKey).slice(1, -1), row[escapedIndexNameForKeyCol]))) {
|
|
9506
|
+
recordCount++;
|
|
9389
9507
|
record = row;
|
|
9508
|
+
} else if (!hasKey && !multiChecks) {
|
|
9509
|
+
if (rowKey !== undefined) {
|
|
9510
|
+
recordCount += Array.isArray(rowKey) ? rowKey.length : 1;
|
|
9511
|
+
record = row;
|
|
9512
|
+
}
|
|
9390
9513
|
}
|
|
9391
|
-
|
|
9392
|
-
|
|
9514
|
+
/* 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. */
|
|
9515
|
+
if (!record) {
|
|
9516
|
+
return 0; // continue
|
|
9517
|
+
}
|
|
9518
|
+
/* c8 ignore stop -- see comment above */
|
|
9519
|
+
|
|
9393
9520
|
records.push(decode$1(record));
|
|
9394
9521
|
if (unboundedDisallowed) {
|
|
9395
9522
|
return 1; // break
|
|
9396
9523
|
}
|
|
9397
|
-
}
|
|
9398
|
-
|
|
9524
|
+
},
|
|
9525
|
+
_ret;
|
|
9399
9526
|
for (var i = 0; i < data.rows.length; i++) {
|
|
9400
|
-
|
|
9527
|
+
_ret = _loop();
|
|
9528
|
+
if (_ret === 0) continue;
|
|
9529
|
+
if (_ret === 1) break;
|
|
9401
9530
|
}
|
|
9402
9531
|
} else {
|
|
9403
9532
|
for (var _i = 0; _i < data.rows.length; _i++) {
|
|
@@ -9411,8 +9540,16 @@
|
|
|
9411
9540
|
if (isCount) {
|
|
9412
9541
|
success(recordCount);
|
|
9413
9542
|
} else if (recordCount === 0) {
|
|
9543
|
+
// `unboundedDisallowed` is always `true` here: this function is only reached (for
|
|
9544
|
+
// non-`count` `opType`s) via `get`/`getKey`, which always pass `nullDisallowed: true`
|
|
9545
|
+
// through as `unboundedDisallowed`. `getAll`/`getAllKeys`/`getAllRecords` use a
|
|
9546
|
+
// different (cursor-based) code path, so the `unboundedDisallowed`-`false` case
|
|
9547
|
+
// (returning `[]` here) is unreachable given current callers.
|
|
9548
|
+
/* c8 ignore next -- see comment above */
|
|
9414
9549
|
success(unboundedDisallowed ? undefined : []);
|
|
9415
9550
|
} else {
|
|
9551
|
+
// `unboundedDisallowed` is always `true` here; see comment above.
|
|
9552
|
+
/* c8 ignore next -- see comment above */
|
|
9416
9553
|
success(unboundedDisallowed ? records[0] : records);
|
|
9417
9554
|
}
|
|
9418
9555
|
}, /** @type {SqlErrorCallback} */error);
|
|
@@ -9656,6 +9793,7 @@
|
|
|
9656
9793
|
tx.executeSql(sql, sqlValues, function (tx) {
|
|
9657
9794
|
// This SQL preserves indexes per https://www.sqlite.org/lang_altertable.html
|
|
9658
9795
|
var sql = 'ALTER TABLE ' + escapeStoreNameForSQL(oldName) + ' RENAME TO ' + escapeStoreNameForSQL(name);
|
|
9796
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG` while renaming a store. */
|
|
9659
9797
|
if (CFG.DEBUG) {
|
|
9660
9798
|
console.log(sql);
|
|
9661
9799
|
}
|
|
@@ -9664,8 +9802,10 @@
|
|
|
9664
9802
|
success();
|
|
9665
9803
|
});
|
|
9666
9804
|
}, function (tx, err) {
|
|
9805
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9667
9806
|
error(err);
|
|
9668
9807
|
return false;
|
|
9808
|
+
/* c8 ignore stop -- see comment above */
|
|
9669
9809
|
});
|
|
9670
9810
|
});
|
|
9671
9811
|
}
|
|
@@ -9739,6 +9879,7 @@
|
|
|
9739
9879
|
storeHandles[storeName] = IDBObjectStore.__clone(store, transaction);
|
|
9740
9880
|
}
|
|
9741
9881
|
transaction.__addNonRequestToTransactionQueue(function createObjectStore(tx, args, success, failure) {
|
|
9882
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9742
9883
|
/**
|
|
9743
9884
|
* @param {WebSQLTransaction} tx
|
|
9744
9885
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9751,6 +9892,8 @@
|
|
|
9751
9892
|
failure(createDOMException('UnknownError', 'Could not create object store "' + storeName + '"', err));
|
|
9752
9893
|
return false;
|
|
9753
9894
|
}
|
|
9895
|
+
/* c8 ignore stop -- see comment above */
|
|
9896
|
+
|
|
9754
9897
|
var escapedStoreNameSQL = escapeStoreNameForSQL(storeName);
|
|
9755
9898
|
// key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE
|
|
9756
9899
|
var sql = ['CREATE TABLE', escapedStoreNameSQL, '(key BLOB', store.autoIncrement ? 'UNIQUE, inc INTEGER PRIMARY KEY AUTOINCREMENT' : 'PRIMARY KEY', ', value BLOB)'].join(' ');
|
|
@@ -9805,6 +9948,7 @@
|
|
|
9805
9948
|
|
|
9806
9949
|
// Remove the object store from WebSQL
|
|
9807
9950
|
transaction.__addNonRequestToTransactionQueue(function deleteObjectStore(tx, args, success, failure) {
|
|
9951
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
9808
9952
|
/**
|
|
9809
9953
|
* @param {WebSQLTransaction} tx
|
|
9810
9954
|
* @param {(Error & {code?: number})} [err]
|
|
@@ -9817,6 +9961,8 @@
|
|
|
9817
9961
|
failure(createDOMException('UnknownError', 'Could not delete ObjectStore', err));
|
|
9818
9962
|
return false;
|
|
9819
9963
|
}
|
|
9964
|
+
/* c8 ignore stop -- see comment above */
|
|
9965
|
+
|
|
9820
9966
|
tx.executeSql('SELECT "name" FROM __sys__ WHERE "name" = ?', [escapeSQLiteStatement(store.__currentName)], function (tx, data) {
|
|
9821
9967
|
if (data.rows.length > 0) {
|
|
9822
9968
|
tx.executeSql('DROP TABLE ' + escapeStoreNameForSQL(store.__currentName), [], function () {
|
|
@@ -9996,13 +10142,15 @@
|
|
|
9996
10142
|
return;
|
|
9997
10143
|
}
|
|
9998
10144
|
var indexKeyValue = indexKey.value;
|
|
10145
|
+
/* 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. */
|
|
9999
10146
|
if (indexKeyValue === undefined) {
|
|
10000
10147
|
resolve(undefined);
|
|
10001
10148
|
return;
|
|
10002
10149
|
}
|
|
10150
|
+
/* c8 ignore stop -- see comment above */
|
|
10003
10151
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
10004
10152
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
10005
|
-
executeFetchIndexData.apply(void 0,
|
|
10153
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
10006
10154
|
if (key === undefined || excludeKey !== undefined && cmp(/** @type {import('./Key.js').Key} */key, excludeKey) === 0) {
|
|
10007
10155
|
resolve(undefined);
|
|
10008
10156
|
return;
|
|
@@ -10082,16 +10230,18 @@
|
|
|
10082
10230
|
* @returns {void}
|
|
10083
10231
|
*/
|
|
10084
10232
|
function setIndexInfo(index) {
|
|
10233
|
+
/* 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. */
|
|
10085
10234
|
if (indexKeyValue === undefined) {
|
|
10086
10235
|
return;
|
|
10087
10236
|
}
|
|
10237
|
+
/* c8 ignore stop -- see comment above */
|
|
10088
10238
|
paramMap[index.__currentName] = /** @type {string} */
|
|
10089
10239
|
_encode(indexKeyValue, index.multiEntry);
|
|
10090
10240
|
}
|
|
10091
10241
|
if (index.unique) {
|
|
10092
10242
|
var multiCheck = index.multiEntry && Array.isArray(indexKeyValue);
|
|
10093
10243
|
var fetchArgs = buildFetchIndexDataSQL(true, index, indexKeyValue, 'key', multiCheck);
|
|
10094
|
-
executeFetchIndexData.apply(void 0,
|
|
10244
|
+
executeFetchIndexData.apply(void 0, _toConsumableArray(fetchArgs).concat([tx, null, function success(key) {
|
|
10095
10245
|
if (key === undefined) {
|
|
10096
10246
|
setIndexInfo(index);
|
|
10097
10247
|
resolve(undefined);
|
|
@@ -10182,6 +10332,7 @@
|
|
|
10182
10332
|
_me$__validateKeyAndV2 = _slicedToArray(_me$__validateKeyAndV, 2),
|
|
10183
10333
|
ky = _me$__validateKeyAndV2[0],
|
|
10184
10334
|
clonedValue = _me$__validateKeyAndV2[1];
|
|
10335
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10185
10336
|
// @ts-ignore -- Private API
|
|
10186
10337
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, true, ky);
|
|
10187
10338
|
return request;
|
|
@@ -10213,6 +10364,7 @@
|
|
|
10213
10364
|
_me$__validateKeyAndV4 = _slicedToArray(_me$__validateKeyAndV3, 2),
|
|
10214
10365
|
ky = _me$__validateKeyAndV4[0],
|
|
10215
10366
|
clonedValue = _me$__validateKeyAndV4[1];
|
|
10367
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
10216
10368
|
// @ts-ignore -- Private API
|
|
10217
10369
|
IDBObjectStore.__storingRecordObjectStore(request, me, true, clonedValue, false, ky);
|
|
10218
10370
|
return request;
|
|
@@ -10239,8 +10391,10 @@
|
|
|
10239
10391
|
}
|
|
10240
10392
|
cb(tx);
|
|
10241
10393
|
}, function (tx, err) {
|
|
10394
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10242
10395
|
error(err);
|
|
10243
10396
|
return false;
|
|
10397
|
+
/* c8 ignore stop -- see comment above */
|
|
10244
10398
|
});
|
|
10245
10399
|
};
|
|
10246
10400
|
|
|
@@ -10349,16 +10503,20 @@
|
|
|
10349
10503
|
return;
|
|
10350
10504
|
}
|
|
10351
10505
|
ret = getKey ? _decode(unescapeSQLiteResponse(/** @type {{key: string}} */data.rows.item(0).key), false) : decode(unescapeSQLiteResponse(/** @type {{value: string}} */data.rows.item(0).value));
|
|
10506
|
+
/* 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. */
|
|
10352
10507
|
} catch (e) {
|
|
10353
10508
|
// If no result is returned, or error occurs when parsing JSON
|
|
10354
10509
|
if (CFG.DEBUG) {
|
|
10355
10510
|
console.log(e);
|
|
10356
10511
|
}
|
|
10357
10512
|
}
|
|
10513
|
+
/* c8 ignore stop -- see comment above */
|
|
10358
10514
|
success(ret);
|
|
10359
10515
|
}, function (tx, err) {
|
|
10516
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10360
10517
|
error(err);
|
|
10361
10518
|
return false;
|
|
10519
|
+
/* c8 ignore stop -- see comment above */
|
|
10362
10520
|
});
|
|
10363
10521
|
}, undefined, me);
|
|
10364
10522
|
};
|
|
@@ -10470,8 +10628,10 @@
|
|
|
10470
10628
|
});
|
|
10471
10629
|
success();
|
|
10472
10630
|
}, function (tx, err) {
|
|
10631
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10473
10632
|
error(err);
|
|
10474
10633
|
return false;
|
|
10634
|
+
/* c8 ignore stop -- see comment above */
|
|
10475
10635
|
});
|
|
10476
10636
|
}, undefined, me);
|
|
10477
10637
|
};
|
|
@@ -10499,8 +10659,10 @@
|
|
|
10499
10659
|
});
|
|
10500
10660
|
success();
|
|
10501
10661
|
}, function (tx, err) {
|
|
10662
|
+
/* c8 ignore start -- Defensive: SQL execution error, not reliably reproducible without mocking the SQL layer. */
|
|
10502
10663
|
error(err);
|
|
10503
10664
|
return false;
|
|
10665
|
+
/* c8 ignore stop -- see comment above */
|
|
10504
10666
|
});
|
|
10505
10667
|
}, undefined, me);
|
|
10506
10668
|
};
|
|
@@ -10835,7 +10997,7 @@
|
|
|
10835
10997
|
if (keyPath !== null && !isValidKeyPath(keyPath)) {
|
|
10836
10998
|
throw createDOMException('SyntaxError', 'The keyPath argument contains an invalid key path.');
|
|
10837
10999
|
}
|
|
10838
|
-
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete) {
|
|
11000
|
+
if (Object.hasOwn(this.__objectStores, storeName) && !this.__objectStores[storeName].__pendingDelete && !this.__objectStores[storeName].__deleted) {
|
|
10839
11001
|
throw createDOMException('ConstraintError', 'Object store "' + storeName + '" already exists in ' + this.name);
|
|
10840
11002
|
}
|
|
10841
11003
|
var autoInc = createOptions.autoIncrement;
|
|
@@ -10984,7 +11146,6 @@
|
|
|
10984
11146
|
}
|
|
10985
11147
|
};
|
|
10986
11148
|
|
|
10987
|
-
// Todo __forceClose: Add tests for `__forceClose`
|
|
10988
11149
|
/**
|
|
10989
11150
|
*
|
|
10990
11151
|
* @param {string} msg
|
|
@@ -10993,23 +11154,39 @@
|
|
|
10993
11154
|
*/
|
|
10994
11155
|
IDBDatabase.prototype.__forceClose = function (msg) {
|
|
10995
11156
|
var me = this;
|
|
11157
|
+
// `close()` (below) resets `me.__transactions` to `[]`, so the
|
|
11158
|
+
// transactions to abort -- and the total count the completion check
|
|
11159
|
+
// below needs -- must be captured before calling it, not read back off
|
|
11160
|
+
// `me.__transactions` afterward.
|
|
11161
|
+
var transactions = me.__transactions;
|
|
10996
11162
|
me.close();
|
|
11163
|
+
|
|
11164
|
+
/**
|
|
11165
|
+
* @returns {void}
|
|
11166
|
+
*/
|
|
11167
|
+
function dispatchClose() {
|
|
11168
|
+
// Todo __forceClose: unblock any pending `upgradeneeded` or `deleteDatabase` calls
|
|
11169
|
+
var evt = createEvent('close');
|
|
11170
|
+
setTimeout(function () {
|
|
11171
|
+
me.dispatchEvent(evt);
|
|
11172
|
+
}, 0);
|
|
11173
|
+
}
|
|
11174
|
+
if (!transactions.length) {
|
|
11175
|
+
dispatchClose();
|
|
11176
|
+
return;
|
|
11177
|
+
}
|
|
10997
11178
|
var ct = 0;
|
|
10998
|
-
|
|
11179
|
+
transactions.forEach(function (trans) {
|
|
10999
11180
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11000
11181
|
trans.on__abort = function () {
|
|
11001
11182
|
ct++;
|
|
11002
|
-
if (ct
|
|
11003
|
-
|
|
11004
|
-
var evt = createEvent('close');
|
|
11005
|
-
setTimeout(function () {
|
|
11006
|
-
me.dispatchEvent(evt);
|
|
11007
|
-
}, 0);
|
|
11183
|
+
if (ct !== transactions.length) {
|
|
11184
|
+
return;
|
|
11008
11185
|
}
|
|
11186
|
+
dispatchClose();
|
|
11009
11187
|
};
|
|
11010
11188
|
trans.__abortTransaction(createDOMException('AbortError', 'The connection was force-closed: ' + (msg || '')));
|
|
11011
11189
|
});
|
|
11012
|
-
me.__transactions = [];
|
|
11013
11190
|
};
|
|
11014
11191
|
/* eslint-disable unicorn/no-top-level-side-effects -- Would be good */
|
|
11015
11192
|
defineOuterInterface(IDBDatabase.prototype, listeners);
|
|
@@ -11176,6 +11353,7 @@
|
|
|
11176
11353
|
return undefined;
|
|
11177
11354
|
}
|
|
11178
11355
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11356
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11179
11357
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11180
11358
|
new IDBVersionChangeEvent('versionchange', {
|
|
11181
11359
|
oldVersion: oldVersion,
|
|
@@ -11223,6 +11401,7 @@
|
|
|
11223
11401
|
}
|
|
11224
11402
|
};
|
|
11225
11403
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
11404
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11226
11405
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11227
11406
|
new IDBVersionChangeEvent('blocked', {
|
|
11228
11407
|
oldVersion: oldVersion,
|
|
@@ -11283,6 +11462,13 @@
|
|
|
11283
11462
|
|
|
11284
11463
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
11285
11464
|
var sysdb;
|
|
11465
|
+
// Tracks which `CFG.memoryDatabase` value `sysdb` was opened against, so a
|
|
11466
|
+
// later change to that config (e.g. toggling in-memory mode on and back
|
|
11467
|
+
// off) causes `sysdb` to be recreated for the new setting rather than
|
|
11468
|
+
// staying pinned, forever, to whatever it was the first time any database
|
|
11469
|
+
// was created in the process.
|
|
11470
|
+
/** @type {string|null|undefined} */
|
|
11471
|
+
var sysdbMemoryDatabaseSetting;
|
|
11286
11472
|
var nameCounter = 0;
|
|
11287
11473
|
|
|
11288
11474
|
/**
|
|
@@ -11364,12 +11550,20 @@
|
|
|
11364
11550
|
function cleanupDatabaseResources(__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError) {
|
|
11365
11551
|
var useMemoryDatabase = typeof CFG.memoryDatabase === 'string';
|
|
11366
11552
|
if (useMemoryDatabase) {
|
|
11553
|
+
/* c8 ignore start -- Defensive: only reachable if `websqlDBCache[name]`
|
|
11554
|
+
was initialized as an empty placeholder by `open()`'s connection-queue
|
|
11555
|
+
setup (`addRequestToConnectionQueue`, above `openDB`) but never
|
|
11556
|
+
populated with an actual instance -- e.g. `__openDatabase` throwing
|
|
11557
|
+
after a `dbVersions` row already existed for `name` from an earlier,
|
|
11558
|
+
successful `open()` -- or if `name` was never added to the cache at
|
|
11559
|
+
all. Not reachable via normal, non-tampered API usage. */
|
|
11367
11560
|
var latestSQLiteDBCached = Object.hasOwn(websqlDBCache, name) ? getLatestCachedWebSQLDB(name) : null;
|
|
11368
11561
|
if (!latestSQLiteDBCached) {
|
|
11369
11562
|
console.warn('Could not find a memory database instance to delete.');
|
|
11370
11563
|
databaseDeleted();
|
|
11371
11564
|
return;
|
|
11372
11565
|
}
|
|
11566
|
+
/* c8 ignore stop -- see comment above */
|
|
11373
11567
|
var _sqliteDB = latestSQLiteDBCached._db;
|
|
11374
11568
|
if (!_sqliteDB || !_sqliteDB.close) {
|
|
11375
11569
|
console.error('The `openDatabase` implementation does not have the expected `._db.close` method for closing the database');
|
|
@@ -11423,15 +11617,24 @@
|
|
|
11423
11617
|
tables.item(i).name)), [], function () {
|
|
11424
11618
|
deleteTables(i + 1);
|
|
11425
11619
|
}, function () {
|
|
11620
|
+
/* c8 ignore start -- Defensive: continues deleting the rest
|
|
11621
|
+
even if this specific store's table is already gone (e.g.
|
|
11622
|
+
duplicate `__sys__` rows for the same escaped table name, or
|
|
11623
|
+
external tampering); not reachable via normal API usage. */
|
|
11426
11624
|
deleteTables(i + 1);
|
|
11427
11625
|
return false;
|
|
11626
|
+
/* c8 ignore stop -- see comment above */
|
|
11428
11627
|
});
|
|
11429
11628
|
}
|
|
11430
11629
|
})(0);
|
|
11431
11630
|
}, function () {
|
|
11432
|
-
|
|
11631
|
+
/* c8 ignore start -- `__sys__` is always created by `openDB` before this
|
|
11632
|
+
database's `dbVersions` row (a prerequisite for reaching this code at
|
|
11633
|
+
all) is ever inserted; only reachable if the file was tampered with/
|
|
11634
|
+
removed externally afterward. */
|
|
11433
11635
|
databaseDeleted();
|
|
11434
11636
|
return false;
|
|
11637
|
+
/* c8 ignore stop -- see comment above */
|
|
11435
11638
|
});
|
|
11436
11639
|
});
|
|
11437
11640
|
}
|
|
@@ -11462,9 +11665,11 @@
|
|
|
11462
11665
|
}
|
|
11463
11666
|
failure(er);
|
|
11464
11667
|
}
|
|
11465
|
-
if (sysdb) {
|
|
11668
|
+
if (sysdb && sysdbMemoryDatabaseSetting === CFG.memoryDatabase) {
|
|
11466
11669
|
success();
|
|
11467
11670
|
} else {
|
|
11671
|
+
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Needed
|
|
11672
|
+
sysdbMemoryDatabaseSetting = CFG.memoryDatabase;
|
|
11468
11673
|
// eslint-disable-next-line unicorn/no-top-level-assignment-in-function -- Necessary?
|
|
11469
11674
|
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);
|
|
11470
11675
|
sysdb.transaction(function (systx) {
|
|
@@ -11644,6 +11849,17 @@
|
|
|
11644
11849
|
* @returns {void}
|
|
11645
11850
|
*/
|
|
11646
11851
|
var sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11852
|
+
/* c8 ignore start -- This initial definition is always
|
|
11853
|
+
superseded before ever being invoked: the `sysdb.transaction(...)`
|
|
11854
|
+
call below always reaches its `nonstandardTransCb` (4th arg)
|
|
11855
|
+
after this same SQL batch finishes running (since `dbCreateError`
|
|
11856
|
+
always reports errors as "handled" and this call site is never
|
|
11857
|
+
a `readTransaction`), which unconditionally reassigns
|
|
11858
|
+
`sysdbFinishedCb` to a version using the library's own
|
|
11859
|
+
`rollback`/`commit` -- well before any real invocation from
|
|
11860
|
+
`on__beforecomplete`/`on__preabort`/`on__abort` below (those only
|
|
11861
|
+
fire once the upgrade transaction itself later completes/aborts).
|
|
11862
|
+
Kept as a defensive fallback in case that invariant ever changes. */
|
|
11647
11863
|
if (err) {
|
|
11648
11864
|
/**
|
|
11649
11865
|
* @param {unknown} [errorToShow]
|
|
@@ -11692,6 +11908,7 @@
|
|
|
11692
11908
|
}
|
|
11693
11909
|
// In browser, should auto-commit
|
|
11694
11910
|
cb(); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11911
|
+
/* c8 ignore stop -- see comment above */
|
|
11695
11912
|
};
|
|
11696
11913
|
sysdb.transaction(function (systx) {
|
|
11697
11914
|
/**
|
|
@@ -11699,6 +11916,7 @@
|
|
|
11699
11916
|
*/
|
|
11700
11917
|
function versionSet() {
|
|
11701
11918
|
var e = /** @type {import('eventtargeter').EventWithProps & Event & IDBVersionChangeEvent} */
|
|
11919
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
11702
11920
|
// @ts-ignore It's ok; needed under some TS versions
|
|
11703
11921
|
new IDBVersionChangeEvent('upgradeneeded', {
|
|
11704
11922
|
oldVersion: oldVersion,
|
|
@@ -11824,9 +12042,17 @@
|
|
|
11824
12042
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11825
12043
|
req.transaction.on__complete = function () {
|
|
11826
12044
|
var pos = connection.__transactions.indexOf(req.transaction);
|
|
12045
|
+
// `req.transaction` (the versionchange transaction) is created
|
|
12046
|
+
// directly via `IDBTransaction.__createInstance` above, never
|
|
12047
|
+
// via `IDBDatabase.prototype.transaction()` (the only place
|
|
12048
|
+
// that pushes onto `connection.__transactions`), so `pos` is
|
|
12049
|
+
// always -1 here.
|
|
12050
|
+
/* c8 ignore start -- see comment above */
|
|
11827
12051
|
if (pos !== -1) {
|
|
11828
12052
|
connection.__transactions.splice(pos, 1);
|
|
11829
12053
|
}
|
|
12054
|
+
/* c8 ignore stop -- see comment above */
|
|
12055
|
+
|
|
11830
12056
|
if (/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */req.__result.__closePending) {
|
|
11831
12057
|
req.__transaction = null;
|
|
11832
12058
|
var err = createDOMException('AbortError', 'The connection has been closed.');
|
|
@@ -11862,9 +12088,16 @@
|
|
|
11862
12088
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [version, sqlSafeName], versionSet, dbCreateError);
|
|
11863
12089
|
}
|
|
11864
12090
|
}, dbCreateError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12091
|
+
// Defensive fallback, not reachable in practice: same reasoning
|
|
12092
|
+
// as `deleteDatabase`'s own `nonstandardTransCb` below
|
|
12093
|
+
// (`currentTask.readOnly` is always false here, and
|
|
12094
|
+
// `dbCreateError` always returns `false`, so `err` is never
|
|
12095
|
+
// truthy either).
|
|
12096
|
+
/* c8 ignore start -- see comment above */
|
|
11865
12097
|
if (currentTask.readOnly || err) {
|
|
11866
12098
|
return true;
|
|
11867
12099
|
}
|
|
12100
|
+
/* c8 ignore stop -- see comment above */
|
|
11868
12101
|
sysdbFinishedCb = function sysdbFinishedCb(systx, err, cb) {
|
|
11869
12102
|
if (err) {
|
|
11870
12103
|
rollback(err,
|
|
@@ -11879,7 +12112,17 @@
|
|
|
11879
12112
|
} else {
|
|
11880
12113
|
systx.executeSql('UPDATE dbVersions SET "version" = ? WHERE "name" = ?', [oldVersion, sqlSafeName]);
|
|
11881
12114
|
}
|
|
11882
|
-
},
|
|
12115
|
+
},
|
|
12116
|
+
// Deeply-nested defensive path: only reached if
|
|
12117
|
+
// the *revert* SQL (undoing the `dbVersions`
|
|
12118
|
+
// INSERT/UPDATE after the original version-
|
|
12119
|
+
// upgrade itself already failed) fails a
|
|
12120
|
+
// *second* time. Not feasibly triggerable
|
|
12121
|
+
// without fault-injecting the underlying SQL
|
|
12122
|
+
// driver on this specific, already-failing
|
|
12123
|
+
// revert statement.
|
|
12124
|
+
function (sqlErr) {
|
|
12125
|
+
/* c8 ignore next 2 -- see comment above */
|
|
11883
12126
|
isRevertingSysdb = false;
|
|
11884
12127
|
cb(sqlErr); // eslint-disable-line promise/no-callback-in-promise -- Convenient
|
|
11885
12128
|
}, function () {
|
|
@@ -11895,8 +12138,20 @@
|
|
|
11895
12138
|
});
|
|
11896
12139
|
return undefined;
|
|
11897
12140
|
}).catch(function (err) {
|
|
12141
|
+
/* c8 ignore start -- Purely defensive: nothing in
|
|
12142
|
+
`triggerAnyVersionChangeAndBlockedEvents`'s promise chain
|
|
12143
|
+
(or this `.then()` continuation above) ever rejects/throws
|
|
12144
|
+
under any reachable application-level condition -- all of
|
|
12145
|
+
its continuations resolve cleanly, and its `dispatchEvent`
|
|
12146
|
+
calls are deliberately fire-and-forget ("No need to catch
|
|
12147
|
+
errors"), running inside a `setTimeout` where a listener
|
|
12148
|
+
throwing becomes an uncaught exception in that macrotask
|
|
12149
|
+
rather than a promise rejection here. This exists solely
|
|
12150
|
+
to surface a truly-unexpected internal bug via the console
|
|
12151
|
+
before rethrowing, not to handle a real, testable error path. */
|
|
11898
12152
|
console.log('Error within `triggerAnyVersionChangeAndBlockedEvents`');
|
|
11899
12153
|
throw err;
|
|
12154
|
+
/* c8 ignore stop -- see comment above */
|
|
11900
12155
|
});
|
|
11901
12156
|
} else {
|
|
11902
12157
|
finishRequest();
|
|
@@ -11924,11 +12179,19 @@
|
|
|
11924
12179
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
11925
12180
|
db = websqlDBCache[name][version];
|
|
11926
12181
|
} else {
|
|
11927
|
-
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? CFG.memoryDatabase : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
12182
|
+
db = /** @type {DatabaseFull} */me.__openDatabase(useMemoryDatabase ? (/** @type {string} */CFG.memoryDatabase) : joinPath(CFG.databaseBasePath || '', escapedDatabaseName), '1', name, CFG.DEFAULT_DB_SIZE);
|
|
11928
12183
|
if (useDatabaseCache) {
|
|
12184
|
+
/* c8 ignore start -- Defensive: by the time `openDB` runs,
|
|
12185
|
+
`websqlDBCache[name]` has always already been created by
|
|
12186
|
+
`addRequestToConnectionQueue`'s own callback above (guarded
|
|
12187
|
+
by this same `useDatabaseCache` condition), which always
|
|
12188
|
+
runs first and unconditionally ensures the entry exists
|
|
12189
|
+
before ever calling `openDB`. Kept as a safety net in case
|
|
12190
|
+
that invariant ever changes. */
|
|
11929
12191
|
if (!Object.hasOwn(websqlDBCache, name)) {
|
|
11930
12192
|
websqlDBCache[name] = {};
|
|
11931
12193
|
}
|
|
12194
|
+
/* c8 ignore stop -- see comment above */
|
|
11932
12195
|
websqlDBCache[name][version] = db;
|
|
11933
12196
|
}
|
|
11934
12197
|
}
|
|
@@ -12079,6 +12342,7 @@
|
|
|
12079
12342
|
req.__result = undefined;
|
|
12080
12343
|
req.__done = true;
|
|
12081
12344
|
var e = /** @type {Event & IDBVersionChangeEvent} */
|
|
12345
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12082
12346
|
// @ts-ignore It's ok; needed under some TS versions
|
|
12083
12347
|
new IDBVersionChangeEvent('success', {
|
|
12084
12348
|
oldVersion: version,
|
|
@@ -12121,9 +12385,23 @@
|
|
|
12121
12385
|
cleanupDatabaseResources(me.__openDatabase, name, escapedDatabaseName, databaseDeleted, dbError);
|
|
12122
12386
|
}, dbError);
|
|
12123
12387
|
}, dbError, undefined, function (currentTask, err, done, rollback, commit) {
|
|
12388
|
+
/* c8 ignore start -- Defensive fallback, not reachable in
|
|
12389
|
+
practice: `currentTask.readOnly` is always `false` here
|
|
12390
|
+
(this callback is only ever attached to the writable
|
|
12391
|
+
`sysdb.transaction(...)` call above, never to a
|
|
12392
|
+
`sysdb.readTransaction(...)`), and `err` can only be
|
|
12393
|
+
truthy if the `DELETE FROM dbVersions` statement's own
|
|
12394
|
+
error callback (`dbError`) reports the failure back to
|
|
12395
|
+
`websql-configurable` as unhandled -- but `dbError`
|
|
12396
|
+
deliberately always `return`s `false`, which tells the
|
|
12397
|
+
library the error was already handled (and to keep
|
|
12398
|
+
`err` falsy here), precisely so this custom
|
|
12399
|
+
`sysdbFinishedCbDelete` rollback/commit path below is
|
|
12400
|
+
used instead of the library's own default rollback. */
|
|
12124
12401
|
if (currentTask.readOnly || err) {
|
|
12125
12402
|
return true;
|
|
12126
12403
|
}
|
|
12404
|
+
/* c8 ignore stop -- see comment above */
|
|
12127
12405
|
sysdbFinishedCbDelete = function sysdbFinishedCbDelete(err, cb) {
|
|
12128
12406
|
if (err) {
|
|
12129
12407
|
rollback(err, cb);
|
|
@@ -12249,10 +12527,9 @@
|
|
|
12249
12527
|
};
|
|
12250
12528
|
|
|
12251
12529
|
/**
|
|
12252
|
-
* @todo forceClose: Test
|
|
12253
12530
|
* This is provided to facilitate unit-testing of the
|
|
12254
12531
|
* closing of a database connection with a forced flag:
|
|
12255
|
-
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection
|
|
12532
|
+
* <https://w3c.github.io/IndexedDB/#steps-for-closing-a-database-connection>.
|
|
12256
12533
|
* @param {string} dbName
|
|
12257
12534
|
* @param {Integer} connIdx
|
|
12258
12535
|
* @param {string} msg
|
|
@@ -12353,6 +12630,7 @@
|
|
|
12353
12630
|
* @this {IDBRecordFull}
|
|
12354
12631
|
*/
|
|
12355
12632
|
function IDBRecord() {
|
|
12633
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12356
12634
|
// @ts-ignore Should be ok
|
|
12357
12635
|
this[Symbol.toStringTag] = 'IDBRecord';
|
|
12358
12636
|
this.__key = key;
|
|
@@ -12389,6 +12667,7 @@
|
|
|
12389
12667
|
if (!(this instanceof IDBRecordAlias)) {
|
|
12390
12668
|
throw new TypeError('Illegal invocation');
|
|
12391
12669
|
}
|
|
12670
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
12392
12671
|
// @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
|
|
12393
12672
|
return this['__' + prop];
|
|
12394
12673
|
});
|
|
@@ -12731,6 +13010,7 @@
|
|
|
12731
13010
|
success(undefined, undefined, undefined);
|
|
12732
13011
|
}
|
|
12733
13012
|
}, function (tx, err) {
|
|
13013
|
+
/* c8 ignore next -- Debug-only log; no test sets `CFG.DEBUG`. */
|
|
12734
13014
|
if (CFG.DEBUG) {
|
|
12735
13015
|
console.log('Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12736
13016
|
}
|
|
@@ -12914,7 +13194,16 @@
|
|
|
12914
13194
|
if (a.key > b.key) {
|
|
12915
13195
|
return me.direction === 'prev' ? -1 : 1;
|
|
12916
13196
|
}
|
|
13197
|
+
/* c8 ignore start -- Defensive: only reachable if two matches
|
|
13198
|
+
in the same batch shared both the same `matchingKey` and
|
|
13199
|
+
the same primary `key`, which would require the same
|
|
13200
|
+
record's multi-entry array to contain a duplicate value.
|
|
13201
|
+
`Key.js`'s array-to-key conversion already drops duplicate
|
|
13202
|
+
values when a multi-entry index entry is built, so this
|
|
13203
|
+
can never happen in practice; kept only to satisfy the
|
|
13204
|
+
`Array.prototype.sort` comparator contract. */
|
|
12917
13205
|
return 0;
|
|
13206
|
+
/* c8 ignore stop -- see comment above */
|
|
12918
13207
|
});
|
|
12919
13208
|
me.__prefetchedIndex = 0;
|
|
12920
13209
|
me.__prefetchedData = {
|
|
@@ -12933,13 +13222,19 @@
|
|
|
12933
13222
|
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
12934
13223
|
}
|
|
12935
13224
|
me.__decode(rows[0], success);
|
|
12936
|
-
},
|
|
13225
|
+
},
|
|
13226
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13227
|
+
execution error (e.g. I/O error, corruption) while querying for
|
|
13228
|
+
multi-entry cursor matches; not reliably reproducible without
|
|
13229
|
+
mocking the SQL layer. */
|
|
13230
|
+
function (tx, err) {
|
|
12937
13231
|
if (CFG.DEBUG) {
|
|
12938
13232
|
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
12939
13233
|
}
|
|
12940
13234
|
error(err);
|
|
12941
13235
|
return false;
|
|
12942
13236
|
});
|
|
13237
|
+
/* c8 ignore stop -- see comment above */
|
|
12943
13238
|
}
|
|
12944
13239
|
runQuery();
|
|
12945
13240
|
};
|
|
@@ -13048,6 +13343,7 @@
|
|
|
13048
13343
|
* @returns {void}
|
|
13049
13344
|
*/
|
|
13050
13345
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
13346
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13051
13347
|
// @ts-ignore Why is this not being found?; needed under some TS versions
|
|
13052
13348
|
this.__prefetchedData = null;
|
|
13053
13349
|
this.__multiEntryExhausted = false;
|
|
@@ -13072,7 +13368,7 @@
|
|
|
13072
13368
|
convertValueToKeyRethrowingAndIfInvalid(key);
|
|
13073
13369
|
var cmpResult = cmp(key, me.key);
|
|
13074
13370
|
if (cmpResult === 0 || me.direction.includes('next') && cmpResult === -1 || me.direction.includes('prev') && cmpResult === 1) {
|
|
13075
|
-
throw createDOMException('DataError', 'Cannot
|
|
13371
|
+
throw createDOMException('DataError', 'Cannot continue the cursor in an unexpected direction');
|
|
13076
13372
|
}
|
|
13077
13373
|
}
|
|
13078
13374
|
this.__continueFinish(key, undefined, advanceState);
|
|
@@ -13329,6 +13625,7 @@
|
|
|
13329
13625
|
// continuation logic in `__findBasic` to see this update's
|
|
13330
13626
|
// effect on ordering (see "Modify records during cursor
|
|
13331
13627
|
// iteration" in idbcursor_update_index.any.js).
|
|
13628
|
+
// eslint-disable-next-line jsdoc/ts-ban-ts-comment -- TS 6/7
|
|
13332
13629
|
// @ts-ignore -- API (not erring in TS 6)
|
|
13333
13630
|
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
13334
13631
|
}
|
|
@@ -13378,14 +13675,33 @@
|
|
|
13378
13675
|
// We don't invalidate the cache (as we don't access it anymore
|
|
13379
13676
|
// and it will set the index off)
|
|
13380
13677
|
success(undefined);
|
|
13678
|
+
/* c8 ignore start -- Defensive: `__find` (invoked just above) has
|
|
13679
|
+
already confirmed a row exists for this primary key within the
|
|
13680
|
+
same transaction queue, so `rowsAffected` should always be 1 in
|
|
13681
|
+
normal usage. This branch would only be reached if the underlying
|
|
13682
|
+
row were removed by another request queued in the same
|
|
13683
|
+
transaction between `__find`'s check and this DELETE actually
|
|
13684
|
+
running (e.g. deleting the same record directly via the object
|
|
13685
|
+
store while a cursor over it is mid-iteration); attempts to
|
|
13686
|
+
construct such a scenario instead trigger a transaction abort
|
|
13687
|
+
(`AbortError`) before this callback ever runs, since the default
|
|
13688
|
+
action of an unhandled request error is to abort the
|
|
13689
|
+
transaction. */
|
|
13381
13690
|
} else {
|
|
13382
13691
|
// @ts-expect-error Apparently ok
|
|
13383
13692
|
error('No rows with key found' + key);
|
|
13384
13693
|
}
|
|
13385
|
-
|
|
13694
|
+
/* c8 ignore stop -- see comment above */
|
|
13695
|
+
},
|
|
13696
|
+
/* c8 ignore start -- Defensive: guards against an unexpected SQLite
|
|
13697
|
+
execution error (e.g. I/O error, corruption) while deleting the
|
|
13698
|
+
current row; not reliably reproducible without mocking the SQL
|
|
13699
|
+
layer. */
|
|
13700
|
+
function (tx, data) {
|
|
13386
13701
|
error(data);
|
|
13387
13702
|
return false;
|
|
13388
13703
|
});
|
|
13704
|
+
/* c8 ignore stop -- see comment above */
|
|
13389
13705
|
}, error);
|
|
13390
13706
|
}, undefined, me);
|
|
13391
13707
|
};
|
|
@@ -13796,7 +14112,7 @@
|
|
|
13796
14112
|
setConfig(initialConfig);
|
|
13797
14113
|
}
|
|
13798
14114
|
var IDB = /** @type {ShimmedObject & {[key: string]: unknown}} */
|
|
13799
|
-
/** @type {unknown} */idb || globalThis
|
|
14115
|
+
/** @type {unknown} */idb || globalThis;
|
|
13800
14116
|
/**
|
|
13801
14117
|
* @param {string} name
|
|
13802
14118
|
* @param {unknown} value
|
|
@@ -13887,80 +14203,87 @@
|
|
|
13887
14203
|
});
|
|
13888
14204
|
}
|
|
13889
14205
|
var shimIDBFactory = IDBFactory;
|
|
13890
|
-
if (CFG.win.openDatabase
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
14206
|
+
if (CFG.win.openDatabase === undefined) {
|
|
14207
|
+
return;
|
|
14208
|
+
}
|
|
14209
|
+
shimIndexedDB.__openDatabase = CFG.win.openDatabase.bind(CFG.win); // We cache here in case the function is overwritten later as by the IndexedDB support promises tests
|
|
14210
|
+
// Polyfill ALL of IndexedDB, using WebSQL
|
|
14211
|
+
shim('indexedDB', shimIndexedDB, {
|
|
14212
|
+
enumerable: true,
|
|
14213
|
+
configurable: true,
|
|
14214
|
+
get: function get() {
|
|
14215
|
+
if (this !== IDB && !isNullish(this) && !this.shimNS) {
|
|
14216
|
+
// Latter is hack for test environment
|
|
14217
|
+
throw new TypeError('Illegal invocation');
|
|
13902
14218
|
}
|
|
13903
|
-
|
|
13904
|
-
/** @type {[string, unknown][]} */
|
|
13905
|
-
[['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) {
|
|
13906
|
-
var _ref4 = _slicedToArray(_ref3, 2),
|
|
13907
|
-
prop = _ref4[0],
|
|
13908
|
-
obj = _ref4[1];
|
|
13909
|
-
shim(prop, obj, {
|
|
13910
|
-
enumerable: false,
|
|
13911
|
-
configurable: true
|
|
13912
|
-
});
|
|
13913
|
-
});
|
|
13914
|
-
// For Node environments
|
|
13915
|
-
if (CFG.fs) {
|
|
13916
|
-
setFS(CFG.fs);
|
|
14219
|
+
return shimIndexedDB;
|
|
13917
14220
|
}
|
|
13918
|
-
|
|
13919
|
-
|
|
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
|
-
|
|
14221
|
+
});
|
|
14222
|
+
/** @type {[string, unknown][]} */
|
|
14223
|
+
[['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) {
|
|
14224
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
14225
|
+
prop = _ref4[0],
|
|
14226
|
+
obj = _ref4[1];
|
|
14227
|
+
shim(prop, obj, {
|
|
14228
|
+
enumerable: false,
|
|
14229
|
+
configurable: true
|
|
14230
|
+
});
|
|
14231
|
+
});
|
|
14232
|
+
// For Node environments
|
|
14233
|
+
if (CFG.fs) {
|
|
14234
|
+
setFS(CFG.fs);
|
|
14235
|
+
}
|
|
14236
|
+
if (CFG.fullIDLSupport) {
|
|
14237
|
+
// Slow per MDN so off by default! Though apparently needed for WebIDL: https://stackoverflow.com/questions/41927589/rationales-consequences-of-webidl-class-inheritance-requirements
|
|
14238
|
+
|
|
14239
|
+
Object.setPrototypeOf(IDB.IDBOpenDBRequest, IDB.IDBRequest);
|
|
14240
|
+
Object.setPrototypeOf(IDB.IDBCursorWithValue, IDB.IDBCursor);
|
|
14241
|
+
Object.setPrototypeOf(IDBDatabase, EventTarget);
|
|
14242
|
+
Object.setPrototypeOf(IDBRequest, EventTarget);
|
|
14243
|
+
Object.setPrototypeOf(IDBTransaction, EventTarget);
|
|
14244
|
+
Object.setPrototypeOf(IDBVersionChangeEvent, ShimEvent);
|
|
14245
|
+
// `ShimDOMException` is the real native `DOMException` when one
|
|
14246
|
+
// is available (see `DOMException.js`'s `useNativeDOMException`)
|
|
14247
|
+
// -- which, unlike the shim classes above, is a single,
|
|
14248
|
+
// process-wide singleton shared by reference across every
|
|
14249
|
+
// sandbox this library gets installed into (see
|
|
14250
|
+
// `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
|
|
14251
|
+
// already has the correct prototype chain out of the box
|
|
14252
|
+
// (`Object.getPrototypeOf(DOMException) === Function.prototype`,
|
|
14253
|
+
// not `Error`), so forcing it here isn't just unneeded but
|
|
14254
|
+
// actively wrong -- and, because it's shared, permanently
|
|
14255
|
+
// wrong for every later use of `DOMException` in the same
|
|
14256
|
+
// process (e.g. a later WPT test file's own idlharness-style
|
|
14257
|
+
// check that `DOMException` does *not* inherit from `Error`
|
|
14258
|
+
// on the class side), not just this one shim install.
|
|
14259
|
+
if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
|
|
14260
|
+
Object.setPrototypeOf(ShimDOMException, Error);
|
|
14261
|
+
Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
|
|
13945
14262
|
}
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
if (CFG.replaceNonIDBGlobals) {
|
|
13954
|
-
setNonIDBGlobals();
|
|
13955
|
-
}
|
|
14263
|
+
}
|
|
14264
|
+
if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
|
|
14265
|
+
if (CFG.addNonIDBGlobals) {
|
|
14266
|
+
// As `DOMStringList` exists per IDL (and Chrome) in the global
|
|
14267
|
+
// thread (but not in workers), we prefix the name to avoid
|
|
14268
|
+
// shadowing or conflicts
|
|
14269
|
+
setNonIDBGlobals('Shim');
|
|
13956
14270
|
}
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
return;
|
|
14271
|
+
if (CFG.replaceNonIDBGlobals) {
|
|
14272
|
+
setNonIDBGlobals();
|
|
13960
14273
|
}
|
|
13961
|
-
/* c8 ignore stop -- TS guard */
|
|
13962
|
-
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13963
14274
|
}
|
|
14275
|
+
/* c8 ignore start -- Defensive: `IDB.shimIndexedDB` was already
|
|
14276
|
+
confirmed truthy just before this function (`__useShim`) was
|
|
14277
|
+
defined and immediately invoked (see the `if ('shimIndexedDB'
|
|
14278
|
+
in IDB && IDB.shimIndexedDB)` guard above), and nothing in
|
|
14279
|
+
this function's body reassigns or deletes it. Only reachable
|
|
14280
|
+
if `IDB` is some unusual object (e.g. a Proxy) whose
|
|
14281
|
+
`shimIndexedDB` property value changes between reads. */
|
|
14282
|
+
if (!IDB.shimIndexedDB) {
|
|
14283
|
+
return;
|
|
14284
|
+
}
|
|
14285
|
+
/* c8 ignore stop -- see comment above */
|
|
14286
|
+
IDB.shimIndexedDB.__setConnectionQueueOrigin();
|
|
13964
14287
|
};
|
|
13965
14288
|
IDB.shimIndexedDB.__debug = /** @type {(val: boolean) => void} */function (val) {
|
|
13966
14289
|
CFG.DEBUG = val;
|