Commit graph

126 commits

Author SHA1 Message Date
Andreas Kling
3240cd536c LibWeb: Prevent navigation on destroyed navigables
When an iframe is removed before its post-connection session history
steps finish processing, the queued steps still run and call
navigate() on the now-destroyed navigable. This calls
set_delaying_load_events(true), creating a DocumentLoadEventDelayer
on the parent document. Since the navigable is destroyed, no
finalize step ever runs to clear the delayer, permanently blocking
the parent document's load event.

Fix this by checking has_been_destroyed() at the start of
begin_navigation() and bailing out early.
2026-02-10 21:19:35 +01:00
Shannon Booth
1da77d2796 LibWeb/HTML: Simplify checking if navigation ID is no longer the same 2026-02-05 08:38:33 +01:00
Aliaksandr Kalenik
42544c1ff5 LibWeb: Rebuild visual contexts after visual viewport scroll
When the visual viewport scrolls (e.g. panning while zoomed in), the
transform matrix baked into the AccumulatedVisualContext tree becomes
stale. Previously only set_needs_display(InvalidateDisplayList::No) was
called, which re-rendered with the old transform — making hit testing
and painting incorrect after visual viewport panning.
2026-01-31 19:20:09 +01:00
Jelle Raaijmakers
887ed85877 LibWeb: Return early during viewport scrolling if nothing changes
I noticed that when performing a smooth scroll up or down, we would
repeatedly enter `Navigable::perform_a_scroll_of_the_viewport()` when
the top or bottom (respectively) of the page was reached. Optimize this
case by returning early when we've reached the intended target scroll
position and we're not performing any vertical or horizontal scrolling.
2026-01-29 08:56:21 +01:00
Aliaksandr Kalenik
a86f318a9b LibWeb: Move rendering backpressure from main thread to RenderingThread
In preparation for handling input events on the rendering thread, move
backpressure management to RenderingThread. The rendering thread needs
to manage this independently without querying the main thread.

Previously, the main thread would block when the UI process hadn't yet
released the backing surface. Now, the main thread can continue
producing display lists while the UI process is busy, allowing more work
to happen in parallel. When rasterization is slow and display lists are
produced faster than they can be consumed, presentation requests are
naturally coalesced using a flag-based approach -
multiple present_frame() calls simply update the pending state,
resulting in a single rasterization with the latest display list.
2026-01-26 19:05:34 +01:00
Shannon Booth
3e0ea4f62e LibWeb/HTML: Check ongoing navigation before javascript: URL navigation
See: 976d272

