These should persist for the duration of the program, at least until we
have persistent storage to restore from if a database needs to be used
again.
This fixes a flake in indexeddb-queued-delete-after-open that turns
into a consistent failure (or an assertion failure in GC::Weak in
debug builds) when running the test with the -g flag.
cleanup_indexed_database_transactions() is called on every event
loop spin. It was calling associated_connections() which allocates
a GC::HeapVector every time, creating massive GC pressure on
JS-heavy sites (217K allocations observed on x.com).
Switch the hot path to use a GC::RootVector instead, which lives
on the stack and avoids GC heap allocation while still being
visible to the garbage collector.
Rename the existing methods to make the return type explicit:
- associated_connections_as_heap_vector() for callers that
capture the result in GC::Function lambdas
- associated_connections_as_root_vector() for callers that
just iterate safely within a single scope
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.
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.
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.
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.
C++ will jovially select the implicit conversion operator, even if it's
complete bogus, such as for unknown-size types or non-destructible
types. Therefore, all such conversions (which incur a copy) must
(unfortunately) be explicit so that non-copyable types continue to work.
NOTE: We make an exception for trivially copyable types, since they
are, well, trivially copyable.
Co-authored-by: kleines Filmröllchen <filmroellchen@serenityos.org>
Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:
* JS::NonnullGCPtr -> GC::Ref
* JS::GCPtr -> GC::Ptr
* JS::HeapFunction -> GC::Function
* JS::CellImpl -> GC::Cell
* JS::Handle -> GC::Root
The main motivation behind this is to remove JS specifics of the Realm
from the implementation of the Heap.
As a side effect of this change, this is a bit nicer to read than the
previous approach, and in my opinion, also makes it a little more clear
that this method is specific to a JavaScript Realm.