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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! indexeddbshim - v17.3.
|
|
1
|
+
/*! indexeddbshim - v17.3.3 - 8/25/2026 */
|
|
2
2
|
|
|
3
3
|
(function (global, factory) {
|
|
4
4
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -6156,9 +6156,15 @@
|
|
|
6156
6156
|
if (err !== null) {
|
|
6157
6157
|
me.__error = err;
|
|
6158
6158
|
}
|
|
6159
|
-
if (me.__requestsFinished) {
|
|
6159
|
+
if (me.__requestsFinished && err !== null) {
|
|
6160
6160
|
// The transaction has already completed, so we can't call "onerror" or "onabort".
|
|
6161
|
-
// So throw the error instead.
|
|
6161
|
+
// So throw the error instead. `err` is only ever `null` here via
|
|
6162
|
+
// `IDBTransaction.prototype.abort`'s own `__abortTransaction(null)`
|
|
6163
|
+
// call, which now checks `__requestsFinished` itself first and
|
|
6164
|
+
// throws `InvalidStateError` synchronously before ever reaching
|
|
6165
|
+
// this point -- so this guard is just defense in depth against
|
|
6166
|
+
// `err` somehow being `null` some other way, not something this
|
|
6167
|
+
// path should see in practice.
|
|
6162
6168
|
setTimeout(function () {
|
|
6163
6169
|
throw err;
|
|
6164
6170
|
}, 0);
|
|
@@ -6278,6 +6284,14 @@
|
|
|
6278
6284
|
if (me.__committed) {
|
|
6279
6285
|
throw createDOMException('InvalidStateError', 'The transaction has already been committed');
|
|
6280
6286
|
}
|
|
6287
|
+
if (me.__requestsFinished) {
|
|
6288
|
+
// All requests have already finished and the transaction is
|
|
6289
|
+
// auto-committing (the async SQL commit round trip just hasn't
|
|
6290
|
+
// resolved yet) -- too late to abort per spec, even though
|
|
6291
|
+
// `__committed` itself isn't set until that round trip actually
|
|
6292
|
+
// finishes.
|
|
6293
|
+
throw createDOMException('InvalidStateError', 'The transaction is already committing');
|
|
6294
|
+
}
|
|
6281
6295
|
me.__abortTransaction(null);
|
|
6282
6296
|
};
|
|
6283
6297
|
|
|
@@ -11092,7 +11106,29 @@
|
|
|
11092
11106
|
return new SyncPromise(function (resolve) {
|
|
11093
11107
|
setTimeout(function () {
|
|
11094
11108
|
entry.dispatchEvent(e); // No need to catch errors
|
|
11095
|
-
|
|
11109
|
+
// Unlike a native `Promise`, `SyncPromise#then` chains
|
|
11110
|
+
// synchronously off `resolve()` (verified directly:
|
|
11111
|
+
// `SyncPromise.resolve().then(cb)` runs `cb` before
|
|
11112
|
+
// even the calling code below it finishes) -- so
|
|
11113
|
+
// resolving immediately here would let the
|
|
11114
|
+
// `connectionsClosed()` check below run before a
|
|
11115
|
+
// same-task-but-microtask-later continuation of a
|
|
11116
|
+
// `versionchange` listener above (e.g. an `await`-
|
|
11117
|
+
// based one that then calls `db.close()`, as in
|
|
11118
|
+
// `transaction-lifetime.any.js`) ever gets a turn,
|
|
11119
|
+
// incorrectly firing `blocked` even though the
|
|
11120
|
+
// connection was about to close in time. Give real
|
|
11121
|
+
// microtask-deferred continuations a small, bounded
|
|
11122
|
+
// number of turns first -- same pattern as
|
|
11123
|
+
// `IDBTransaction.js`'s `checkQueueEntry`.
|
|
11124
|
+
var attemptsLeft = 10;
|
|
11125
|
+
(function wait() {
|
|
11126
|
+
if (attemptsLeft-- <= 0) {
|
|
11127
|
+
resolve(undefined);
|
|
11128
|
+
return;
|
|
11129
|
+
}
|
|
11130
|
+
queueMicrotask(wait);
|
|
11131
|
+
})();
|
|
11096
11132
|
}, 0);
|
|
11097
11133
|
});
|
|
11098
11134
|
});
|
|
@@ -11152,6 +11188,23 @@
|
|
|
11152
11188
|
*/
|
|
11153
11189
|
var websqlDBCache = {};
|
|
11154
11190
|
|
|
11191
|
+
/**
|
|
11192
|
+
* Tracks databases with a creation/upgrade currently in flight but not yet
|
|
11193
|
+
* committed or aborted -- keyed by (unescaped) database name. The
|
|
11194
|
+
* `dbVersions` row in `sysdb` these entries shadow is written *before*
|
|
11195
|
+
* `upgradeneeded` is even dispatched to user code (as the success
|
|
11196
|
+
* callback of that very `INSERT`/`UPDATE`), on the same shared `sysdb`
|
|
11197
|
+
* connection `databases()` itself reads from -- so, absent this, a
|
|
11198
|
+
* `databases()` call made while an upgrade is still pending would see
|
|
11199
|
+
* the new row (or new version) immediately, rather than only once the
|
|
11200
|
+
* corresponding `versionchange` transaction has genuinely committed, as
|
|
11201
|
+
* required by `get-databases.any.js`'s "doesn't pick up changes that
|
|
11202
|
+
* haven't committed" test. `IDBFactory.prototype.databases` filters
|
|
11203
|
+
* its SQL results against this map.
|
|
11204
|
+
* @type {Map<string, {oldVersion: Integer, newVersion: Integer}>}
|
|
11205
|
+
*/
|
|
11206
|
+
var pendingVersionChanges = new Map();
|
|
11207
|
+
|
|
11155
11208
|
/** @type {import('websql-configurable/lib/websql/WebSQLDatabase.js').default} */
|
|
11156
11209
|
var sysdb;
|
|
11157
11210
|
var nameCounter = 0;
|
|
@@ -11454,6 +11507,19 @@
|
|
|
11454
11507
|
if (calledDbCreateError) {
|
|
11455
11508
|
return false;
|
|
11456
11509
|
}
|
|
11510
|
+
// Defensive cleanup: `pendingVersionChanges.set(name, ...)` (see
|
|
11511
|
+
// below) runs *before* the `dbVersions` `INSERT`/`UPDATE` it
|
|
11512
|
+
// guards is even attempted, but only `versionSet`'s own
|
|
11513
|
+
// `on__beforecomplete`/`on__preabort` handlers ever clear it --
|
|
11514
|
+
// and `versionSet` never runs at all if that `INSERT`/`UPDATE`,
|
|
11515
|
+
// or an earlier step in this same `open()` flow, fails first.
|
|
11516
|
+
// Without this, such a failure would leave the entry orphaned
|
|
11517
|
+
// forever, silently corrupting `databases()` for any *other*,
|
|
11518
|
+
// unrelated later `open()` call that happens to reuse the same
|
|
11519
|
+
// database name (common in WPT tests, e.g. generic names like
|
|
11520
|
+
// "DB1"/"TestDatabase" reused across different test files in
|
|
11521
|
+
// the same process). A no-op if no entry was ever set.
|
|
11522
|
+
pendingVersionChanges.delete(name);
|
|
11457
11523
|
var er = err ? webSQLErrback(err) : (/** @type {Error} */tx);
|
|
11458
11524
|
calledDbCreateError = true;
|
|
11459
11525
|
// Re: why bubbling here (and how cancelable is only really relevant for `window.onerror`) see: https://github.com/w3c/IndexedDB/issues/86
|
|
@@ -11565,22 +11631,43 @@
|
|
|
11565
11631
|
// open/close the transaction's active-handler window itself.
|
|
11566
11632
|
req.transaction.__handlerActive = true;
|
|
11567
11633
|
req.dispatchEvent(e);
|
|
11568
|
-
// Give any
|
|
11634
|
+
// Give any microtask-scheduled continuation of the
|
|
11569
11635
|
// `upgradeneeded` handler (e.g. a plain
|
|
11570
|
-
// `Promise.resolve().then(...)
|
|
11571
|
-
//
|
|
11572
|
-
//
|
|
11573
|
-
//
|
|
11574
|
-
//
|
|
11575
|
-
//
|
|
11576
|
-
//
|
|
11577
|
-
//
|
|
11578
|
-
//
|
|
11579
|
-
//
|
|
11580
|
-
//
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11636
|
+
// `Promise.resolve().then(...)`, or an `await`-based
|
|
11637
|
+
// continuation of a promise resolved from within the handler,
|
|
11638
|
+
// such as testharness.js's own `EventWatcher`) a chance to
|
|
11639
|
+
// run -- and still observe the transaction as active -- before
|
|
11640
|
+
// we deactivate it again, per
|
|
11641
|
+
// https://github.com/w3c/IndexedDB/issues/87. A single deferred
|
|
11642
|
+
// tick isn't always enough: an `await`-based continuation can
|
|
11643
|
+
// take more than one microtask turn to resume (e.g.
|
|
11644
|
+
// `transaction-lifetime.any.js`'s `EventWatcher`-based
|
|
11645
|
+
// `await eventWatcher.wait_for('upgradeneeded')`), so retry a
|
|
11646
|
+
// small, bounded number of times first -- same pattern as
|
|
11647
|
+
// `IDBTransaction.js`'s `checkQueueEntry` -- rather than
|
|
11648
|
+
// resetting after only one. Only the flag reset itself is
|
|
11649
|
+
// deferred here -- unlike `IDBTransaction.js`'s
|
|
11650
|
+
// `advanceAfterDispatch`, `finished()` (this transaction's own
|
|
11651
|
+
// queue-advancement/completion signal) still runs
|
|
11652
|
+
// synchronously, at exactly its previous timing: an earlier
|
|
11653
|
+
// attempt at deferring `finished()` too raced against unrelated
|
|
11654
|
+
// test setup that assumed a freshly deleted/created database's
|
|
11655
|
+
// upgrade transaction had already fully completed by the time
|
|
11656
|
+
// this function returns.
|
|
11657
|
+
/**
|
|
11658
|
+
* @param {Integer} attemptsLeft
|
|
11659
|
+
* @returns {void}
|
|
11660
|
+
*/
|
|
11661
|
+
function deferHandlerActiveReset(attemptsLeft) {
|
|
11662
|
+
if (attemptsLeft <= 0) {
|
|
11663
|
+
req.transaction.__handlerActive = false;
|
|
11664
|
+
return;
|
|
11665
|
+
}
|
|
11666
|
+
queueMicrotask(function () {
|
|
11667
|
+
deferHandlerActiveReset(attemptsLeft - 1);
|
|
11668
|
+
});
|
|
11669
|
+
}
|
|
11670
|
+
deferHandlerActiveReset(10);
|
|
11584
11671
|
if (e.__legacyOutputDidListenersThrowError) {
|
|
11585
11672
|
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
|
|
11586
11673
|
req.transaction.__abortTransaction(createDOMException('AbortError', 'A request was aborted.'));
|
|
@@ -11596,6 +11683,7 @@
|
|
|
11596
11683
|
* @returns {void}
|
|
11597
11684
|
*/
|
|
11598
11685
|
function (ev) {
|
|
11686
|
+
pendingVersionChanges.delete(name);
|
|
11599
11687
|
connection.__upgradeTransaction = null;
|
|
11600
11688
|
/** @type {import('./IDBDatabase.js').IDBDatabaseFull} */
|
|
11601
11689
|
req.__result.__versionTransaction = null;
|
|
@@ -11610,6 +11698,7 @@
|
|
|
11610
11698
|
|
|
11611
11699
|
// eslint-disable-next-line camelcase -- Clear API
|
|
11612
11700
|
req.transaction.on__preabort = function () {
|
|
11701
|
+
pendingVersionChanges.delete(name);
|
|
11613
11702
|
connection.__upgradeTransaction = null;
|
|
11614
11703
|
// We ensure any cache is deleted before any request error events fire and try to reopen
|
|
11615
11704
|
if (useDatabaseCache) {
|
|
@@ -11672,6 +11761,10 @@
|
|
|
11672
11761
|
// });
|
|
11673
11762
|
};
|
|
11674
11763
|
}
|
|
11764
|
+
pendingVersionChanges.set(name, {
|
|
11765
|
+
oldVersion: oldVersion,
|
|
11766
|
+
newVersion: version
|
|
11767
|
+
});
|
|
11675
11768
|
if (oldVersion === 0) {
|
|
11676
11769
|
systx.executeSql('INSERT INTO dbVersions VALUES (?,?)', [sqlSafeName, version], versionSet, dbCreateError);
|
|
11677
11770
|
} else {
|
|
@@ -11974,6 +12067,15 @@
|
|
|
11974
12067
|
IDBFactory.prototype.databases = function () {
|
|
11975
12068
|
var me = this;
|
|
11976
12069
|
var calledDbCreateError = false;
|
|
12070
|
+
// Snapshotted *now*, synchronously, at call time -- not read later
|
|
12071
|
+
// from inside the SQL query's callback below, which runs on a
|
|
12072
|
+
// deferred macrotask (see `nodeSQLiteDatabase.js`'s `exec`) and so
|
|
12073
|
+
// could otherwise race against (and lose to) an in-flight upgrade's
|
|
12074
|
+
// own commit/abort handler clearing its `pendingVersionChanges`
|
|
12075
|
+
// entry in the meantime -- which would make this method incorrectly
|
|
12076
|
+
// reflect a since-committed change that hadn't committed yet when
|
|
12077
|
+
// it was actually called.
|
|
12078
|
+
var pendingVersionChangesSnapshot = new Map(pendingVersionChanges);
|
|
11977
12079
|
return new Promise(function (resolve, reject) {
|
|
11978
12080
|
// eslint-disable-line promise/avoid-new -- Own polyfill
|
|
11979
12081
|
if (!(me instanceof IDBFactory)) {
|
|
@@ -12003,10 +12105,29 @@
|
|
|
12003
12105
|
var dbNames = [];
|
|
12004
12106
|
for (var i = 0; i < data.rows.length; i++) {
|
|
12005
12107
|
var _data$rows$item2 = /** @type {{name: string, version: Integer}} */data.rows.item(i),
|
|
12006
|
-
|
|
12108
|
+
encodedName = _data$rows$item2.name,
|
|
12007
12109
|
version = _data$rows$item2.version;
|
|
12110
|
+
var name = unescapeSQLiteResponse(encodedName);
|
|
12111
|
+
// A row for a database whose creation/upgrade hasn't
|
|
12112
|
+
// committed yet (see `pendingVersionChanges`) must
|
|
12113
|
+
// not reflect that in-flight change: a brand new
|
|
12114
|
+
// database (`oldVersion === 0`) isn't reported at
|
|
12115
|
+
// all until its creation commits, and an existing
|
|
12116
|
+
// database being upgraded is still reported, but
|
|
12117
|
+
// with its pre-upgrade version.
|
|
12118
|
+
var pending = pendingVersionChangesSnapshot.get(name);
|
|
12119
|
+
if (pending) {
|
|
12120
|
+
if (pending.oldVersion === 0) {
|
|
12121
|
+
continue;
|
|
12122
|
+
}
|
|
12123
|
+
dbNames.push({
|
|
12124
|
+
name: name,
|
|
12125
|
+
version: pending.oldVersion
|
|
12126
|
+
});
|
|
12127
|
+
continue;
|
|
12128
|
+
}
|
|
12008
12129
|
dbNames.push({
|
|
12009
|
-
name:
|
|
12130
|
+
name: name,
|
|
12010
12131
|
version: version
|
|
12011
12132
|
});
|
|
12012
12133
|
}
|
|
@@ -12426,9 +12547,26 @@
|
|
|
12426
12547
|
// Key.convertValueToKey(key); // Already checked by `continue` or `continuePrimaryKey`
|
|
12427
12548
|
sqlValues.push(/** @type {string} */_encode(key));
|
|
12428
12549
|
} else if (continueCall && me.__key !== undefined) {
|
|
12429
|
-
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
12430
12550
|
// Key.convertValueToKey(me.__key); // Already checked when stored
|
|
12431
|
-
|
|
12551
|
+
if (!me.__unique && me.__keyColumnName !== 'key' && me.__primaryKey !== undefined) {
|
|
12552
|
+
// A plain `continue()` on a non-unique index cursor must find
|
|
12553
|
+
// the next record strictly after the (key, primaryKey) pair
|
|
12554
|
+
// this cursor last returned -- a scalar `key > lastKey` alone
|
|
12555
|
+
// would wrongly exclude a *different*, not-yet-visited record
|
|
12556
|
+
// that's still tied on key with the last one (e.g. another
|
|
12557
|
+
// record that always had that same indexed value), and would
|
|
12558
|
+
// also wrongly re-admit the *same* record forever if a
|
|
12559
|
+
// same-transaction `update()` bumped its own key back above
|
|
12560
|
+
// the threshold, since a scalar comparison can't distinguish
|
|
12561
|
+
// "some other record newly tied" from "this record moved
|
|
12562
|
+
// past its own last position." Comparing the full tuple (via
|
|
12563
|
+
// this OR) against both key and primary key resolves both.
|
|
12564
|
+
sql.push('AND (', quotedKeyColumnName, op, '?', 'OR (', quotedKeyColumnName, '= ?', 'AND', quotedKey, op, '?))');
|
|
12565
|
+
sqlValues.push(/** @type {string} */_encode(me.__key), /** @type {string} */_encode(me.__key), /** @type {string} */_encode(me.__primaryKey));
|
|
12566
|
+
} else {
|
|
12567
|
+
sql.push('AND', quotedKeyColumnName, op + ' ?');
|
|
12568
|
+
sqlValues.push(/** @type {string} */_encode(me.__key));
|
|
12569
|
+
}
|
|
12432
12570
|
}
|
|
12433
12571
|
if (!me.__count) {
|
|
12434
12572
|
// 1. Sort by key
|
|
@@ -13058,9 +13196,15 @@
|
|
|
13058
13196
|
* @returns {void}
|
|
13059
13197
|
*/
|
|
13060
13198
|
function addToQueue(clonedValue) {
|
|
13061
|
-
//
|
|
13199
|
+
// `invalidateCache: true` so any cursor on this store (including
|
|
13200
|
+
// this one) drops its prefetched row batch, forcing its next
|
|
13201
|
+
// `continue()` to re-query live rather than serve rows snapshotted
|
|
13202
|
+
// before this update -- needed for the compound-tuple
|
|
13203
|
+
// continuation logic in `__findBasic` to see this update's
|
|
13204
|
+
// effect on ordering (see "Modify records during cursor
|
|
13205
|
+
// iteration" in idbcursor_update_index.any.js).
|
|
13062
13206
|
// @ts-ignore -- API (not erring in TS 6)
|
|
13063
|
-
IDBObjectStore.__storingRecordObjectStore(request, me.__store,
|
|
13207
|
+
IDBObjectStore.__storingRecordObjectStore(request, me.__store, true, clonedValue, false, key);
|
|
13064
13208
|
}
|
|
13065
13209
|
if (me.__store.keyPath !== null) {
|
|
13066
13210
|
var _me$__store$__validat = me.__store.__validateKeyAndValueAndCloneValue(valueToUpdate, undefined, true),
|