This fixes a timeout in the included test. In order for the
test to run properly in our test harness it is modified slightly
(as we are loading the HTML from a file:// URL).
2026-01-26 18:46:54 +01:00
Aliaksandr Kalenik
b69ec8757f LibWeb: Store presentation callback in RenderingThread
This is preparation for future work where the rendering thread will
initiate rasterization independently and notify the UI process without
requiring coordination with the main thread.
2026-01-26 17:01:48 +01:00
Aliaksandr Kalenik
516fb5f2fe LibWeb: Make RenderingThread own display list and backing stores
This change prepares for a future where the rendering thread handles
input events directly, allowing it to trigger repainting without
waiting for the main thread. To support this, the compositor needs to
own the display list, scroll state, and backing stores rather than
receiving them per-frame from the main thread.
2026-01-26 14:53:08 +01:00
Andreas Kling
37bdcc3488 LibWeb: Support MIME type sniffing for streaming HTTP responses
Previously, when loading a document, we would try to sniff the MIME
type by reading from the response body's source. However, for streaming
HTTP responses, the body source is Empty (the data comes through the
stream instead), so we had no bytes to sniff.

This caused pages like hypr.land (which sends no Content-Type header)
to be misidentified as plain text instead of HTML, since the MIME
sniffing algorithm would receive zero bytes and fall back to the
default type.

The fix captures the first bytes of the response body during fetch,
storing them on the Body object. These bytes are the "resource header"
defined by the MIME Sniffing spec - up to 1445 bytes, which is enough
to identify any MIME type the spec can detect.

Since bytes may arrive asynchronously during streaming, we use a
callback mechanism: if bytes aren't ready yet when load_document()
needs them, it registers a callback that fires once enough bytes have
been captured (or the stream ends).

The flow is:
1. FetchedDataReceiver receives network bytes, buffers them
2. When Body is created, buffered bytes are flushed to Body's sniff
   buffer, and subsequent bytes are appended as they arrive
3. Before calling load_document(), Navigable waits for sniff bytes
4. load_document() passes the bytes to MimeSniff::Resource::sniff()
2026-01-24 15:21:26 +01:00
Aliaksandr Kalenik
f63674e92d LibWeb: Fix scroll regression when pinch-to-zoom is applied
When scrolling with a visual viewport offset (from pinch-to-zoom),
scroll_viewport_by_delta() was passing m_viewport_scroll_offset + delta
to perform_a_scroll_of_the_viewport(). However, that function calculates
the scroll delta as `position - page_top()`, where page_top() includes
the visual viewport offset. This caused the effective scroll delta to be
reduced by the visual offset amount.

Fix by using the current page position (which includes the visual
offset) as the base for the delta calculation.

Regression from 0a57e1e8ac.
2026-01-23 17:52:50 +01:00
Aliaksandr Kalenik
8d47c98ed3 LibWeb: Cache scroll state snapshot in ViewportPaintable
Cache the scroll state snapshot in ViewportPaintable when
refresh_scroll_state() is called.

The upcoming AccumulatedVisualContext integration requires access to
the scroll state snapshot during hit testing to transform screen
coordinates through scroll frames. Without caching, each hit test would
allocate a new snapshot (a Vector<Entry>), causing many temporary
allocations during mouse movement. Caching the snapshot eliminates this
overhead.
2026-01-15 19:50:53 +01:00
Tim Ledbetter
1022ec3b4a LibWeb: Set referrer policy on navigation fetch requests 2026-01-12 12:47:40 +01:00
Sam Atkins
8a0ba904b9 LibWeb/HTML: Return Promises from Window scroll methods
A version of this was added in a610639119
and reverted in 70671b4c11. The bugs
there (confusing scroll-to-position and scroll-by-delta, and not having
an execution context in some cases) have been fixed in this version.
2026-01-08 14:50:09 +00:00
Sam Atkins
0a57e1e8ac LibWeb: Clarify some scrolling-related code
A lot of our scrolling code is quite old, and doesn't match the spec,
but does use some similar names. This is quite confusing. In particular
`perform_scroll_of_viewport()` is not the same as the spec algorithm.
That algorithm is actually almost implemented in
`scroll_viewport_by_delta()`.

To clarify things, this commit makes a few changes:
- Rename perform_scroll_of_viewport() to
  perform_scroll_of_viewport_scrolling_box(). This is a better match
  for how we use this method, even if it's not actually a match for the
  algorithm. (:yakbait:)
- Move `scroll_viewport_by_delta()`'s code into a new
  `perform_a_scroll_of_the_viewport()` method, and make it take a
  position like it should. `scroll_viewport_by_delta()` now calls it
  with a calculated position.

I've avoided reusing the original `perform_scroll_of_viewport()` name to
avoid accidents.
2026-01-08 14:50:09 +00:00
Jonathan Gamble
7385569a02 LibWeb: Selection toString focused text control delegation
Allows selected text in form controls to be copied to clipboard.
2026-01-02 18:40:05 +01:00
Aliaksandr Kalenik
9a2931527a LibWeb: Use ConservativeVector in get_session_history_entries()
This way we ensure doc states traversal queue elements are visited.
2025-12-27 18:40:21 +01:00
Aliaksandr Kalenik
38af5d623c LibWeb: Avoid shifting vector elements in get_session_history_entries()
This function essentially performs a BFS traversal over document states.
With this change, we let `doc_states` grow instead of removing traversed
states, avoiding shifting elements on every iteration.

This reduces `./test-web -j 1` from ~7m to ~5m on my machine.
2025-12-27 18:40:21 +01:00
Aliaksandr Kalenik
f6a7df78e7 LibWeb: Add missing GC visits for XHR::FormDataEntry
3a6782689 fix up that changes `Vector<XHR::FormDataEntry>` to
`GC::ConservativeVector<XHR::FormDataEntry>`.
2025-12-26 19:48:46 +01:00
Tim Ledbetter
70671b4c11 Revert "LibWeb/HTML: Return Promises from Window scroll methods"
This reverts commit a610639119.
2025-12-26 19:33:51 +01:00
Aliaksandr Kalenik
8af78cff30 LibWeb: Skip scroll promise allocation in mouse event handling
Fixes crashing introduced in a610639 when `scroll_viewport_by_delta()`
is called from `EventHandler::handle_mousewheel()` and there's no
running execution context to grab current realm from to allocate a
promise.
2025-12-23 17:36:48 +01:00
Sam Atkins
a610639119 LibWeb/HTML: Return Promises from Window scroll methods
Corresponds to part of:
c548a9a1d4
2025-12-23 14:24:28 +01:00
Sam Atkins
cb0c428b3a LibWeb/DOM: Use a single scroll queue for all events
Corresponds to:
36f05864a6
302490c80c
https://github.com/w3c/csswg-drafts/pull/13238
https://github.com/w3c/csswg-drafts/pull/13239

The latter two are my own corrections which haven't been merged yet.
2025-12-19 12:09:19 -06:00
Psychpsyo
3a4f7eeb4a LibWeb: Prevent scrolling viewport with overflow:hidden 2025-12-15 09:47:25 +00:00
Sam Atkins
43bd5342c5 LibWeb/HTML: Create a temporary execution context to abort navigation
Stops this WPT test from crashing:
navigation-api/ordering-and-transition/transition-to.html

...it now times out instead, so more work is needed before importing.
2025-12-05 09:20:02 +00:00
Sam Atkins
c8990697d1 LibWeb: Add FIXME for moving "stop parsing" step for error documents
Corresponds to:
48cd393d1e

Actually doing so was causing crashes and other issues, so I'll leave it
as a FIXME for later.
2025-12-01 11:07:16 +00:00
Timothy Flynn
9375660b64 LibHTTP+LibWeb+RequestServer: Move Fetch's HTTP header infra to LibHTTP
The end goal here is for LibHTTP to be the home of our RFC 9111 (HTTP
caching) implementation. We currently have one implementation in LibWeb
for our in-memory cache and another in RequestServer for our disk cache.

The implementations both largely revolve around interacting with HTTP
headers. But in LibWeb, we are using Fetch's header infra, and in RS we
are using are home-grown header infra from LibHTTP.

So to give these a common denominator, this patch replaces the LibHTTP
implementation with Fetch's infra. Our existing LibHTTP implementation
was not particularly compliant with any spec, so this at least gives us
a standards-based common implementation.

This migration also required moving a handful of other Fetch AOs over
to LibHTTP. (It turns out these AOs were all from the Fetch/Infra/HTTP
folder, so perhaps it makes sense for LibHTTP to be the implementation
of that entire set of facilities.)
2025-11-27 14:57:29 +01:00
Timothy Flynn
f675cfe90f LibWeb: Store HTTP methods and headers as ByteString
The spec declares these as a byte sequence, which we then implemented as
a ByteBuffer. This has become pretty awkward to deal with, as evidenced
by the plethora of `MUST(ByteBuffer::copy(...))` and `.bytes()` calls
everywhere inside Fetch. We would then treat the bytes as a string
anyways by wrapping them in StringView everywhere.

We now store these as a ByteString. This is more comfortable to deal
with, and we no longer need to continually copy underlying storage (as
ByteString is ref-counted).

This work is largely preparatory for an upcoming HTTP header refactor.
2025-11-26 09:15:06 -05:00
Prajjwal
50a79c6af8 LibWeb: Change SessionHistoryTraversalQueue to use Promises
If multiple cross-document navigations are queued on
SessionHistoryTraversalQueue, running the next entry before the current
document load is finished may result in a deadlock. If the new document
has a navigable element of its own, it will append steps to SHTQ and
hang in nested spin_until.
This change uses promises to ensure that the current document loads
before the next entry is executed.

Fixes timeouts in the imported tests.

Co-authored-by: Sam Atkins <sam@ladybird.org>
2025-11-26 12:27:12 +01:00
Psychpsyo
100f37995f Everywhere: Clean up AD-HOC and FIXME comments without colons 2025-11-13 15:56:04 +01:00
Luke Wilde
7f7babe735 LibWeb: Remove spin_until from create_navigation_params_by_fetching
This is in similar fashion and reason to e095bf3
2025-11-07 04:08:30 +01:00
Aliaksandr Kalenik
ed9c0c1e09 LibWeb: Don't visit registered NavigationObserver from Navigable
NavigationObserver register itself in Navigable from constructor and
unregister itself from `finalize()`. The problem is that `finalize()`
won't be invoked for as long as NavigationObserver is visited by
Navigable, leading to GC leaks.
2025-11-07 04:08:30 +01:00
Luke Wilde
167de08c81 LibWeb: Remove exception throwing from Fetch
These were only here to manage OOMs, but there's not really any way to
recover from small OOMs in Fetch especially with its async nature.
2025-11-07 04:08:30 +01:00
Andreas Kling
4c2a02370d LibWeb: Add API to allow DecodedImageData to paint itself directly
Instead of painting DecodedImageData by first asking it for a bitmap
and then painting that, this commit adds two new APIs:

- frame_rect(frame_index):

    Gets the size of the animation frame at the given index.

- paint(context, ...):

    Paints the DecodedImageData into a DisplayListRecordingContext.

The main powerful thing here is that this allows SVGDecodedImageData
to render itself using the GPU when available.
2025-11-05 09:11:49 +01:00
Callum Law
12716dccf0 LibWeb: Avoid including ComputedProperties.h in Element.h
This reduces the size of the recompile when ComputedProperties.h is
modified from ~1200 to ~70
2025-10-27 14:50:54 +00:00
Andreas Kling
dbf041aa98 LibWeb: Ignore repaint requests inside iframes with visibility: hidden
This reduces idle CPU usage on https://gymgrossisten.com/ from 100%
(split between WebContent and Ladybird) to ~4% on my machine.
2025-10-23 17:42:37 +02:00
Luke Wilde
eeb5446c1b LibWeb: Avoid including Navigable.h in headers
This greatly reduces how much is recompiled when changing Navigable.h,
from >1000 to 82.
2025-10-20 10:16:55 +01:00
Aliaksandr Kalenik
d7f830cdd1 LibWeb: Execute rasterization callback on the rendering thread
Previously, we enqueued a task on the main thread's event loop to
execute the callback. This meant that even though the rendering thread
had finished producing the next frame, there was still a delay before
the main thread notified the UI process.

This change makes the rendering thread execute the callback directly.
This should be safe, as the only pointer captured by the callback is the
traversable `PageClient`, which is expected to remain alive for as long
as the rendering thread exists. The callback then invokes either
`page_did_paint()` or `page_did_take_screenshot()`, both of which
enqueue an IPC message, which is safe to do since `SendQueue` is
protected by a mutex.
2025-10-10 17:25:55 +02:00
Aliaksandr Kalenik
835081d66e LibWeb+LibWebView+WebContent: Reset pinch-to-zoom state on Ctrl/Cmd+0 2025-10-10 15:37:45 +02:00
Aliaksandr Kalenik
b477c6bfc4 LibWeb: Implement VisualViewport aware viewport scrolling
Implements spec algorithm for viewport scrolling that first checks if
it's possible to use delta to move the visual viewport before falling
back to scrolling the layout viewport. This is a part of pinch-to-zoom
support.
2025-10-10 15:37:45 +02:00
Aliaksandr Kalenik
5c699e1a45 LibWeb: Delete NavigableContainerViewportPaintable::layout_box()
No need for this method when we could reach into DOM node directly from
Paintable.
2025-10-10 09:03:39 +02:00
Timothy Flynn
efa9311527 LibWeb+WebContent+UI: Port text pasting to UTF-16 2025-09-19 06:38:52 -04:00
Jelle Raaijmakers
26b5fa348c LibWeb: Make Navigable::active_document() const 2025-09-12 15:34:09 -04:00
Psychpsyo
17e5289524 LibWeb: Suppress rendering due to view transitions
This also fixes a bug in the view transitions code that was
required to get the imported test to pass. The code for setting
the initial containing block size just did not set the right thing,
since doing so would trigger an error later on.

That later error resulted from walking up the tree, without
considering that the document element has a parent that is not
itself an element. (and then doing element things to it)
2025-09-09 10:25:17 +02:00
Psychpsyo
56739b4b16 LibWeb: Implement plumbing for view transitions
This implements large parts of the CSS view-transitions-1 spec.
2025-09-07 13:58:05 +01:00
Tim Ledbetter
cb1a1a5cb5 LibWeb: Replace is<T>() with as_if<T>() where possible 2025-08-25 18:45:00 +02:00
Timothy Flynn
70db474cf0 LibJS+LibWeb: Port interned bytecode strings to UTF-16
This was almost a no-op, except we intern JS exception messages. So the
bulk of this patch is porting exception messages to UTF-16.
2025-08-14 10:27:08 +02:00
Kenneth Myhra
e9246c15d9 LibWeb: Pass top-level navigation initiator origin to Fetch's Request 2025-08-12 07:08:33 -04:00
Sam Atkins
cfdc4bad7c LibWeb: Update more navigation code to spec
Partly corresponds to 80ebad5fbf

This is mostly to handle null source_documents, which is something that
needs more work elsewhere. The spec change above is about the deferred
fetch quota.
2025-08-11 11:08:04 +01:00
Sam Atkins
0e5fd11bdc LibWeb/HTML: Create navigation params for browser-UI navigations
Step 4 corresponds to 3b6a99b1d9

The rest is from some earlier spec change.
2025-08-11 11:08:04 +01:00
Sam Atkins
cf969abba7 LibWeb/HTML: Add missing "else" to create_navigation_params_by_fetching 2025-08-11 11:08:04 +01:00