Commit Graph

217 Commits

Author SHA1 Message Date
Andreas Kling
f6e755506d LibWeb: Check weak pointer liveness in Database::for_key_and_name()
The database map stores GC::Weak<Database> entries. When the GC
collects a Database, the weak pointer goes null but the map entry
remains. The old code dereferenced the weak pointer without checking
liveness, causing a null reference binding (UBSan).

Fix this by checking ptr() before dereferencing, and cleaning up the
stale map entry if the database was collected.
2026-03-08 11:39:41 +01:00
Zaggy1024
5eeac1b9dd LibWeb: Fire the "blocked" event at the IDB open request
...rather than at each of the open connections. These disagreed with the
spec steps written right above them.

The transaction-lifetime.any.html and idbdatabase_close.any.html tests
pass instead of timing out with these changes, so they've been imported.
2026-03-05 17:12:55 -06:00
Zaggy1024
5f114d730b LibWeb: Skip IDB request processing/completion when aborted 2026-03-05 17:12:55 -06:00
Zaggy1024
e8c1c2246e LibWeb: Autocommit IDB transactions with no requests during cleanup
If the current JS task has not made any requests, then nothing else
will trigger a commit like the spec desires, so we need to do it in the
microtask checkpoint.

Two WPT tests no longer time out with this change and have been
imported.
2026-03-05 17:12:55 -06:00
Zaggy1024
3f2bb43d47 LibWeb: Reset IDB transaction state to active after serialization error
If an error causes this to be left inactive, further requests will be
rejected on the transaction. This gives us a few subtest passes in
IndexedDB/key-conversion-exceptions and IndexedDB/keypath-exceptions
WPTs.

With this fixed, the cleanup loop can assert that the transactions'
states are all active before they are set inactive.
2026-03-05 17:12:55 -06:00
Zaggy1024
ea96072fee LibWeb: Implement IndexedDB transaction dependency ordering
This fixes the regression in idbindex_reverse_cursor.any.html, which
was actually exposing the underlying issue of ignoring conflicting
read/write transactions. Now, if a read/write transaction is in the
queue, no transactions can coincide with its requests' execution.
2026-03-05 17:12:55 -06:00
Zaggy1024
3c24a394c6 LibWeb: Refactor IndexedDB to handle requests serially
Previously, after one request was marked as processed, we would
synchronously queue another task to process the next request. This
would mean that two open requests on the same database could
interleave. This was especially problematic when one of the requests
would cause the database to upgrade, since the second open request
would begin processing before the upgradeneeded event fired, causing an
exception to be thrown in the second open().

The solution is to explicitly check for continuation conditions after
events have been fired in order to ensure that every step for the
request is completed before starting any further request processing.

For connection requests, the spec states:

> Open requests are processed in a connection queue. The queue contains
> all open requests associated with an storage key and a name. Requests
> added to the connection queue processed in order and each request
> must run to completion before the next request is processed. An open
> request may be blocked on other connections, requiring those
> connections to close before the request can complete and allow
> further requests to be processed.

For requests against a transaction, the spec states:

> Once the transaction has been started the implementation can begin
> executing the requests placed against the transaction. Requests must
> be executed in the order in which they were made against the
> transaction. Likewise, their results must be returned in the order
> the requests were placed against a specific transaction. There is no
> guarantee about the order that results from requests in different
> transactions are returned.

In the process of reworking it to use this approach, I've added a bunch
of new tests that cover things that our imported WPTs weren't checking.

With the fix for serializing connection requests, we can now fully
download the assets for the emscripten-compiled asm.js games in the
Humble Mozilla Bundle, particularly FTL: Faster Than Light.

There were no regressions in our test suite. One web platform test,
'idbindex_reverse_cursor.any.html', has one newly-failing subtest, but
the subtest was apparently only passing by chance due synchronous
execution of requests. A few web platform tests that were added in a
prior commit improved. The delete-request-queue.any.html test has
stopped crashing, and the close-in-upgrade-needed.any.html test has
stopped flaking, so they are both imported here as well.

