This fixes a timeout in WPT's abort-in-initial-upgradeneeded.any.html
test. The timeout was a rare one, caused by idbfactory_open.any.html
leaving the second connection in the final test open, since support.js
only tracks the connection created by the first createdb call. By
leaving the connection open, the harness's deleteDatabase() call would
never take effect. This in turn meant that the upgradeneeded test would
fail an assertion on the number of databases. That assertion was also
uncaught by the harness, turning it into a timeout instead of a fail.
By closing the connections when a document is destroyed, we can ensure
that the connection doesn't leak over to the next test and cause the
exception to be thrown.
Cleanup following the per-Navigable rasterization split: since each
Navigable now rasterizes its own display list independently, the HashMap
keyed on display list was always populated with exactly one entry. Pass
the ScrollStateSnapshot directly through the display list player and
rendering thread instead.
Previously, iframes were rasterized synchronously as nested display
lists inside their parent's display list: the parent's paint walk called
record_display_list() on each hosted iframe document and emitted a
PaintNestedDisplayList command that the player would recurse into. Only
the top-level traversable's RenderingThread was ever active, even though
every Navigable already owned one.
The motivation for splitting this apart:
- Work in the outer document no longer has to be re-recorded when only
an iframe changes. The parent's cached display list now references the
iframe's rasterized output live via an ExternalContentSource, so an
iframe invalidation just needs the parent's display list replayed, not
re-recorded.
- Each iframe now has a self-contained rasterization pipeline, which is
prep work for moving iframes into separate sandboxed processes.
Prep for rasterizing each Navigable independently, where children must
paint before their parents — the event loop needs to walk documents in
an order where every child comes after its container. The HTML spec
already mandates such an order for the "docs" list: each document
appears after its container, with siblings in shadow-including tree
order.
Maintain m_documents in that sorted order, re-sorting lazily when a
document is registered or its navigable is reassigned.
When a dedicated worker has an unhandled exception, we should propogate
that exception to be fired at the parent global. Fixes a timeout
in the included WPT test.
The proposal has not seemed to progress for a while, and there is
a open issue about module imports which breaks HTML integration.
While we could probably make an AD-HOC change to fix that issue,
it is deep enough in the JS engine that I am not particularly
keen on making that change.
Until other browsers begin to make positive signals about shipping
ShadowRealms, let's remove our implementation for now.
There is still some cleanup that can be done with regard to the
HTML integration, but there are a few more items that need to be
untangled there.
We should not throw exception types that are not dictated by the spec.
This is observable. This was preventing login on strava.com from
working.
Let's mark this feature as experimental as well, since it is just a stub
and was only added for a WPT score increase.
The spec's "not completely loaded" check in navigate_an_iframe_or_frame
was applied to all navigations, including attribute-driven src changes.
This caused navigations triggered before the previous page's load event
(e.g. via postMessage during parsing) to replace the history entry
instead of pushing a new one.
Restrict the check to initial insertion only. For subsequent src
attribute changes, always use "auto" so the navigate algorithm's own
logic (navigation_must_be_a_replace) decides the history handling.
Previously, we had to recompute targetStep in the middle of history
step application because our session history traversal queue (SHTQ)
implementation was broken and didn't provide actual task serialization.
This meant the step could change while we were waiting for tasks to
complete.
Now that the SHTQ correctly serializes tasks, the step should no longer
change mid-application. Replace the recomputation with a VERIFY() assert
to enforce this invariant.
Per https://webidl.spec.whatwg.org/#interface-prototype-object any
global platform object should reject prototype changes (besides
from ShadowRealmGlobalScope), and interface prototype objects on
global prototype chains must be immutable.
We already handled parts of this on the globals themselves, but not
the full chain.
Also align some spec comments to the latest WebIDL spec.
Blink, WebKit, and Gecko round the border-box geometry that feeds
offsetWidth and offsetHeight instead of truncating it. Do the same
in HTMLElement so these CSSOM View APIs match interop behavior for
fractional sizes.
This also updates the two local text expectations that changed
because they observe the rounded values.
WebContent process keeps session history entries for pages we have
navigated away from. Before this change, those entries could prevent GC
objects (e.g. PolicyContainer and its CSP PolicyList) from being
collected, since the GC-allocated SHE/DocumentState held live GC::Ref
pointers into the heap.
By making both classes RefCounted and storing SerializedPolicyContainer
instead of a live PolicyContainer, history entries no longer keep alive
any GC objects. This eliminates the leak and is also a step toward
moving the session history entry tree to the UI process.
Remove m_original_source_browsing_context, m_browsing_context_name, and
m_policy_container along with their getters and setters, as they have no
callers outside the class itself.
This also adds a missing include for JS::call in WebDriver/JSON.cpp,
which was previously provided transitively through the removed headers.
This cannot happen inside the Make Active algorithm, since that gets
called during document creation, which commonly happens before the
document's navigable is created.
Aligns us with a recent spec change and rids us of some AD_HOC
behavior.
Now that Navigable directly owns its active document (m_active_document)
we can have Navigable maintain a back-pointer on Document instead of
using the old cache-with-validation pattern that fell back to a linear
scan of all navigables via navigable_with_active_document().
Previously, the active document's lifecycle was bound to
SessionHistoryEntry via DocumentState. The ownership chain was:
Navigable → SessionHistoryEntry → DocumentState → Document
This made it impossible to move SessionHistoryEntry to the UI process
(which cannot own DOM::Document). This commit decouples the two by
giving Navigable a direct m_active_document field that serves as the
authoritative source for active_document().
- Navigable owns m_active_document directly; active_document() reads
from it instead of going through the active session history entry.
- DocumentState no longer holds a Document pointer. Instead, it stores
a document_id for "same document?" checks. Same-document navigations
share a DocumentState and thus the same document_id, while
cross-document navigations create a new DocumentState with a new ID.
- A pending_document parameter is threaded through
finalize_a_cross_document_navigation → apply_the_push_or_replace →
apply_the_history_step so the newly created document reaches
activation without being stored on DocumentState.
- For traversal, the population output delivers the document.
A resolved_document is computed per continuation from either the
pending document, the population output, or the current active
document (for same-document traversals).
Audio output on macOS was consuming Core Audio resources until the
PlaybackStream creation took well over the timeout for some tests.
This was observed in media-source-buffered.html, where it would time
out due to the long-running callback on the main thread to create the
PlaybackStream for AudioMixingSink.
However, the AudioUnit init should definitely not be blocking the main
thread, so I've added a FIXME there.
If we fire the error event synchronously within the on_error callback,
then we'll end up destroying the PlaybackManager inside its own
callback and crash. Instead, queue a task to execute the error steps.
This could happen with or without MSE, but I observed it occurring on
YouTube with MSE when we hit a decoding error, since they immediately
try another source when an error is reported.
The segments are parsed for the SourceBufferProcessor by the
WebMByteStreamParser. It parses the initialization segment to update
its internal set of tracks, then SourceBufferProcessor/SourceBuffer set
them up for playback. When a media segment is received, it also parses
as much of it as is available, returning all the coded frames found so
far. SourceBufferProcessor then tells TrackBufferDemuxer to remove any
overlapping frames and insert the new ones.
TrackBufferDemuxer implements the Demuxer interface in terms of the
coded frame store maintained by the SourceBufferProcessor. It returns
the frames in decode order when requested by a data provider. When a
is needed, it finds the keyframe prior to the target timestamp, and
checks that there are no gaps in data up to the target timestamp. If
there are any gaps, it blocks until the gaps are gone.
These steps are the best definition we have for how the ready state
should be set, and it seems to be reasonable to apply to plain file
playback as well.
Since our file demuxers are hardcoded to return the entire duration as
buffered, the ready state immediately progresses to HAVE_CURRENT_DATA.
This will probably change once we can check the demuxers for buffered
data.
Removing a display risks triggering callbacks on the playback manager
that may cause a recursive GC. This wasn't having any effect since the
playback manager became an OwnPtr.
...giving tracks a kind attribute, and renaming name to label.
Demuxers will need to determine the kind attribute, since the spec for
sourcing tracks requires us to select based on info we don't expose.
The Crash/HTML/image-load-after-iframe-navigated.html test was
crashing on CI with a null pointer dereference at
NavigableContainer.cpp:178. The crash occurs because content_document()
dereferences the return value of active_document() without checking for
null.
When an iframe is navigated, Document::destroy() sets the old
document state's document to null via set_document(nullptr), but
the navigable (m_content_navigable) remains non-null since it is
reused for the new navigation. During the window between the old
document being destroyed and the new document being set,
active_document() returns null. If JS code accesses
iframe.contentDocument during this window (e.g. via a timer
callback), content_document() would dereference the null pointer.
Replace the blocking spin_processing_tasks_with_source_until calls
in apply_the_history_step_after_unload_check() with an event-driven
ApplyHistoryStepState GC cell that tracks 5 phases, following the
same pattern used by CheckUnloadingCanceledState.
Key changes:
- Introduce ApplyHistoryStepState with phases:
WaitingForDocumentPopulation, ProcessingContinuations,
WaitingForChangeJobCompletion, WaitingForNonChangingJobs and Completed
- Add on_complete callbacks to apply_the_push_or_replace_history_step,
finalize_a_same_document_navigation,
finalize_a_cross_document_navigation, and
update_for_navigable_creation_or_destruction
- Remove spin_until from Document::open()
- Use null-document tasks for non-changing navigable updates and
document unload/destroy to avoid stuck tasks when documents become
non-fully-active
- Defer completely_finish_loading when document has no navigable yet,
and re-trigger post-load steps in activate_history_entry for documents
that completed loading before activation
Co-Authored-By: Shannon Booth <shannon@serenityos.org>
The 100ms debounce timer on textarea input events causes character
loss when JavaScript restores a previously captured value via
requestAnimationFrame. The text node mutation happens immediately
during input processing, but the input DOM event is delayed,
creating a window where stale rAF callbacks overwrite new input.
Remove the debounce timer and fire the input event immediately
via queue_an_element_task, matching HTMLInputElement behavior.
The spec notes this delay is optional ("User agents may wait").
Fixes#7793.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement the forwarded part names step of the CSS Shadow Parts
spec in ShadowRoot::calculate_part_element_map(). When a shadow
host has an exportparts attribute, the inner shadow root's part
element map is consulted and matching parts are added to the
outer shadow root's map under the exported name.
This supports both shorthand same-name forwarding (exportparts=
"foo") and renamed forwarding (exportparts="foo: bar"), and
chains transitively through nested shadow boundaries via
recursive part_element_map() calls.
Fixes 4 WPT tests: simple-forward, simple-forward-shorthand,
double-forward, and precedence-part-vs-part.
When <br> element style display is not 'none', it must be an inline box.
Add a condition to ensure <br> is treated as an inline element
instead of a table, flex, or grid in that case,
preventing program from crashing.
Fixes#5568