LibWeb: Don't count unversioned databases in IDBFactory::databases()

This code was treating the parameter to the JS::Array as if it was a
capacity, but that causes JS to see more databases than are actually
accessible if a database was being created in an aborted transaction.
This commit is contained in:
Zaggy1024 2026-03-05 16:04:28 -06:00 committed by Gregory Bertilson
parent 547d4eb1f5
commit ef845fe22a
4 changed files with 61 additions and 2 deletions

View file

@ -203,9 +203,10 @@ GC::Ref<WebIDL::Promise> IDBFactory::databases()
auto databases = Database::for_key(storage_key);
// 2. Let result be a new list.
auto result = MUST(JS::Array::create(realm, databases.size()));
auto result = MUST(JS::Array::create(realm, 0));
// 3. For each db of databases:
u32 result_index = 0;
for (u32 i = 0; i < databases.size(); ++i) {
auto& db = databases[i];
@ -223,7 +224,7 @@ GC::Ref<WebIDL::Promise> IDBFactory::databases()
MUST(info->create_data_property("version"_utf16_fly_string, JS::Value(db->version())));
// 4. Append info to result.
MUST(result->create_data_property_or_throw(i, info));
MUST(result->create_data_property_or_throw(result_index++, info));
}
// 4. Resolve p with result.

View file

@ -0,0 +1,6 @@
Harness status: OK
Found 1 tests
1 Pass
Pass An abort() in the initial onupgradeneeded sets version back to 0

View file

@ -0,0 +1,15 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB</title>
<script>
self.GLOBAL = {
isWindow: function() { return true; },
isWorker: function() { return false; },
isShadowRealm: function() { return false; },
};
</script>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="resources/support.js"></script>
<div id=log></div>
<script src="../IndexedDB/abort-in-initial-upgradeneeded.any.js"></script>

View file

@ -0,0 +1,37 @@
// META: title=IndexedDB
// META: global=window,worker
// META: script=resources/support.js
'use strict';
async_test(t => {
let db;
let open_rq = createdb(t, undefined, 2);
open_rq.onupgradeneeded = function(e) {
db = e.target.result;
assert_equals(db.version, 2);
let transaction = e.target.transaction;
transaction.oncomplete = fail(t, 'unexpected transaction.complete');
transaction.onabort = function(e) {
assert_equals(e.target.db.version, 0);
};
db.onabort = function() {};
transaction.abort();
};
open_rq.onerror = function(e) {
assert_equals(open_rq, e.target);
assert_equals(e.target.result, undefined);
assert_equals(e.target.error.name, 'AbortError');
assert_equals(db.version, 0);
assert_equals(open_rq.transaction, null);
indexedDB.databases().then(dbs => {
// The database should be deleted.
assert_equals(dbs.length, 0);
t.done();
});
};
}, 'An abort() in the initial onupgradeneeded sets version back to 0');