Incidentally fixes #7512, for which a crash test has been added.
2026-03-05 17:12:55 -06:00
Zaggy1024
213edeccc2 LibWeb: Make Connection a private class in IDB's ConnectionQueueHandler 2026-03-05 17:12:55 -06:00
Zaggy1024
9ec949980a LibWeb: Don't set a transaction request's error until after JS finishes
Otherwise, the JS can't access the `result` property anymore.
2026-03-05 17:12:55 -06:00
Shannon Booth
46cd47753f LibWeb: Make more use of Value::{as,as_if,is} in LibWeb 2026-02-28 10:24:37 -05:00
Tim Ledbetter
84043cd82d LibWeb: Track deleted state on IndexedDb Index and ObjectStore
An `InvalidStateError` is now thrown when an attempt is made to
interact with an index or object store that has been deleted.
2026-02-24 17:37:04 +01:00
Sam Atkins
91526fcbcb LibWeb/IndexedDB: Store Key's key-array value as Ref not Root 2026-02-17 07:40:03 -05:00
Sam Atkins
598172d096 LibWeb/IndexedDB: Store Key's key-array value as a HeapVector
This reduces it to one GC::Root instead of one per element, but also
will make it easier to replace that Root with a Ref when needed in the
next commit.
2026-02-17 07:40:03 -05:00
Shannon Booth
4d64f21fa5 LibWeb: Give IDL exposed PlatformObjects an InterfaceName
By making use of the WEB_PLATFORM_OBJECT macro we can remove
the boilerplate of needing to add this override for every
serializable platform object so that we can check whether they
are exposed or not.
2026-02-14 20:22:40 +01:00
Andreas Kling
2ac363dcba LibGC: Only call finalize() on types that override finalize()
This dramatically cuts down on time spent in the GC's finalizer pass,
since most types don't override finalize().
2026-01-07 20:51:17 +01:00
Jelle Raaijmakers
d00571719f LibGC+LibJS+LibWeb: Add Visitor::visit(Optional<T>)
No functional changes.
2026-01-06 10:55:56 +01:00
Aliaksandr Kalenik
a3a00b0658 LibWeb/IndexedDB: Use GC::Weak for Database in "database registry"
This way databases are allowed to be GC'ed when there are no open
connections to them.

As a side effect, databases are no longer kept alive for the duration of
a browsing session. This will be addressed once IndexedDB gets proper
on-disk persistence. For now, avoiding memory leaks is the better
trade-off.

With this change the number of live `Window` objects in GC graph
captured by `test-web -j 1 --dump-gc-graph` goes down from 50 to 25.
2025-12-27 16:25:51 +01:00
Aliaksandr Kalenik
b291d75289 LibWeb/IndexedDB: Use GC::Weak in RequestList
By doing this we allow unclosed `IDBRequest`s to be GC-ed, instead of
keeping them alive forever in the `RequestList`.
2025-12-26 06:17:01 +01:00
Andreas Kling
f58d4dd324 LibWeb: Initialize IDBTransaction::m_state correctly
The spec says this should be initialized as "active", so let's do that.

Found by UBSAN when using 16 KiB GC heap blocks on Linux.
2025-12-19 20:21:07 -06:00
stelar7
684c543ddb LibWeb/IDB: Handle cursor iteration more correctly 2025-11-13 08:52:16 -05:00
stelar7
8fcba173e0 LibWeb/IDB: Correctly implement IDBRecord getters 2025-10-28 19:25:26 -04:00
stelar7
d3568d9467 LibWeb/IDB: Handle off-by-one error in IDBIndex::getAll 2025-10-28 11:50:01 +01:00
Luke Wilde
85e8d2ba38 LibWeb/IndexedDB: Prevent copying and moving of RequestList
RequestList cannot be copied or moved, because m_pending_request_queue
contains lambdas that store pointers to the original RequestList and
completion steps that we don't have a reference to.

Fixes a bunch of WPT regressions and imports the ones that work.
2025-10-23 14:42:45 +02:00
stelar7
d0bfb85c22 LibWeb/IDB: Mark request as errored if upgrade transaction is aborted 2025-10-23 14:26:54 +02:00
stelar7
98f91a3fcc LibWeb/IDB: Dont run wait callbacks as a database task 2025-10-18 13:50:01 +01:00
stelar7
ced862c460 LibWeb/IDB: Apply default cursor direction
IDBGetAllOptions is supposed to have a default value for direction.
When the value passed is not a potentially valid key range, we
need to default the direction argument, and not assume its set

