Also, update the ready state when the progress event is fired.
Otherwise, we won't autoplay if 5 seconds of data aren't available in
on_metadata_parsed().
If a page contains multiple <link rel="icon"> elements, we would send
each of them to the UI process. We would then just use whichever was
sent last as the favicon in the UI.
We now only send the favicon that was chosen for the document. This
will either be the largest icon decoded from a link element, or the
singular fallback icon.
We currently pick the first favicon in reverse tree order. But we are
encouraged by the spec to pick the most appropraite icon. We now
consider the size of the decoded icon, and choose the largest.
Problem: Select All (Ctrl+A or the context menu) followed by Ctrl+C
unexpectedly copies text from elements with user-select:none — breaking
compat with Chrome and Firefox, which both exclude user-select:none
content from the clipboard.
Cause: Navigable::selected_text() walks the selection range via
visible_text_in_range() and concatenates each text node’s data. The walk
filters out nodes without a layout, but not nodes whose used value of
user-select is ‘none’.
Fix: Add a user-select check at each visible_text_in_range() walk point.
The Selection range itself is left unchanged. Selection.toString() still
returns the full text per spec — but the clipboard-extraction path now
excludes user-select: none subtrees, per spec
Previously, `text_path() used the glyph outline bounding box width to
compute text alignment offsets and maxWidth scaling. The bounding box
only covers visible glyph outlines, excluding the advance of spaces and
glyph side bearings. This caused text with `textAlign` "end", "right",
or "center" to be mispositioned. We now use the sum of glyph run
advance widths instead.
By default, `rustfmt` persists the import granularity. In practice, most
Rust code has import granularity "Module" due to LSP's actions.
"Item" gets rid of import groupings and achieves cleaner diffs and
better conflict resolution. Better greppability is a positive side
effect.
Note: it's an unstable rustfmt feature. `cargo +nightly fmt` must be
used instead of `cargo fmt`.
...and avoid telling the media element about it unless the track is
actually associated. The media element should set its state later when
it queries the status upon metadata parsing.
CompositorState treats presence in m_contexts as the lifetime state
for a compositor context. create_context() creates the entry and
destroy_context() removes it, so ContextState::is_registered duplicated
the map membership invariant.
The top-level-traversable bit was also duplicate information. The
only compositor use was backing-store padding while a window resize is
in progress, and page-presenting contexts are already identified by
PagePresentationRegistration::Yes. Normalize resize-in-progress to No
for non-page-presenting contexts, then remove the flag from
CompositorState, the backing-store API, and the compositor IPC boundary.
Only give initial and empty loaded about:blank documents the implicit
light/dark supported schemes when they belong to a top-level navigable.
Embedded empty documents should not negotiate the page preferred dark
scheme while their embedding element remains light, since that forces an
opaque dark iframe canvas.
Add text coverage for both initial and navigated embedded about:blank
documents under a dark preferred scheme.
Opt empty about:blank documents into both light and dark supported
color schemes. This covers both navigation-created about:blank documents
and the initial about:blank document created with a browsing context, so
dark mode can choose the dark Canvas color before page content arrives.
Display lists owned the accumulated visual context tree through a
ref-counted pointer. That tied visual-context state to display-list
lifetime and made compositor updates treat the two as one unit, even
though AVC trees need to become independently updateable compositor
state.
Make accumulated visual context trees plain versioned values, have each
display list store the compatible tree version, and pass the matching
tree alongside display-list updates and replay calls. Replay verifies
that the provided tree matches the display list before executing it.
This prepares the compositor for receiving AVC tree updates separately
from display-list updates: it now accepts the tree as a separate update
parameter, stores it next to the display list, and uses that stored tree
for replay and async-scroll hit testing. Nested display-list resources
carry their own tree snapshots for the same version check.
Stop HTMLImageElement animation timers when their document becomes
hidden, and resume them only if visibility was what paused them. This
keeps inactive tabs from advancing animated image frames and requesting
more decoded frames from ImageDecoder.
Also avoid starting newly loaded animated images while their document is
hidden, so images loaded in background tabs wait until the page becomes
visible before animating.
Trackpad pinches applied directly as visual viewport zoom, so pages
could not observe the gesture or cancel the browser default. Canvas
apps such as maps expect the ctrl-wheel path instead.
An HTMLImageElement can be adopted across documents while an image
update is still pending. In that case the element's wrapper realm can
still be the old iframe realm, but the image request must be created and
fetched using the element's current node document.
Using the old iframe realm associates the request with the removed
iframe's document-owned image request cache, so the adopted image can
fail to complete in the parent document. Use document().realm() when
creating/updating/fetching image requests so adopted images continue
loading in their new document.
Add a regression for an image created in an iframe, then adopted into
the parent after the iframe is removed.
Chromium and Webkit do not fire a load event for the test, but Firefox
does. All load the image, where we previously did not.
See: https://github.com/whatwg/html/issues/8492
This lays the groundwork to allow shared workers, nested workers (i.e.
workers owned by workers) and service workers to function independently
of WebContent.
When a label's activation behavior runs for a form-associated custom
element whose shadow root has delegatesFocus: true, the shadow host is
not itself a focusable area. The old is_focusable() check prevented
run_focusing_steps from ever being called, which means
get_focusable_area never got a chance to descend into the shadow root
via focus_delegate.
Fixes WPT custom-elements/form-associated/label-delegatesFocus.html.
Treat a missing animation frame callback driver as an empty map when
canceling a frame. This keeps media controls finalization from
allocating while GC is collecting unreachable media elements.
Cover this with a media controls GC text test.
Reuse the existing display-list invalidation signal from viewport
updates to distinguish ordinary resizes from DPR and zoom changes.
The latter still need full style invalidation because snapped border
and outline widths depend on device_pixels_per_css_pixel even when
style does not otherwise depend on viewport metrics.
Add a text test for changing devicePixelRatio with subpixel border
and outline widths.
Use the viewport metric dependency flags to restyle only elements whose
computed values can change after a viewport resize. Descendants that
inherit changed values are reached through the existing inherited-style
update path.
Keep targeted style reads correct by treating pending media query
evaluation as style dirtiness. Seed the style computer with the latest
viewport before resolving pending animated style, so viewport-unit
keyframes do not use stale metrics.
Share pseudo-element recomputation with inherited-style updates, so
pseudos stay current when their originating element changes only via
inherited values.
Schedule animated style updates when inherited style recomputation can
affect existing animations.
Add viewport resize coverage for media queries, inherited font metrics,
monospace font-size recascade, line-height percentages, font-relative
and pending viewport-unit animations, inherited pseudo-elements, direct
pseudo viewport dependencies, and canvas currentColor reads.
CompositorHost still accepted page presentation metadata so the old
in-process compositor path could register new contexts while
constructing the LibWeb handle. With the compositor process as the only
backend, context allocation and service registration already happen
before LibWeb creates the handle.
Make CompositorHost::create_context() take only the allocated context id
and remove the private register_context() hook. Navigable no longer
computes page metadata for the host, and WebContent no longer carries a
erification-only registration override.
The compositor thread used to need a way for LibWeb to postpone
adopting async scroll offsets when the thread had already presented
newer state. The compositor process implementation never defers this
path, so the hook became a hardcoded false result after the thread code
was removed.
Remove the host callback and let Navigable always consume the pending
async scroll updates from the compositor process before running
rendering-update observers.
Preserve leading BOMs when parsing already-decoded HTML strings, since
those strings do not go through the encoded byte decoder path.
Decoded markup from JS strings can also contain WTF-8 for lone surrogate
code units. Keep the common scalar UTF-8 path to a single validation and
copy, but replace surrogates before handing bytes to the Rust tokenizer.
Add text coverage for DOMParser and innerHTML string parsing, including
leading BOMs, text and attributes, lone high and low surrogates, and a
valid surrogate pair.
Keep decoded ImageBitmap transfer bytes in a stable heap object before
handing their pixel pointer to Gfx::Bitmap. GCC can evaluate the lambda
capture that moves the ByteBuffer before the data() argument. That can
leave the bitmap backed by moved-from storage.
Taking the pointer from heap-owned storage avoids that dependency. This
does not copy pixel data. The existing crash test covers the offscreen
canvas path.
The browser previously treated the out-of-process Compositor as fatal.
Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.
Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.
Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.
Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
Do not skip fully transparent canvas fill and stroke styles when the
current compositing operator can still affect the destination bitmap.
TradingView uses transparent copy fills while repainting its chart
canvases, and skipping those draws left old translucent chart pixels in
place so later source-over draws accumulated on top.
Add text coverage for transparent copy replacing an existing translucent
pixel before another translucent draw.
Represent WebIDL C++ types with a single CppType model that tracks
nullability, optional presence, and contained storage.
GC-like values now use GC::Ref/GC::Ptr directly, while containers choose
"plain", "Root", or "Conservative" container types depending on what
they contain. For example, sequence<Element> becomes a RootVector of
GC::Ref values, while sequence<SomeDictionary> becomes a
ConservativeVector only when the dictionary contains GC-like values.
This moves the generated bindings away from wrapping GC values in
GC::Root by default.
This has broad fallout as the types passed to interfaces for GC
objects changes almost fully across the board.
When an image source changes before a queued decode() job can attach
fetch callbacks, the current request can still be unavailable and have
no shared resource request. Treat that as the spec's current request
changed case instead of asserting while adding callbacks.
Add text coverage for changing an image source immediately after
calling decode(), matching the WPT image-decode-path-changes crash.
Follow the script execution model by checking the preparation-time
document before waiting for scripts to run in the node document. An
async script can be adopted into a freshly-created document while its
fetch is still pending, and that script must return without executing
when the fetch completes.
Also unblock render-blocking elements when removal disconnects them
from their browsing context, matching the render-blocking mechanism.
Add a crash test for an adopted async script whose fetch completes
after adoption.
Leave the resolved object null when parsing the pseudo-element argument
fails, as required by CSSOM. The view-transition update hook ran
after that step and still unwrapped the parse result, crashing on
unsupported pseudos such as ::scroll-marker-group.
Only run the view-transition hook once parsing succeeds. Add a crash
test covering unsupported scroll pseudo-elements passed to
getComputedStyle().
This ensures that we're only beginning a remote fetch when the document
is active, which the observer callbacks already assume. Combined with
the next commit, this will help ensure that the fix preventing the
VERIFY in the document_became_active callback from being hit works.
Once the compositor lives in another process, the helper has to know a
context's id before any per-context message about it can be dispatched.
Today the id is minted inside CompositorHost::create_context and
returned to the caller, so it cannot be named ahead of time.
Untangle allocation from creation so Browser can mint the id and hand it
down through the call chain into both the local host and the future
remote host with no special case. The id helpers also move into a public
header so LibWeb, WebContent, and the upcoming service share one
encoding for the page-presenting bit. Behavior is preserved; the
in-process compositor still owns rendering.
Follow the spec reuse of the initial same-origin about:blank window for
a browsing context's first real navigation. This fixes a crash in
promise-job-entry-different-function-realm.html by preserving the
correct iframe realm.
However, reusing the initial about:blank Window means
create-and-initialize can associate that Window with the pending
Document before session history activation has made the Document active.
Treating a browsing context's active document as its active Window's
associated Document therefore exposes the pending Document too early.
To fix this, add an explicit active document slot to BrowsingContext and
update it when a Document is made active.
A similar fix was attempted in 7fc7263a4d,
but that version still queued navigation tasks through the reused active
Window, tagging them with the pending Document before it was active.
This caused parser-created iframe loads to hang in encoding WPTs. This
commit instead queues those navigation-internal tasks against the
navigable's currently active Document.
The newly added iframe-initial-load-chunked-body.html mimics the same
type of failure seen by the WPT regressions mentioned above.
When image data becomes available, intrinsic dimensions can change, but
that does not require relayout for image elements whose computed width,
height, and min/max constraints are independent of intrinsic sizing. In
that case, invalidate paint and intrinsic-size caches instead of marking
layout dirty.
Keep the conservative relayout path for auto, percentage,
calc-percentage, and intrinsic sizing constraints, since decoded image
dimensions can affect used size in indefinite contexts. Query image
availability while painting so an existing paintable can switch from alt
text to image content without relayout.
Add text coverage that waits for image load events and checks auto,
percentage, calc-percentage, intrinsic keyword, min/max percentage, and
fixed-size cases without relying on timeouts.
Remember the last mouse or wheel position seen by the event handler.
Schedule a hover refresh once async scrolling goes idle.
This lets hover state and boundary events follow content under a
stationary pointer after scrolling has stopped.
Add a text test that keeps hover on the old target while scrolling is
active. It then checks that hover moves after the idle update without
extra mousemove or pointermove events.
Problem: An iframe whose content changes while it (or an ancestor)
has visibility:hidden isn’t painted once it becomes visible again.
The stale previous frame stays on screen until an unrelated
repaint (e.g., window resize) happens to occur.
Cause: set_needs_repaint() returns early for any document inside an
iframe with a visibility:hidden ancestor — discarding the request
entirely. The navigable’s needs_repaint flag is never set. Nothing
sets it again when the iframe becomes visible — so the rendering
loop keeps skipping it — and its display list stays stale.
Fix: Stop discarding the request in set_needs_repaint(). Instead,
skip painting hidden navigables in the rendering loop — while
leaving needs_repaint set. Once an ancestor iframe becomes
visible, the still-set flag makes the rendering loop paint the
navigable on the next frame.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/9305