indexeddbshim 17.0.0 → 17.1.0
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 +62 -0
- package/badges/licenses-badge-dev.svg +1 -1
- package/badges/licenses-badge.svg +1 -1
- package/dist/CFG.d.ts +1 -0
- package/dist/CFG.d.ts.map +1 -1
- package/dist/IDBCursor.d.ts +9 -2
- package/dist/IDBCursor.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBIndex.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts +21 -0
- package/dist/IDBTransaction.d.ts.map +1 -1
- package/dist/Key.d.ts.map +1 -1
- package/dist/indexeddbshim-Key.js +25 -6
- 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 +1402 -818
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +467 -298
- package/dist/indexeddbshim-UnicodeIdentifiers.js.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js +4 -4
- package/dist/indexeddbshim-UnicodeIdentifiers.min.js.map +1 -1
- package/dist/indexeddbshim-node.cjs +1402 -818
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +467 -298
- package/dist/indexeddbshim-noninvasive.js.map +1 -1
- package/dist/indexeddbshim-noninvasive.min.js +4 -4
- package/dist/indexeddbshim-noninvasive.min.js.map +1 -1
- package/dist/indexeddbshim.js +471 -295
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +4 -4
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/node-UnicodeIdentifiers.d.ts.map +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/nodeSQLiteDatabase.d.ts +65 -0
- package/dist/nodeSQLiteDatabase.d.ts.map +1 -0
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/dist/util.d.ts +5 -0
- package/dist/util.d.ts.map +1 -1
- package/package.json +17 -13
- package/src/CFG.js +3 -0
- package/src/IDBCursor.js +136 -86
- package/src/IDBFactory.js +10 -6
- package/src/IDBIndex.js +1 -2
- package/src/IDBTransaction.js +32 -2
- package/src/Key.js +10 -2
- package/src/node-UnicodeIdentifiers.js +5 -1
- package/src/node.js +5 -1
- package/src/nodeSQLiteDatabase.js +174 -0
- package/src/nodeWebSQL.js +1 -3
- package/src/util.js +62 -3
package/dist/indexeddbshim.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! indexeddbshim - v17.
|
|
1
|
+
/*! indexeddbshim - v17.1.0 - 8/6/2026 */
|
|
2
2
|
|
|
3
3
|
(function (factory) {
|
|
4
4
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
function _createClass(e, r, t) {
|
|
61
|
-
return r && _defineProperties(e.prototype, r), Object.defineProperty(e, "prototype", {
|
|
61
|
+
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
|
|
62
62
|
writable: false
|
|
63
63
|
}), e;
|
|
64
64
|
}
|
|
@@ -301,6 +301,13 @@
|
|
|
301
301
|
function _slicedToArray(r, e) {
|
|
302
302
|
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
303
303
|
}
|
|
304
|
+
function _taggedTemplateLiteral(e, t) {
|
|
305
|
+
return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, {
|
|
306
|
+
raw: {
|
|
307
|
+
value: Object.freeze(t)
|
|
308
|
+
}
|
|
309
|
+
}));
|
|
310
|
+
}
|
|
304
311
|
function _toConsumableArray(r) {
|
|
305
312
|
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
|
|
306
313
|
}
|
|
@@ -1307,6 +1314,7 @@
|
|
|
1307
1314
|
* sqlBusyTimeout: number,
|
|
1308
1315
|
* sqlTrace: () => void,
|
|
1309
1316
|
* sqlProfile: () => void,
|
|
1317
|
+
* escapeNULForSQLiteStatements: boolean,
|
|
1310
1318
|
* createIndexes: boolean
|
|
1311
1319
|
* }} ConfigValues
|
|
1312
1320
|
*/
|
|
@@ -1461,8 +1469,8 @@
|
|
|
1461
1469
|
// Callback not used by default
|
|
1462
1470
|
'sqlProfile',
|
|
1463
1471
|
// Callback not used by default
|
|
1464
|
-
|
|
1465
|
-
'createIndexes'].forEach(function (prop) {
|
|
1472
|
+
// Defaults to true except in Node builds where we can preserve literal NUL with better-sqlite3
|
|
1473
|
+
'escapeNULForSQLiteStatements', 'createIndexes'].forEach(function (prop) {
|
|
1466
1474
|
/** @type {(val: any) => void} */
|
|
1467
1475
|
var validator;
|
|
1468
1476
|
if (Array.isArray(prop)) {
|
|
@@ -1543,7 +1551,8 @@
|
|
|
1543
1551
|
* @returns {string}
|
|
1544
1552
|
*/
|
|
1545
1553
|
function escapeSQLiteStatement(arg) {
|
|
1546
|
-
|
|
1554
|
+
var escaped = arg.replaceAll('^', '^^');
|
|
1555
|
+
return escapeUnmatchedSurrogates(CFG.escapeNULForSQLiteStatements === false ? escaped : escaped.replaceAll('\0', '^0'));
|
|
1547
1556
|
}
|
|
1548
1557
|
|
|
1549
1558
|
/**
|
|
@@ -1551,7 +1560,11 @@
|
|
|
1551
1560
|
* @returns {string}
|
|
1552
1561
|
*/
|
|
1553
1562
|
function unescapeSQLiteResponse(arg) {
|
|
1554
|
-
|
|
1563
|
+
var unescaped = unescapeUnmatchedSurrogates(arg);
|
|
1564
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
1565
|
+
return unescaped.replaceAll('^^', '^');
|
|
1566
|
+
}
|
|
1567
|
+
return unescaped.replaceAll(/(\^+)0/g, function (_, esc) {
|
|
1555
1568
|
return esc.length % 2 ? esc.slice(1) + '\0' : _;
|
|
1556
1569
|
}).replaceAll('^^', '^');
|
|
1557
1570
|
}
|
|
@@ -1952,6 +1965,56 @@
|
|
|
1952
1965
|
return v === null || v === undefined;
|
|
1953
1966
|
}
|
|
1954
1967
|
|
|
1968
|
+
/**
|
|
1969
|
+
* Cursor/request continuation chains can call each other synchronously
|
|
1970
|
+
* (e.g. walking a large prefetched buffer, or advancing many interleaved
|
|
1971
|
+
* cursors in one transaction) which, for large enough record counts, can
|
|
1972
|
+
* exceed the JS engine's call stack ("Maximum call stack size exceeded").
|
|
1973
|
+
*
|
|
1974
|
+
* This can't be fixed by deferring continuations to a microtask/macrotask:
|
|
1975
|
+
* the transaction machinery synchronously checks (once the current call
|
|
1976
|
+
* stack unwinds) whether there are any pending requests left in order to
|
|
1977
|
+
* decide it's safe to commit; deferring a continuation opens a real gap in
|
|
1978
|
+
* which that check runs first and the transaction completes prematurely,
|
|
1979
|
+
* with the deferred continuation then acting on an already-finished
|
|
1980
|
+
* transaction (a hang, since it can never resolve).
|
|
1981
|
+
*
|
|
1982
|
+
* Instead, this implements a true trampoline: the first call starts a
|
|
1983
|
+
* synchronous work queue and drains it in a flat loop; any call made while
|
|
1984
|
+
* already draining (i.e. a continuation triggering another continuation)
|
|
1985
|
+
* is simply appended to that same queue and returns immediately instead of
|
|
1986
|
+
* recursing. This keeps everything synchronous (so no completion-check
|
|
1987
|
+
* race is introduced) while preventing the call stack from growing with
|
|
1988
|
+
* each successive continuation.
|
|
1989
|
+
*/
|
|
1990
|
+
var continuationState = {
|
|
1991
|
+
/** @type {Array<() => void>|null} */
|
|
1992
|
+
queue: null
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
/**
|
|
1996
|
+
* @param {() => void} fn
|
|
1997
|
+
* @returns {void}
|
|
1998
|
+
*/
|
|
1999
|
+
function runContinuationSafely(fn) {
|
|
2000
|
+
if (continuationState.queue) {
|
|
2001
|
+
continuationState.queue.push(fn);
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
var queue = [fn];
|
|
2005
|
+
continuationState.queue = queue;
|
|
2006
|
+
try {
|
|
2007
|
+
while (queue.length) {
|
|
2008
|
+
var next = /** @type {() => void} */queue.shift();
|
|
2009
|
+
next();
|
|
2010
|
+
}
|
|
2011
|
+
} finally {
|
|
2012
|
+
// Ensure a thrown exception can't leave the queue permanently
|
|
2013
|
+
// stuck (which would silently swallow all future continuations).
|
|
2014
|
+
continuationState.queue = null;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
1955
2018
|
/**
|
|
1956
2019
|
* @typedef {Error} DebuggingError
|
|
1957
2020
|
*/
|
|
@@ -2633,16 +2696,15 @@
|
|
|
2633
2696
|
/* eslint-disable promise/prefer-await-to-callbacks -- Needed for API */
|
|
2634
2697
|
/* eslint-disable promise/catch-or-return, n/callback-return,
|
|
2635
2698
|
promise/always-return -- Not needed */
|
|
2636
|
-
/* eslint-disable unicorn/no-this-assignment -- Clarity */
|
|
2637
2699
|
// Since [immediate](https://github.com/calvinmetcalf/immediate) is
|
|
2638
2700
|
// not doing the trick for our WebSQL transactions (at least in Node),
|
|
2639
2701
|
// we are forced to make the promises run fully synchronously.
|
|
2640
2702
|
|
|
2641
|
-
|
|
2642
|
-
|
|
2703
|
+
/* eslint-disable jsdoc/reject-any-type -- Truly arbitrary */
|
|
2643
2704
|
/**
|
|
2644
2705
|
* @typedef {any} ArbitraryValue
|
|
2645
2706
|
*/
|
|
2707
|
+
/* eslint-enable jsdoc/reject-any-type -- Truly arbitrary */
|
|
2646
2708
|
|
|
2647
2709
|
/**
|
|
2648
2710
|
* @callback Resolve
|
|
@@ -2702,209 +2764,235 @@
|
|
|
2702
2764
|
REJECTED = 1;
|
|
2703
2765
|
|
|
2704
2766
|
/**
|
|
2705
|
-
*
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
* reject: (reason?: any) => void
|
|
2709
|
-
* ) => void} fn
|
|
2710
|
-
*/
|
|
2711
|
-
function SyncPromise(fn) {
|
|
2712
|
-
var that = this;
|
|
2713
|
-
// Value, this will be set to either a resolved value or rejected reason
|
|
2714
|
-
that.v = 0;
|
|
2715
|
-
// State of the promise
|
|
2716
|
-
that.s = PENDING;
|
|
2717
|
-
// Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
|
|
2718
|
-
/** @type {Callbacks|null} */
|
|
2719
|
-
that.c = [[], []];
|
|
2767
|
+
*
|
|
2768
|
+
*/
|
|
2769
|
+
var SyncPromise = /*#__PURE__*/function () {
|
|
2720
2770
|
/**
|
|
2721
|
-
*
|
|
2722
|
-
*
|
|
2723
|
-
*
|
|
2724
|
-
*
|
|
2771
|
+
* @param {(
|
|
2772
|
+
* resolve: (value: ArbitraryValue | PromiseLike<ArbitraryValue>) => void,
|
|
2773
|
+
* reject: (reason?: ArbitraryValue) => void
|
|
2774
|
+
* ) => void} fn
|
|
2725
2775
|
*/
|
|
2726
|
-
function
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2776
|
+
function SyncPromise(fn) {
|
|
2777
|
+
var _this = this;
|
|
2778
|
+
_classCallCheck(this, SyncPromise);
|
|
2779
|
+
// Value, this will be set to either a resolved value or rejected reason
|
|
2780
|
+
_defineProperty(this, "v", 0);
|
|
2781
|
+
// State of the promise
|
|
2782
|
+
this.s = PENDING;
|
|
2783
|
+
// Callbacks c[0] is fulfillment and c[1] contains rejection callbacks
|
|
2784
|
+
/** @type {Callbacks|null} */
|
|
2785
|
+
this.c = [[], []];
|
|
2786
|
+
/**
|
|
2787
|
+
*
|
|
2788
|
+
* @param {ArbitraryValue} val
|
|
2789
|
+
* @param {0|1} state
|
|
2790
|
+
* @returns {void}
|
|
2791
|
+
*/
|
|
2792
|
+
var transist = function transist(val, state) {
|
|
2793
|
+
_this.v = val;
|
|
2794
|
+
_this.s = state;
|
|
2743
2795
|
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2796
|
+
// console.log('state', state);
|
|
2797
|
+
/** @type {Callbacks} */
|
|
2798
|
+
_this.c[state].forEach(function (func) {
|
|
2799
|
+
func(val);
|
|
2800
|
+
});
|
|
2801
|
+
// Release memory, but if no handlers have been added, as we
|
|
2802
|
+
// assume that we will resolve/reject (truly) synchronously
|
|
2803
|
+
// and thus we avoid flagging checks about whether we've
|
|
2804
|
+
// already resolved/rejected.
|
|
2805
|
+
if (/** @type {Callbacks} */_this.c[state].length) {
|
|
2806
|
+
_this.c = null;
|
|
2807
|
+
}
|
|
2808
|
+
};
|
|
2752
2809
|
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2810
|
+
/** @type {Resolve} */
|
|
2811
|
+
var _resolve = function resolve(val) {
|
|
2812
|
+
if (!_this.c) ; else if (isPromise(val)) {
|
|
2813
|
+
addReject(val.then(_resolve), _reject);
|
|
2814
|
+
} else {
|
|
2815
|
+
transist(val, FULFILLED);
|
|
2816
|
+
}
|
|
2817
|
+
};
|
|
2818
|
+
|
|
2819
|
+
/** @type {Reject} */
|
|
2820
|
+
var _reject = function reject(reason) {
|
|
2821
|
+
if (!_this.c) ; else if (isPromise(reason)) {
|
|
2822
|
+
addReject(reason.then(_reject), _reject);
|
|
2823
|
+
} else {
|
|
2824
|
+
transist(reason, REJECTED);
|
|
2825
|
+
}
|
|
2826
|
+
};
|
|
2827
|
+
try {
|
|
2828
|
+
fn(_resolve, _reject);
|
|
2829
|
+
} catch (err) {
|
|
2830
|
+
_reject(err);
|
|
2759
2831
|
}
|
|
2760
2832
|
}
|
|
2761
|
-
try {
|
|
2762
|
-
fn(resolve, reject);
|
|
2763
|
-
} catch (err) {
|
|
2764
|
-
reject(err);
|
|
2765
|
-
}
|
|
2766
|
-
}
|
|
2767
2833
|
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2834
|
+
/* eslint-disable unicorn/no-thenable -- Promise API */
|
|
2835
|
+
/**
|
|
2836
|
+
* @param {((value: ArbitraryValue) => ArbitraryValue)|null|undefined} [cb]
|
|
2837
|
+
* @param {(reason: ArbitraryValue) => PromiseLike<never>} [errBack]
|
|
2838
|
+
* @returns {SyncPromise}
|
|
2839
|
+
*/
|
|
2840
|
+
return _createClass(SyncPromise, [{
|
|
2841
|
+
key: "then",
|
|
2842
|
+
value: function then(cb, errBack) {
|
|
2843
|
+
var _this2 = this;
|
|
2844
|
+
/* eslint-enable unicorn/no-thenable -- Promise API */
|
|
2845
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2846
|
+
function (resolve, reject) {
|
|
2847
|
+
var rej = typeof errBack === 'function' ? errBack : reject;
|
|
2780
2848
|
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2849
|
+
/** @type {Settle} */
|
|
2850
|
+
var settle = function settle() {
|
|
2851
|
+
try {
|
|
2852
|
+
resolve(cb ? cb(_this2.v) : _this2.v);
|
|
2853
|
+
} catch (e) {
|
|
2854
|
+
rej(e);
|
|
2855
|
+
}
|
|
2856
|
+
};
|
|
2857
|
+
if (_this2.s === FULFILLED) {
|
|
2858
|
+
settle();
|
|
2859
|
+
} else if (_this2.s === REJECTED) {
|
|
2860
|
+
rej(_this2.v);
|
|
2861
|
+
} else {
|
|
2862
|
+
/** @type {Callbacks} */_this2.c[FULFILLED].push(settle);
|
|
2863
|
+
/** @type {Callbacks} */
|
|
2864
|
+
_this2.c[REJECTED].push(rej);
|
|
2865
|
+
}
|
|
2866
|
+
});
|
|
2797
2867
|
}
|
|
2798
|
-
});
|
|
2799
|
-
};
|
|
2800
2868
|
|
|
2801
|
-
/**
|
|
2802
|
-
* @param {(reason: any) => PromiseLike<never>|null|undefined} cb
|
|
2803
|
-
* @returns {SyncPromise}
|
|
2804
|
-
*/
|
|
2805
|
-
SyncPromise.prototype.catch = function (cb) {
|
|
2806
|
-
var that = this;
|
|
2807
|
-
return new SyncPromise(/** @type {ResolveReject} */
|
|
2808
|
-
function (resolve, reject) {
|
|
2809
2869
|
/**
|
|
2810
|
-
* @
|
|
2870
|
+
* @param {(reason: ArbitraryValue) => PromiseLike<never>|null|undefined} cb
|
|
2871
|
+
* @returns {SyncPromise}
|
|
2811
2872
|
*/
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2873
|
+
}, {
|
|
2874
|
+
key: "catch",
|
|
2875
|
+
value: function _catch(cb) {
|
|
2876
|
+
var _this3 = this;
|
|
2877
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2878
|
+
function (resolve, reject) {
|
|
2879
|
+
/**
|
|
2880
|
+
* @returns {void}
|
|
2881
|
+
*/
|
|
2882
|
+
var settle = function settle() {
|
|
2883
|
+
try {
|
|
2884
|
+
resolve(cb(_this3.v));
|
|
2885
|
+
} catch (e) {
|
|
2886
|
+
reject(e);
|
|
2887
|
+
}
|
|
2888
|
+
};
|
|
2889
|
+
if (_this3.s === REJECTED) {
|
|
2890
|
+
settle();
|
|
2891
|
+
} else if (_this3.s === FULFILLED) {
|
|
2892
|
+
resolve(_this3.v);
|
|
2893
|
+
} else {
|
|
2894
|
+
/** @type {Callbacks} */_this3.c[REJECTED].push(settle);
|
|
2895
|
+
/** @type {Callbacks} */
|
|
2896
|
+
_this3.c[FULFILLED].push(resolve);
|
|
2897
|
+
}
|
|
2898
|
+
});
|
|
2827
2899
|
}
|
|
2828
|
-
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2900
|
+
}], [{
|
|
2901
|
+
key: "all",
|
|
2902
|
+
value:
|
|
2903
|
+
/**
|
|
2904
|
+
* @param {unknown[]|[]} promises
|
|
2905
|
+
* @returns {SyncPromise}
|
|
2906
|
+
*/
|
|
2907
|
+
function all(promises) {
|
|
2908
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2909
|
+
function (resolve, reject) {
|
|
2910
|
+
var l = promises.length;
|
|
2911
|
+
/** @type {ArbitraryValue[]} */
|
|
2912
|
+
var newPromises = [];
|
|
2913
|
+
if (!l) {
|
|
2914
|
+
resolve(newPromises);
|
|
2915
|
+
return;
|
|
2916
|
+
}
|
|
2917
|
+
promises.forEach(function (p, i) {
|
|
2918
|
+
if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
|
|
2919
|
+
addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
|
|
2920
|
+
function (res) {
|
|
2921
|
+
newPromises[i] = res;
|
|
2922
|
+
--l;
|
|
2923
|
+
if (!l) {
|
|
2924
|
+
resolve(newPromises);
|
|
2925
|
+
}
|
|
2926
|
+
}), reject);
|
|
2927
|
+
} else {
|
|
2928
|
+
newPromises[i] = p;
|
|
2929
|
+
--l;
|
|
2930
|
+
if (!l) {
|
|
2931
|
+
resolve(promises);
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
});
|
|
2935
|
+
});
|
|
2844
2936
|
}
|
|
2845
|
-
promises.forEach(function (p, i) {
|
|
2846
|
-
if (isPromise(/** @type {PromiseLike<any>} */p)) {
|
|
2847
|
-
addReject(/** @type {PromiseLike<any>} */p.then(/** @type {OnFulfilled} */
|
|
2848
|
-
function (res) {
|
|
2849
|
-
newPromises[i] = res;
|
|
2850
|
-
--l || resolve(newPromises);
|
|
2851
|
-
}), reject);
|
|
2852
|
-
} else {
|
|
2853
|
-
newPromises[i] = p;
|
|
2854
|
-
--l || resolve(promises);
|
|
2855
|
-
}
|
|
2856
|
-
});
|
|
2857
|
-
});
|
|
2858
|
-
};
|
|
2859
2937
|
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2938
|
+
/**
|
|
2939
|
+
* @param {unknown[]|[]} promises
|
|
2940
|
+
* @returns {SyncPromise}
|
|
2941
|
+
*/
|
|
2942
|
+
}, {
|
|
2943
|
+
key: "race",
|
|
2944
|
+
value: function race(promises) {
|
|
2945
|
+
var resolved = false;
|
|
2946
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2947
|
+
function (resolve, reject) {
|
|
2948
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
2949
|
+
// eslint-disable-next-line unicorn/no-unused-array-method-return -- Shortcuts
|
|
2950
|
+
promises.some(function (p) {
|
|
2951
|
+
if (isPromise(/** @type {PromiseLike<ArbitraryValue>} */p)) {
|
|
2952
|
+
addReject(/** @type {PromiseLike<ArbitraryValue>} */p.then(/** @type {OnFulfilled} */
|
|
2953
|
+
function (res) {
|
|
2954
|
+
if (resolved) {
|
|
2955
|
+
return;
|
|
2956
|
+
}
|
|
2957
|
+
resolve(res);
|
|
2958
|
+
resolved = true;
|
|
2959
|
+
}), reject);
|
|
2960
|
+
return false;
|
|
2874
2961
|
}
|
|
2875
|
-
resolve(
|
|
2962
|
+
resolve(p);
|
|
2876
2963
|
resolved = true;
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
}
|
|
2880
|
-
|
|
2881
|
-
resolved = true;
|
|
2882
|
-
return true;
|
|
2883
|
-
});
|
|
2884
|
-
});
|
|
2885
|
-
};
|
|
2964
|
+
return true;
|
|
2965
|
+
});
|
|
2966
|
+
});
|
|
2967
|
+
}
|
|
2886
2968
|
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2969
|
+
/**
|
|
2970
|
+
* @param {ArbitraryValue} val
|
|
2971
|
+
* @returns {SyncPromise}
|
|
2972
|
+
*/
|
|
2973
|
+
}, {
|
|
2974
|
+
key: "resolve",
|
|
2975
|
+
value: function resolve(val) {
|
|
2976
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2977
|
+
function (resolve) {
|
|
2978
|
+
resolve(val);
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2897
2981
|
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2982
|
+
/**
|
|
2983
|
+
* @param {ArbitraryValue} val
|
|
2984
|
+
* @returns {SyncPromise}
|
|
2985
|
+
*/
|
|
2986
|
+
}, {
|
|
2987
|
+
key: "reject",
|
|
2988
|
+
value: function reject(val) {
|
|
2989
|
+
return new SyncPromise(/** @type {ResolveReject} */
|
|
2990
|
+
function (resolve, reject) {
|
|
2991
|
+
reject(val);
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
}]);
|
|
2995
|
+
}();
|
|
2908
2996
|
|
|
2909
2997
|
/**
|
|
2910
2998
|
* Compares two keys.
|
|
@@ -2941,6 +3029,8 @@
|
|
|
2941
3029
|
return result;
|
|
2942
3030
|
}
|
|
2943
3031
|
|
|
3032
|
+
var _templateObject, _templateObject2;
|
|
3033
|
+
|
|
2944
3034
|
/**
|
|
2945
3035
|
* @typedef {NodeJS.TypedArray|DataView} ArrayBufferView
|
|
2946
3036
|
*/
|
|
@@ -3216,14 +3306,22 @@
|
|
|
3216
3306
|
_iterator.f();
|
|
3217
3307
|
}
|
|
3218
3308
|
encoded.push(keyTypeToEncodedChar.invalid + '-'); // append an extra item, so empty arrays sort correctly
|
|
3219
|
-
|
|
3309
|
+
var encodedKey = JSON.stringify(encoded);
|
|
3310
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
3311
|
+
encodedKey = encodedKey.replaceAll(String.raw(_templateObject || (_templateObject = _taggedTemplateLiteral(["\0"], ["\\u0000"]))), '\0');
|
|
3312
|
+
}
|
|
3313
|
+
return keyTypeToEncodedChar.array + '-' + encodedKey;
|
|
3220
3314
|
},
|
|
3221
3315
|
/**
|
|
3222
3316
|
* @param {string} key
|
|
3223
3317
|
* @returns {ValueTypeArray}
|
|
3224
3318
|
*/
|
|
3225
3319
|
decode: function decode(key) {
|
|
3226
|
-
var
|
|
3320
|
+
var decodedKey = key.slice(2);
|
|
3321
|
+
if (CFG.escapeNULForSQLiteStatements === false) {
|
|
3322
|
+
decodedKey = decodedKey.replaceAll('\0', String.raw(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\0"], ["\\u0000"]))));
|
|
3323
|
+
}
|
|
3324
|
+
var decoded = JSON.parse(decodedKey);
|
|
3227
3325
|
decoded.pop(); // remove the extra item
|
|
3228
3326
|
for (var i = 0; i < decoded.length; i++) {
|
|
3229
3327
|
var item = decoded[i];
|
|
@@ -4687,6 +4785,7 @@
|
|
|
4687
4785
|
* },
|
|
4688
4786
|
* __requestsFinished: boolean,
|
|
4689
4787
|
* __transFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
4788
|
+
* __callTransFinishedCb: (err: boolean, cb: ((bool?: boolean) => void)) => void,
|
|
4690
4789
|
* __transactionEndCallback: () => void,
|
|
4691
4790
|
* __transactionFinished: boolean,
|
|
4692
4791
|
* __completed: boolean,
|
|
@@ -4796,6 +4895,35 @@
|
|
|
4796
4895
|
IDBTransaction.prototype.__transFinishedCb = function (err, cb) {
|
|
4797
4896
|
cb(Boolean(err));
|
|
4798
4897
|
};
|
|
4898
|
+
|
|
4899
|
+
/**
|
|
4900
|
+
* In Node, the real (SQL-commit-capable) `__transFinishedCb` is only
|
|
4901
|
+
* installed once the underlying WebSQL driver's own SQL-queue-idle check
|
|
4902
|
+
* has fired at least once for this transaction (asynchronously, via the
|
|
4903
|
+
* `nonstandardTransCb` passed to `db.transaction`/`.readTransaction`).
|
|
4904
|
+
* Since our own request processing can now finish synchronously (e.g., a
|
|
4905
|
+
* trivial upgrade using a synchronous SQL driver), it is possible to reach
|
|
4906
|
+
* transaction completion here before that has happened, in which case
|
|
4907
|
+
* `__transFinishedCb` is still the non-committing default above. Calling
|
|
4908
|
+
* that default directly would silently skip the actual SQL commit and
|
|
4909
|
+
* leave the underlying WebSQL transaction "running" forever, hanging any
|
|
4910
|
+
* later transaction on that same database connection. So, if the real
|
|
4911
|
+
* callback isn't installed yet, defer and retry until it is.
|
|
4912
|
+
* @this {IDBTransactionFull}
|
|
4913
|
+
* @param {boolean} err
|
|
4914
|
+
* @param {(bool?: boolean) => void} cb
|
|
4915
|
+
* @returns {void}
|
|
4916
|
+
*/
|
|
4917
|
+
IDBTransaction.prototype.__callTransFinishedCb = function (err, cb) {
|
|
4918
|
+
var me = this;
|
|
4919
|
+
if (me.__transFinishedCb === IDBTransaction.prototype.__transFinishedCb) {
|
|
4920
|
+
setTimeout(function () {
|
|
4921
|
+
me.__callTransFinishedCb(err, cb);
|
|
4922
|
+
}, 0);
|
|
4923
|
+
return;
|
|
4924
|
+
}
|
|
4925
|
+
me.__transFinishedCb(err, cb);
|
|
4926
|
+
};
|
|
4799
4927
|
/**
|
|
4800
4928
|
* @this {IDBTransactionFull}
|
|
4801
4929
|
* @returns {void}
|
|
@@ -4855,7 +4983,7 @@
|
|
|
4855
4983
|
me.__abortTransaction(createDOMException('AbortError', 'A request was aborted (in user handler after success).'));
|
|
4856
4984
|
return;
|
|
4857
4985
|
}
|
|
4858
|
-
executeNextRequest
|
|
4986
|
+
runContinuationSafely(executeNextRequest);
|
|
4859
4987
|
}
|
|
4860
4988
|
|
|
4861
4989
|
/**
|
|
@@ -4930,7 +5058,9 @@
|
|
|
4930
5058
|
try {
|
|
4931
5059
|
q = me.__requests[i];
|
|
4932
5060
|
if (!q.req) {
|
|
4933
|
-
q.op(tx, q.args,
|
|
5061
|
+
q.op(tx, q.args, function () {
|
|
5062
|
+
return runContinuationSafely(executeNextRequest);
|
|
5063
|
+
}, error);
|
|
4934
5064
|
return;
|
|
4935
5065
|
}
|
|
4936
5066
|
if (q.req.__done) {
|
|
@@ -7626,7 +7756,7 @@
|
|
|
7626
7756
|
reject(err);
|
|
7627
7757
|
});
|
|
7628
7758
|
}));
|
|
7629
|
-
SyncPromise.all(indexCreations).then(finish
|
|
7759
|
+
SyncPromise.all(indexCreations).then(finish).catch(/** @type {(reason: any) => PromiseLike<never>} */
|
|
7630
7760
|
error).catch(function (err) {
|
|
7631
7761
|
console.log('Index rename error');
|
|
7632
7762
|
throw err;
|
|
@@ -10010,7 +10140,7 @@
|
|
|
10010
10140
|
/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
|
|
10011
10141
|
req.__result.__versionTransaction = null;
|
|
10012
10142
|
sysdbFinishedCb(systx, false, function () {
|
|
10013
|
-
req.transaction.
|
|
10143
|
+
req.transaction.__callTransFinishedCb(false, function () {
|
|
10014
10144
|
ev.complete();
|
|
10015
10145
|
req.__transaction = null;
|
|
10016
10146
|
});
|
|
@@ -10121,6 +10251,13 @@
|
|
|
10121
10251
|
function openDB(oldVersion) {
|
|
10122
10252
|
/** @type {DatabaseFull} */
|
|
10123
10253
|
var db;
|
|
10254
|
+
if (version === undefined) {
|
|
10255
|
+
// Resolve before use as a cache key below, or a `open(name)` call
|
|
10256
|
+
// (no explicit version) would cache/look up under `undefined`
|
|
10257
|
+
// instead of the actual version, causing a second, separate
|
|
10258
|
+
// connection to be opened for the same database on reopen.
|
|
10259
|
+
version = oldVersion || 1;
|
|
10260
|
+
}
|
|
10124
10261
|
if ((useMemoryDatabase || useDatabaseCache) && Object.hasOwn(websqlDBCache, name) && Object.hasOwn(websqlDBCache[name], version)) {
|
|
10125
10262
|
db = websqlDBCache[name][version];
|
|
10126
10263
|
} else {
|
|
@@ -10132,9 +10269,6 @@
|
|
|
10132
10269
|
websqlDBCache[name][version] = db;
|
|
10133
10270
|
}
|
|
10134
10271
|
}
|
|
10135
|
-
if (version === undefined) {
|
|
10136
|
-
version = oldVersion || 1;
|
|
10137
|
-
}
|
|
10138
10272
|
if (oldVersion > version) {
|
|
10139
10273
|
var err = createDOMException('VersionError', 'An attempt was made to open a database using a lower version than the existing version.', version);
|
|
10140
10274
|
if (useDatabaseCache) {
|
|
@@ -10302,7 +10436,6 @@
|
|
|
10302
10436
|
version = _data$rows$item.version;
|
|
10303
10437
|
var openConnections = me.__connections[name] || [];
|
|
10304
10438
|
triggerAnyVersionChangeAndBlockedEvents(openConnections, req, version, null).then(function () {
|
|
10305
|
-
// eslint-disable-line promise/catch-or-return -- Sync promise
|
|
10306
10439
|
// Since we need two databases which can't be in a single transaction, we
|
|
10307
10440
|
// do this deleting from `dbVersions` first since the `__sys__` deleting
|
|
10308
10441
|
// only impacts file memory whereas this one is critical for avoiding it
|
|
@@ -10331,7 +10464,7 @@
|
|
|
10331
10464
|
});
|
|
10332
10465
|
return undefined;
|
|
10333
10466
|
// @ts-expect-error It's ok
|
|
10334
|
-
}
|
|
10467
|
+
}).catch(dbError);
|
|
10335
10468
|
return undefined;
|
|
10336
10469
|
}, dbError);
|
|
10337
10470
|
});
|
|
@@ -10513,6 +10646,9 @@
|
|
|
10513
10646
|
* __unique: boolean,
|
|
10514
10647
|
* __sqlDirection: "DESC"|"ASC",
|
|
10515
10648
|
* __matchedKeys: {[key: string]: true},
|
|
10649
|
+
* __continuationKey: import('./Key.js').Key|undefined,
|
|
10650
|
+
* __continuationPrimaryKey: import('./Key.js').Key|undefined,
|
|
10651
|
+
* __multiEntryExhausted: boolean,
|
|
10516
10652
|
* __invalidateCache: () => void
|
|
10517
10653
|
* }} IDBCursorFull
|
|
10518
10654
|
*/
|
|
@@ -10586,6 +10722,9 @@
|
|
|
10586
10722
|
this.__valueDecoder = this.__keyOnly ? Key : Sca;
|
|
10587
10723
|
this.__count = count;
|
|
10588
10724
|
this.__prefetchedIndex = -1;
|
|
10725
|
+
this.__continuationKey = undefined;
|
|
10726
|
+
this.__continuationPrimaryKey = undefined;
|
|
10727
|
+
this.__multiEntryExhausted = false;
|
|
10589
10728
|
this.__multiEntryIndex = this.__indexSource ? 'multiEntry' in source && source.multiEntry : false;
|
|
10590
10729
|
this.__unique = this.direction.includes('unique');
|
|
10591
10730
|
this.__sqlDirection = ['prev', 'prevunique'].includes(this.direction) ? 'DESC' : 'ASC';
|
|
@@ -10749,73 +10888,97 @@
|
|
|
10749
10888
|
* @param {SQLTransaction} tx
|
|
10750
10889
|
* @param {KeySuccess} success
|
|
10751
10890
|
* @param {FindError} error
|
|
10752
|
-
* @param {Integer
|
|
10891
|
+
* @param {Integer} [recordsToLoad]
|
|
10753
10892
|
* @this {IDBCursorFull}
|
|
10754
10893
|
* @returns {void}
|
|
10755
10894
|
*/
|
|
10756
|
-
IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error
|
|
10895
|
+
IDBCursor.prototype.__findMultiEntry = function (key, primaryKey, tx, success, error) {
|
|
10896
|
+
var recordsToLoad = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
|
|
10757
10897
|
var me = this;
|
|
10758
|
-
if (me.
|
|
10898
|
+
if (me.__multiEntryExhausted) {
|
|
10759
10899
|
if (CFG.DEBUG) {
|
|
10760
|
-
console.log('Reached end of multiEntry cursor');
|
|
10900
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (already exhausted)');
|
|
10761
10901
|
}
|
|
10762
10902
|
success(undefined, undefined, undefined);
|
|
10763
10903
|
return;
|
|
10764
10904
|
}
|
|
10765
10905
|
var quotedKeyColumnName = sqlQuote(me.__keyColumnName);
|
|
10766
|
-
var
|
|
10767
|
-
/** @type {string[]} */
|
|
10768
|
-
var sqlValues = [];
|
|
10769
|
-
sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
|
|
10770
|
-
if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
|
|
10771
|
-
if (me.__range.upper.indexOf(me.__range.lower) === 0) {
|
|
10772
|
-
sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
|
|
10773
|
-
sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
|
|
10774
|
-
}
|
|
10775
|
-
}
|
|
10906
|
+
var quotedKey = sqlQuote('key');
|
|
10776
10907
|
|
|
10777
10908
|
// Determine the ORDER BY direction based on the cursor.
|
|
10778
10909
|
var direction = me.__sqlDirection;
|
|
10779
10910
|
var op = direction === 'ASC' ? '>' : '<';
|
|
10780
|
-
var quotedKey = sqlQuote('key');
|
|
10781
|
-
if (primaryKey !== undefined) {
|
|
10782
|
-
sql.push('AND', quotedKey, op + '= ?');
|
|
10783
|
-
// Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
|
|
10784
|
-
sqlValues.push(/** @type {string} */_encode(primaryKey));
|
|
10785
|
-
}
|
|
10786
|
-
if (key !== undefined) {
|
|
10787
|
-
sql.push('AND', quotedKeyColumnName, op + '= ?');
|
|
10788
|
-
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
10789
|
-
sqlValues.push(/** @type {string} */_encode(key));
|
|
10790
|
-
} else if (me.__key !== undefined) {
|
|
10791
|
-
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
10792
|
-
// Key.convertValueToKey(me.__key); // Already checked when entered
|
|
10793
|
-
sqlValues.push(/** @type {string} */_encode(me.__key));
|
|
10794
|
-
}
|
|
10795
|
-
if (!me.__count) {
|
|
10796
|
-
// 1. Sort by key
|
|
10797
|
-
sql.push('ORDER BY', quotedKeyColumnName, direction);
|
|
10798
10911
|
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10912
|
+
/**
|
|
10913
|
+
* Runs (and, if a batch of underlying rows produces no matching
|
|
10914
|
+
* multi-entry values, repeatedly re-runs) the query for the next batch
|
|
10915
|
+
* of underlying rows, advancing `me.__continuationKey`/
|
|
10916
|
+
* `me.__continuationPrimaryKey` (tracking the last *physical* row
|
|
10917
|
+
* scanned) each time, until either some matches are found or the
|
|
10918
|
+
* underlying table is exhausted.
|
|
10919
|
+
* @returns {void}
|
|
10920
|
+
*/
|
|
10921
|
+
function runQuery() {
|
|
10922
|
+
var sql = ['SELECT * FROM', escapeStoreNameForSQL(me.__store.__currentName)];
|
|
10923
|
+
/** @type {string[]} */
|
|
10924
|
+
var sqlValues = [];
|
|
10925
|
+
sql.push('WHERE', quotedKeyColumnName, 'NOT NULL');
|
|
10926
|
+
if (me.__range && me.__range.lower !== undefined && Array.isArray(me.__range.upper)) {
|
|
10927
|
+
if (me.__range.upper.indexOf(me.__range.lower) === 0) {
|
|
10928
|
+
sql.push('AND', quotedKeyColumnName, "LIKE ? ESCAPE '^'");
|
|
10929
|
+
sqlValues.push('%' + sqlLIKEEscape(/** @type {string} */me.__range.__lowerCached.slice(0, -1)) + '%');
|
|
10930
|
+
}
|
|
10931
|
+
}
|
|
10932
|
+
if (primaryKey !== undefined) {
|
|
10933
|
+
sql.push('AND', quotedKey, op + '= ?');
|
|
10934
|
+
// Key.convertValueToKey(primaryKey); // Already checked by `continuePrimaryKey`
|
|
10935
|
+
sqlValues.push(/** @type {string} */_encode(primaryKey));
|
|
10803
10936
|
}
|
|
10804
|
-
|
|
10805
|
-
|
|
10806
|
-
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
|
|
10937
|
+
if (key !== undefined) {
|
|
10938
|
+
sql.push('AND', quotedKeyColumnName, op + '= ?');
|
|
10939
|
+
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
10940
|
+
sqlValues.push(/** @type {string} */_encode(key));
|
|
10941
|
+
} else if (me.__continuationKey !== undefined) {
|
|
10942
|
+
// Resume from the last underlying (physical) row we scanned, not
|
|
10943
|
+
// from the last *matching* multi-entry value (which lives in a
|
|
10944
|
+
// different key-space than the raw index column and cannot be
|
|
10945
|
+
// reliably compared against it, e.g. for array index keys).
|
|
10946
|
+
sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
|
|
10947
|
+
var encodedContinuationKey = /** @type {string} */
|
|
10948
|
+
_encode(me.__continuationKey, true);
|
|
10949
|
+
sqlValues.push(encodedContinuationKey, encodedContinuationKey, /** @type {string} */_encode(me.__continuationPrimaryKey));
|
|
10950
|
+
}
|
|
10951
|
+
if (!me.__count) {
|
|
10952
|
+
// 1. Sort by key
|
|
10953
|
+
sql.push('ORDER BY', quotedKeyColumnName, direction);
|
|
10954
|
+
|
|
10955
|
+
// 2. Sort by primaryKey (if defined and not unique)
|
|
10956
|
+
if (!me.__unique && me.__keyColumnName !== 'key') {
|
|
10957
|
+
// Avoid adding 'key' twice
|
|
10958
|
+
sql.push(',', sqlQuote('key'), direction);
|
|
10959
|
+
}
|
|
10960
|
+
|
|
10961
|
+
// 3. Sort by position (if defined)
|
|
10962
|
+
|
|
10963
|
+
if (!me.__unique && me.__indexSource) {
|
|
10964
|
+
// 4. Sort by object store position (if defined and not unique)
|
|
10965
|
+
sql.push(',', sqlQuote(me.__valueColumnName), direction);
|
|
10966
|
+
}
|
|
10967
|
+
sql.push('LIMIT', String(recordsToLoad));
|
|
10968
|
+
}
|
|
10969
|
+
var sqlStr = sql.join(' ');
|
|
10970
|
+
if (CFG.DEBUG) {
|
|
10971
|
+
console.log('[multiEntry] query', sqlStr, sqlValues);
|
|
10810
10972
|
}
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10973
|
+
tx.executeSql(sqlStr, sqlValues, function (tx, data) {
|
|
10974
|
+
if (data.rows.length === 0) {
|
|
10975
|
+
me.__multiEntryExhausted = true;
|
|
10976
|
+
if (CFG.DEBUG) {
|
|
10977
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (no more rows)');
|
|
10978
|
+
}
|
|
10979
|
+
success(undefined, undefined, undefined);
|
|
10980
|
+
return;
|
|
10981
|
+
}
|
|
10819
10982
|
if (me.__count) {
|
|
10820
10983
|
// Avoid caching and other processing below
|
|
10821
10984
|
var ct = 0;
|
|
@@ -10828,6 +10991,16 @@
|
|
|
10828
10991
|
success(undefined, ct, undefined);
|
|
10829
10992
|
return;
|
|
10830
10993
|
}
|
|
10994
|
+
|
|
10995
|
+
// Track how far we've physically scanned, regardless of whether
|
|
10996
|
+
// this batch produced any matches, so the next batch (if any)
|
|
10997
|
+
// resumes after this one instead of re-scanning or stopping early.
|
|
10998
|
+
var lastRawRow = data.rows.item(data.rows.length - 1);
|
|
10999
|
+
me.__continuationKey = _decode(lastRawRow[me.__keyColumnName], true);
|
|
11000
|
+
me.__continuationPrimaryKey = _decode(lastRawRow.key);
|
|
11001
|
+
if (data.rows.length < recordsToLoad) {
|
|
11002
|
+
me.__multiEntryExhausted = true;
|
|
11003
|
+
}
|
|
10831
11004
|
var rows = [];
|
|
10832
11005
|
for (var _i = 0; _i < data.rows.length; _i++) {
|
|
10833
11006
|
var _rowItem = data.rows.item(_i);
|
|
@@ -10854,6 +11027,20 @@
|
|
|
10854
11027
|
_iterator.f();
|
|
10855
11028
|
}
|
|
10856
11029
|
}
|
|
11030
|
+
if (rows.length === 0) {
|
|
11031
|
+
if (me.__multiEntryExhausted) {
|
|
11032
|
+
if (CFG.DEBUG) {
|
|
11033
|
+
console.log('[multiEntry] Reached end of multiEntry cursor (last batch had no matches)');
|
|
11034
|
+
}
|
|
11035
|
+
success(undefined, undefined, undefined);
|
|
11036
|
+
return;
|
|
11037
|
+
}
|
|
11038
|
+
if (CFG.DEBUG) {
|
|
11039
|
+
console.log('[multiEntry] batch had no matches; fetching next batch');
|
|
11040
|
+
}
|
|
11041
|
+
runQuery();
|
|
11042
|
+
return;
|
|
11043
|
+
}
|
|
10857
11044
|
var reverse = me.direction.indexOf('prev') === 0;
|
|
10858
11045
|
rows.sort(function (a, b) {
|
|
10859
11046
|
if (a.matchingKey.replaceAll(leftBracketRegex, 'z') < b.matchingKey.replaceAll(leftBracketRegex, 'z')) {
|
|
@@ -10870,47 +11057,31 @@
|
|
|
10870
11057
|
}
|
|
10871
11058
|
return 0;
|
|
10872
11059
|
});
|
|
10873
|
-
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
10880
|
-
|
|
10881
|
-
|
|
10882
|
-
|
|
10883
|
-
return this.data[index];
|
|
10884
|
-
}
|
|
10885
|
-
};
|
|
10886
|
-
if (CFG.DEBUG) {
|
|
10887
|
-
console.log('Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
10888
|
-
}
|
|
10889
|
-
me.__decode(rows[0], success);
|
|
10890
|
-
} else if (rows.length === 1) {
|
|
10891
|
-
if (CFG.DEBUG) {
|
|
10892
|
-
console.log('Reached end of multiEntry cursor');
|
|
10893
|
-
}
|
|
10894
|
-
me.__decode(rows[0], success);
|
|
10895
|
-
} else {
|
|
10896
|
-
if (CFG.DEBUG) {
|
|
10897
|
-
console.log('Reached end of multiEntry cursor');
|
|
11060
|
+
me.__prefetchedIndex = 0;
|
|
11061
|
+
me.__prefetchedData = {
|
|
11062
|
+
data: rows,
|
|
11063
|
+
length: rows.length,
|
|
11064
|
+
/**
|
|
11065
|
+
* @param {Integer} index
|
|
11066
|
+
* @returns {RowItemNonNull}
|
|
11067
|
+
*/
|
|
11068
|
+
item: function item(index) {
|
|
11069
|
+
return this.data[index];
|
|
10898
11070
|
}
|
|
10899
|
-
|
|
11071
|
+
};
|
|
11072
|
+
if (CFG.DEBUG) {
|
|
11073
|
+
console.log('[multiEntry] Preloaded ' + me.__prefetchedData.length + ' records for multiEntry cursor');
|
|
10900
11074
|
}
|
|
10901
|
-
|
|
11075
|
+
me.__decode(rows[0], success);
|
|
11076
|
+
}, function (tx, err) {
|
|
10902
11077
|
if (CFG.DEBUG) {
|
|
10903
|
-
console.log('
|
|
11078
|
+
console.log('[multiEntry] Could not execute Cursor.continue', sqlStr, sqlValues);
|
|
10904
11079
|
}
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
}
|
|
10911
|
-
error(err);
|
|
10912
|
-
return false;
|
|
10913
|
-
});
|
|
11080
|
+
error(err);
|
|
11081
|
+
return false;
|
|
11082
|
+
});
|
|
11083
|
+
}
|
|
11084
|
+
runQuery();
|
|
10914
11085
|
};
|
|
10915
11086
|
|
|
10916
11087
|
/**
|
|
@@ -11019,6 +11190,7 @@
|
|
|
11019
11190
|
IDBCursor.prototype.__invalidateCache = function () {
|
|
11020
11191
|
// @ts-expect-error Why is this not being found?
|
|
11021
11192
|
this.__prefetchedData = null;
|
|
11193
|
+
this.__multiEntryExhausted = false;
|
|
11022
11194
|
};
|
|
11023
11195
|
|
|
11024
11196
|
/**
|
|
@@ -11074,8 +11246,8 @@
|
|
|
11074
11246
|
me.__advanceCount--;
|
|
11075
11247
|
me.__key = k;
|
|
11076
11248
|
me.__continue(undefined, true);
|
|
11077
|
-
|
|
11078
|
-
|
|
11249
|
+
// We don't call success yet but do need to advance the transaction queue
|
|
11250
|
+
runContinuationSafely(/** @type {() => void} */executeNextRequest);
|
|
11079
11251
|
return;
|
|
11080
11252
|
}
|
|
11081
11253
|
me.__advanceCount = undefined;
|
|
@@ -11097,11 +11269,15 @@
|
|
|
11097
11269
|
return;
|
|
11098
11270
|
}
|
|
11099
11271
|
// @ts-expect-error Todo: Our bug to fix
|
|
11100
|
-
|
|
11272
|
+
runContinuationSafely(function () {
|
|
11273
|
+
return cursorContinue(tx, args, success, error);
|
|
11274
|
+
});
|
|
11101
11275
|
}
|
|
11102
11276
|
if (me.__unique && !me.__multiEntryIndex && encKey === _encode(me.key, me.__multiEntryIndex)) {
|
|
11103
11277
|
// @ts-expect-error Todo: Our bug to fix
|
|
11104
|
-
|
|
11278
|
+
runContinuationSafely(function () {
|
|
11279
|
+
return cursorContinue(tx, args, success, error);
|
|
11280
|
+
});
|
|
11105
11281
|
return;
|
|
11106
11282
|
}
|
|
11107
11283
|
checkKey();
|