Spec issue: https://github.com/w3c/IndexedDB/pull/478
2025-10-17 09:42:39 +02:00
stelar7
61185d98aa LibWeb/IDB: Adjust how negative numbers increment the key generator
Directly mapping a negative double to a u64 causes it to wrap around
to the max value. We work around this here by comparing as doubles,
and only incrementing the generator if the new value is greater

Fixes #6455
2025-10-14 10:26:28 +01:00
Luke Wilde
6d83fd92b6 LibWeb/IndexedDB: Add additional debug output for async operations 2025-10-08 17:25:29 +02:00
Luke Wilde
d87c2a55b0 LibWeb/IndexedDB: Remove spin_until from checking finished transactions 2025-10-08 17:25:29 +02:00
Luke Wilde
52b53e52fb LibWeb/IndexedDB: Remove spin_until from waiting for connection closure 2025-10-08 17:25:29 +02:00
Luke Wilde
e6dc52a52b LibWeb/IndexedDB: Remove spin_until from waiting for tasks to complete 2025-10-08 17:25:29 +02:00
Luke Wilde
5c69784ef9 LibWeb/IndexedDB: Remove spin_until from request processing 2025-10-08 17:25:29 +02:00
Julian Dominguez-Schatz
b9153f0ca1 LibWeb/IndexedDB: Allow queryOrOptions to be null in getAllKeys
This fixes a crash on initial load of the page http://demo.actualbudget.org.
Minimal repro of the issue (error in the console without this PR):

<script>
const r = indexedDB.open("t", 1);
r.onupgradeneeded = e => e.target.result.createObjectStore("s", { keyPath: "id" });
r.onsuccess = () => r.result.transaction("s", "readonly").objectStore("s").getAllKeys();
</script>
2025-10-04 20:49:53 +02:00
stelar7
fde5dc7491 LibWeb/IDB: Implement create_a_request_to_retrieve_multiple_items 2025-08-27 16:13:25 +02:00
stelar7
2557e85407 LibWeb/IDB: Implement IDBIndex::get_all_records 2025-08-27 16:13:25 +02:00
stelar7
bd25be9ed3 LibWeb/IDB: Update IDBIndex::get_all_keys to spec 2025-08-27 16:13:25 +02:00
stelar7
9c2d4973c3 LibWeb/IDB: Update IDBIndex::get_all to spec 2025-08-27 16:13:25 +02:00
stelar7
bac1c84241 LibWeb/IDB: Implement retrieve_multiple_items_from_an_index 2025-08-27 16:13:25 +02:00
stelar7
559b9dbd83 LibWeb/IDB: Implement IDBObjectStore::get_all_records 2025-08-27 16:13:25 +02:00
stelar7
6f756f7f6c LibWeb/IDB: Update IDBObjectStore::get_all_keys to spec 2025-08-27 16:13:25 +02:00
stelar7
ca34ecad33 LibWeb/IDB: Update IDBObjectStore::get_all to spec 2025-08-27 16:13:25 +02:00
stelar7
839ffd45f3 LibWeb/IDB: Implement retrieve_multiple_items_from_an_object_store 2025-08-27 16:13:25 +02:00
stelar7
752210aec1 LibWeb/IDB: Implement IDBRecord 2025-08-27 16:13:25 +02:00
stelar7
fe5d5639ef LibWeb/IDB: Move Records and give more descriptive names 2025-08-27 16:13:25 +02:00
stelar7
87af53a613 LibWeb/IDB: Implement is_a_potentially_valid_key_range 2025-08-27 16:13:25 +02:00
Andreas Kling
5e6b8b2785 LibWeb: Add missing visit of IDBRequest::m_source
Clang plugin bug: LadybirdBrowser/ladybird#5959
2025-08-22 19:29:29 +02:00
Andreas Kling
02f3002081 LibWeb: Add missing visit of IDBCursor::m_value
Clang plugin bug: LadybirdBrowser/ladybird#5958
2025-08-22 19:29:29 +02:00
stelar7
8addd5771f LibWeb/IDB: Add debug dump to Keys 2025-08-14 09:31:56 +01:00
stelar7
75054aeecd LibWeb/IDB: Allow null errors during abort 2025-08-14 09:31:56 +01:00
stelar7
474b748275 LibWeb/IDB: Check the request error instead of the transaction 2025-08-14 09:31:56 +01:00