indexeddbshim 17.3.2 → 17.3.3
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/dist/IDBCursor.d.ts.map +1 -1
- package/dist/IDBFactory.d.ts.map +1 -1
- package/dist/IDBTransaction.d.ts.map +1 -1
- package/dist/indexeddbshim-Key.js +1 -1
- package/dist/indexeddbshim-Key.min.js +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs +344 -88
- package/dist/indexeddbshim-UnicodeIdentifiers-node.cjs.map +1 -1
- package/dist/indexeddbshim-UnicodeIdentifiers.js +169 -25
- 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 +344 -88
- package/dist/indexeddbshim-node.cjs.map +1 -1
- package/dist/indexeddbshim-noninvasive.js +169 -25
- 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 +169 -25
- package/dist/indexeddbshim.js.map +1 -1
- package/dist/indexeddbshim.min.js +3 -3
- package/dist/indexeddbshim.min.js.map +1 -1
- package/dist/nodeSQLiteDatabase.d.ts.map +1 -1
- package/dist/nodeWebSQL.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/IDBCursor.js +34 -4
- package/src/IDBFactory.js +119 -21
- package/src/IDBTransaction.js +16 -2
- package/src/nodeSQLiteDatabase.js +92 -26
- package/src/nodeWebSQL.js +8 -1
package/dist/indexeddbshim.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! indexeddbshim - v17.3.
|
|
1
|
+
/*! indexeddbshim - v17.3.3 - 8/25/2026 */
|
|
2
2
|
|
|
3
3
|
(function (factory) {
|
|
4
4
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
@@ -6148,9 +6148,15 @@
|
|
|
6148
6148
|
if (err !== null) {
|
|
6149
6149
|
me.__error = err;
|
|
6150
6150
|
}
|
|
6151
|
-
if (me.__requestsFinished) {
|
|
6151
|
+
if (me.__requestsFinished && err !== null) {
|
|
6152
6152
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
6153
|
-
// So throw the error instead.
|
|
6153
|
+
// So throw the error instead. `err` is only ever `null` here via
|
|
6154
|
+
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
6155
|
+
// call, which now checks `__requestsFinished` itself first and
|
|
6156
|
+
// throws `InvalidStateError` synchronously before ever reaching
|
|
6157
|
+
// this point -- so this guard is just defense in depth against
|
|
6158
|
+
// `err` somehow being `null` some other way, not something this
|
|
6159
|
+
// path should see in practice.
|
|
6154
6160
|
setTimeout(function () {
|
|
6155
6161
|
throw err;
|
|
6156
6162
|
}, 0);
|
|
@@ -6270,6 +6276,14 @@
|
|
|
6270
6276
|
if (me.__committed) {
|
|
6271
6277
|
throw createDOMException('InvalidStateError', 'The transaction has already been committed');
|
|
6272
6278
|
}
|
|
6279
|
+
if (me.__requestsFinished) {
|
|
6280
|
+
// All requests have already finished and the transaction is
|
|
6281
|
+
// auto-committing (the async SQL commit round trip just hasn't
|
|
6282
|
+
// resolved yet) -- too late to abort per spec, even though
|
|
6283
|
+
// `__committed` itself isn't set until that round trip actually
|
|
6284
|
+
// finishes.
|
|
6285
|
+
throw createDOMException('InvalidStateError', 'The transaction is already committing');
|
|
6286
|
+
}
|
|
6273
6287
|
me.__abortTransaction(null);
|
|
6274
6288
|
};
|
|
6275
6289
|
|
|
@@ -11084,7 +11098,29 @@
|
|
|
11084
11098
|
return new SyncPromise(function (resolve) {
|
|
11085
11099
|
setTimeout(function () {
|
|
11086
11100
|
entry.dispatchEvent(e); // No need to catch errors
|
|
11087
|
-
|
|
11101
|
+
// Unlike a native `Promise`, `SyncPromise#then` chains
|
|
11102
|
+
// synchronously off `resolve()` (verified directly:
|
|
11103
|
+
// `SyncPromise.resolve().then(cb)` runs `cb` before
|
|
11104
|
+
// even the calling code below it finishes) -- so
|
|
11105
|
+
// resolving immediately here would let the
|
|
11106
|
+
// `connectionsClosed()` check below run before a
|
|
11107
|
+
// same-task-but-microtask-later continuation of a
|
|
11108
|
+
// `versionchange` listener above (e.g. an `await`-
|
|
11109
|
+
// based one that then calls `db.close()`, as in
|
|
11110
|
+
// `transaction-lifetime.any.js`) ever gets a turn,
|
|
11111
|
+
// incorrectly firing `blocked` even though the
|
|
11112
|
+
// connection was about to close in time. Give real
|
|
11113
|
+
// microtask-deferred continuations a small, bounded
|
|
11114
|
+
// number of turns first -- same pattern as
|
|
11115
|
+
// `IDBTransaction.js`'s `checkQueueEntry`.
|
|
11116
|
+
var attemptsLeft = 10;
|
|
11117
|
+
(function wait() {
|
|
11118
|
+
if (attemptsLeft-- <= 0) {
|
|
11119
|
+
resolve(undefined);
|
|
11120
|
+
return;
|
|
11121
|
+
}
|
|
11122
|
+
queueMicrotask(wait);
|
|
11123
|
+
})();
|
|
11088
11124
|
}, 0);
|
|
11089
11125
|
});
|
|
11090
11126
|
});
|
|
@@ -11144,6 +11180,23 @@
|
|
|
11144
11180
|
*/
|
|
11145
11181
|
var websqlDBCache = {};
|
|
11146
11182
|
|
|
11183
|
+
/**
|
|
11184
|
+
* Tracks databases with a creation/upgrade currently in flight but not yet
|
|
11185
|
+
* committed or aborted -- keyed by (unescaped) database name. The
|
|
11186
|
+
* `dbVersions` row in `sysdb` these entries shadow is written *before*
|
|
11187
|
+
* `upgradeneeded` is even dispatched to user code (as the success
|
|
11188
|
+
* callback of that very `INSERT`/`UPDATE`), on the same shared `sysdb`
|
|
11189
|
+
* connection `databases()` itself reads from -- so, absent this, a
|
|
11190
|
+
* `databases()` call made while an upgrade is still pending would see
|
|
11191
|
+
* the new row (or new version) immediately, rather than only once the
|
|
11192
|
+
* corresponding `versionchange` transaction has genuinely committed, as
|
|
11193
|
+
* required by `get-databases.any.js`'s "doesn't pick up changes that
|
|
11194
|
+
* haven't committed" test. `IDBFactory.prototype.databases` filters
|
|
11195
|
+
* its SQL results against this map.
|
|
11196
|
+
* @type {Map<string, {oldVersion: Integer, newVersion: Integer}>}
|
|
11197
|
+
*/
|
|
11198
|
+
var pendingVersionChanges = new Map();
|
|
11199
|
+
|
|
11147
11200
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
11148
11201
|
var sysdb;
|
|
11149
11202
|
var nameCounter = 0;
|
|
@@ -11446,6 +11499,19 @@
|
|
|
11446
11499
|
if (calledDbCreateError) {
|
|
11447
11500
|
return false;
|
|
11448
11501
|
}
|
|
11502
|
+
// Defensive cleanup: `pendingVersionChanges.set(name, ...)` (see
|
|
11503
|
+
// below) runs *before* the `dbVersions` `INSERT`/`UPDATE` it
|
|
11504
|
+
// guards is even attempted, but only `versionSet`'s own
|
|
11505
|
+
// `on__beforecomplete`/`on__preabort` handlers ever clear it --
|
|
11506
|
+
// and `versionSet` never runs at all if that `INSERT`/`UPDATE`,
|
|
11507
|
+
// or an earlier step in this same `open()` flow, fails first.
|
|
11508
|
+
// Without this, such a failure would leave the entry orphaned
|
|
11509
|
+
// forever, silently corrupting `databases()` for any *other*,
|
|
11510
|
+
// unrelated later `open()` call that happens to reuse the same
|
|
11511
|
+
// database name (common in WPT tests, e.g. generic names like
|
|
11512
|
+
// "DB1"/"TestDatabase" reused across different test files in
|
|
11513
|
+
// the same process). A no-op if no entry was ever set.
|
|
11514
|
+
pendingVersionChanges.delete(name);
|
|
11449
11515
|
var er = err ? webSQLErrback(err) : (/** @type {Error} */tx);
|
|
11450
11516
|
calledDbCreateError = true;
|
|
11451
11517
|
// Re: why bubbling here (and how cancelable is only really relevant for `window.onerror`) see: https://github.com/w3c/IndexedDB/issues/86
|
|
@@ -11557,22 +11623,43 @@
|
|
|
11557
11623
|
// open/close the transaction's active-handler window itself.
|
|
11558
11624
|
req.transaction.__handlerActive = true;
|
|
11559
11625
|
req.dispatchEvent(e);
|
|
11560
|
-
// Give any
|
|
11626
|
+
// Give any microtask-scheduled continuation of the
|
|
11561
11627
|
// `upgradeneeded` handler (e.g. a plain
|
|
11562
|
-
// `Promise.resolve().then(...)
|
|
11563
|
-
//
|
|
11564
|
-
//
|
|
11565
|
-
//
|
|
11566
|
-
//
|
|
11567
|
-
//
|
|
11568
|
-
//
|
|
11569
|
-
//
|
|
11570
|
-
//
|
|
11571
|
-
//
|
|
11572
|
-
//
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11628
|
+
// `Promise.resolve().then(...)`, or an `await`-based
|
|
11629
|
+
// continuation of a promise resolved from within the handler,
|
|
11630
|
+
// such as testharness.js's own `EventWatcher`) a chance to
|
|
11631
|
+
// run -- and still observe the transaction as active -- before
|
|
11632
|
+
// we deactivate it again, per
|
|
11633
|
+
// https://github.com/w3c/IndexedDB/issues/87. A single deferred
|
|
11634
|
+
// tick isn't always enough: an `await`-based continuation can
|
|
11635
|
+
// take more than one microtask turn to resume (e.g.
|
|
11636
|
+
// `transaction-lifetime.any.js`'s `EventWatcher`-based
|
|
11637
|
+
// `await eventWatcher.wait_for('upgradeneeded')`), so retry a
|
|
11638
|
+
// small, bounded number of times first -- same pattern as
|
|
11639
|
+
// `IDBTransaction.js`'s `checkQueueEntry` -- rather than
|
|
11640
|
+
// resetting after only one. Only the flag reset itself is
|
|
11641
|
+
// deferred here -- unlike `IDBTransaction.js`'s
|
|
11642
|
+
// `advanceAfterDispatch`, `finished()` (this transaction's own
|
|
11643
|
+
// queue-advancement/completion signal) still runs
|
|
11644
|
+
// synchronously, at exactly its previous timing: an earlier
|
|
11645
|
+
// attempt at deferring `finished()` too raced against unrelated
|
|
11646
|
+
// test setup that assumed a freshly deleted/created database's
|
|
11647
|
+
// upgrade transaction had already fully completed by the time
|
|
11648
|
+
// this function returns.
|
|
11649
|
+
/**
|
|
11650
|
+
* @param {Integer} attemptsLeft
|
|
11651
|
+
* @returns {void}
|
|
11652
|
+
*/
|
|
11653
|
+
function deferHandlerActiveReset(attemptsLeft) {
|
|
11654
|
+
if (attemptsLeft <= 0) {
|
|
11655
|
+
req.transaction.__handlerActive = false;
|
|
11656
|
+
return;
|
|
11657
|
+
}
|
|
11658
|
+
queueMicrotask(function () {
|
|
11659
|
+
deferHandlerActiveReset(attemptsLeft - 1);
|
|
11660
|
+
});
|
|
11661
|
+
}
|
|
11662
|
+
deferHandlerActiveReset(10);
|
|
11576
11663
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
11577
11664
|
logError('Error', 'An error occurred in an upgradeneeded handler attached to request chain', /** @type {Error} */e.__legacyOutputDidListenersThrowError); // We do nothing else with this error as per spec
|
|
11578
11665
|
req.transaction.__abortTransaction(createDOMException('AbortError', 'A request was aborted.'));
|
|
@@ -11588,6 +11675,7 @@
|
|
|
11588
11675
|
* @returns {void}
|
|
11589
11676
|
*/
|
|
11590
11677
|
function (ev) {
|
|
11678
|
+
pendingVersionChanges.delete(name);
|
|
11591
11679
|
connection.__upgradeTransaction = null;
|
|
11592
11680
|
/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
|
|
11593
11681
|
req.__result.__versionTransaction = null;
|
|
@@ -11602,6 +11690,7 @@
|
|
|
11602
11690
|
|
|
11603
11691
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11604
11692
|
req.transaction.on__preabort = function () {
|
|
11693
|
+
pendingVersionChanges.delete(name);
|
|
11605
11694
|
connection.__upgradeTransaction = null;
|
|
11606
11695
|
// We ensure any cache is deleted before any request error events fire and try to reopen
|
|
11607
11696
|
if (useDatabaseCache) {
|
|
@@ -11664,6 +11753,10 @@
|
|
|
11664
11753
|
// });
|
|
11665
11754
|
};
|
|
11666
11755
|
}
|
|
11756
|
+
pendingVersionChanges.set(name, {
|
|
11757
|
+
oldVersion: oldVersion,
|
|
11758
|
+
newVersion: version
|
|
11759
|
+
});
|
|
11667
11760
|
if (oldVersion === 0) {
|
|
11668
11761
|
systx.executeSql('INSERT INTO dbVersions VALUES (?,?)', [sqlSafeName, version], versionSet, dbCreateError);
|
|
11669
11762
|
} else {
|
|
@@ -11966,6 +12059,15 @@
|
|
|
11966
12059
|
IDBFactory.prototype.databases = function () {
|
|
11967
12060
|
var me = this;
|
|
11968
12061
|
var calledDbCreateError = false;
|
|
12062
|
+
// Snapshotted *now*, synchronously, at call time -- not read later
|
|
12063
|
+
// from inside the SQL query's callback below, which runs on a
|
|
12064
|
+
// deferred macrotask (see `nodeSQLiteDatabase.js`'s `exec`) and so
|
|
12065
|
+
// could otherwise race against (and lose to) an in-flight upgrade's
|
|
12066
|
+
// own commit/abort handler clearing its `pendingVersionChanges`
|
|
12067
|
+
// entry in the meantime -- which would make this method incorrectly
|
|
12068
|
+
// reflect a since-committed change that hadn't committed yet when
|
|
12069
|
+
// it was actually called.
|
|
12070
|
+
var pendingVersionChangesSnapshot = new Map(pendingVersionChanges);
|
|
11969
12071
|
return new Promise(function (resolve, reject) {
|
|
11970
12072
|
// eslint-disable-line promise/avoid-new -- Own polyfill
|
|
11971
12073
|
if (!(me instanceof IDBFactory)) {
|
|
@@ -11995,10 +12097,29 @@
|
|
|
11995
12097
|
var dbNames = [];
|
|
11996
12098
|
for (var i = 0; i < data.rows.length; i++) {
|
|
11997
12099
|
var _data$rows$item2 = /** @type {{name: string, version: Integer}} */data.rows.item(i),
|
|
11998
|
-
|
|
12100
|
+
encodedName = _data$rows$item2.name,
|
|
11999
12101
|
version = _data$rows$item2.version;
|
|
12102
|
+
var name = unescapeSQLiteResponse(encodedName);
|
|
12103
|
+
// A row for a database whose creation/upgrade hasn't
|
|
12104
|
+
// committed yet (see `pendingVersionChanges`) must
|
|
12105
|
+
// not reflect that in-flight change: a brand new
|
|
12106
|
+
// database (`oldVersion === 0`) isn't reported at
|
|
12107
|
+
// all until its creation commits, and an existing
|
|
12108
|
+
// database being upgraded is still reported, but
|
|
12109
|
+
// with its pre-upgrade version.
|
|
12110
|
+
var pending = pendingVersionChangesSnapshot.get(name);
|
|
12111
|
+
if (pending) {
|
|
12112
|
+
if (pending.oldVersion === 0) {
|
|
12113
|
+
continue;
|
|
12114
|
+
}
|
|
12115
|
+
dbNames.push({
|
|
12116
|
+
name: name,
|
|
12117
|
+
version: pending.oldVersion
|
|
12118
|
+
});
|
|
12119
|
+
continue;
|
|
12120
|
+
}
|
|
12000
12121
|
dbNames.push({
|
|
12001
|
-
name:
|
|
12122
|
+
name: name,
|
|
12002
12123
|
version: version
|
|
12003
12124
|
});
|
|
12004
12125
|
}
|
|
@@ -12418,9 +12539,26 @@
|
|
|
12418
12539
|
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
12419
12540
|
sqlValues.push(/** @type {string} */_encode(key));
|
|
12420
12541
|
} else if (continueCall && me.__key !== undefined) {
|
|
12421
|
-
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
12422
12542
|
// Key.convertValueToKey(me.__key); // Already checked when stored
|
|
12423
|
-
|
|
12543
|
+
if (!me.__unique && me.__keyColumnName !== 'key' && me.__primaryKey !== undefined) {
|
|
12544
|
+
// A plain `continue()` on a non-unique index cursor must find
|
|
12545
|
+
// the next record strictly after the (key, primaryKey) pair
|
|
12546
|
+
// this cursor last returned -- a scalar `key > lastKey` alone
|
|
12547
|
+
// would wrongly exclude a *different*, not-yet-visited record
|
|
12548
|
+
// that's still tied on key with the last one (e.g. another
|
|
12549
|
+
// record that always had that same indexed value), and would
|
|
12550
|
+
// also wrongly re-admit the *same* record forever if a
|
|
12551
|
+
// same-transaction `update()` bumped its own key back above
|
|
12552
|
+
// the threshold, since a scalar comparison can't distinguish
|
|
12553
|
+
// "some other record newly tied" from "this record moved
|
|
12554
|
+
// past its own last position." Comparing the full tuple (via
|
|
12555
|
+
// this OR) against both key and primary key resolves both.
|
|
12556
|
+
sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
|
|
12557
|
+
sqlValues.push(/** @type {string} */_encode(me.__key), /** @type {string} */_encode(me.__key), /** @type {string} */_encode(me.__primaryKey));
|
|
12558
|
+
} else {
|
|
12559
|
+
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
12560
|
+
sqlValues.push(/** @type {string} */_encode(me.__key));
|
|
12561
|
+
}
|
|
12424
12562
|
}
|
|
12425
12563
|
if (!me.__count) {
|
|
12426
12564
|
// 1. Sort by key
|
|
@@ -13050,9 +13188,15 @@
|
|
|
13050
13188
|
* @returns {void}
|
|
13051
13189
|
*/
|
|
13052
13190
|
function addToQueue(clonedValue) {
|
|
13053
|
-
//
|
|
13191
|
+
// `invalidateCache: true` so any cursor on this store (including
|
|
13192
|
+
// this one) drops its prefetched row batch, forcing its next
|
|
13193
|
+
// `continue()` to re-query live rather than serve rows snapshotted
|
|
13194
|
+
// before this update -- needed for the compound-tuple
|
|
13195
|
+
// continuation logic in `__findBasic` to see this update's
|
|
13196
|
+
// effect on ordering (see "Modify records during cursor
|
|
13197
|
+
// iteration" in idbcursor_update_index.any.js).
|
|
13054
13198
|
// @ts-ignore -- API (not erring in TS 6)
|
|
13055
|
-
IDBObjectStore.__storingRecordObjectStore(request, me.__store,
|
|
13199
|
+
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
13056
13200
|
}
|
|
13057
13201
|
if (me.__store.keyPath !== null) {
|
|
13058
13202
|
var _me$__store$__validat = me.__store.__validateKeyAndValueAndCloneValue(valueToUpdate, undefined, true),
|