Commit graph

1961 commits

Author SHA1 Message Date
Shannon Booth
2ae54d77e0 LibWeb: Reuse initial about:blank window for first same-origin load
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.
2026-05-22 18:17:58 +02:00
Andreas Kling
56e1f1ca22 LibWeb: Avoid relayout for definite-size image updates
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.
2026-05-22 15:09:29 +02:00
Andreas Kling
75375e8cef LibWeb: Update hover after async scrolling stops
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.
2026-05-22 14:33:39 +02:00
sideshowbarker
c1f38f92fe LibWeb: Keep repaints pending inside visibility:hidden iframes
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
2026-05-22 09:58:10 +01:00
Andreas Kling
55aad9ee38 LibWeb: Install fresh JS bytecode cache blobs locally
After generating a bytecode cache blob, map it as ImmutableBytes and ask
the owning JS record to install it. This lets a cold-cache load move to
mapped cache backing without waiting for a later page load.
2026-05-22 10:54:44 +02:00
Andreas Kling
43b8a8b099 LibWeb: Thread request context into ContentBlocker
Carry the initiating URL, fetch destination, initiator type, and request
mode from Fetch into LoadRequest and pass them to ContentBlocker. The
existing substring matcher still matches only the request URL, but the
blocker API now receives the context needed by source-aware backends.

Preserve that metadata for CORS preflights and connection hints, and add
coverage for resource-type mapping and blob source URL normalization.
2026-05-21 21:16:56 +02:00
Callum Law
199e82fc73 LibWeb: Forward non-synthetic pseudo-elt accesses to relevant element
This adds a new class `ElementReferencePseudoElement` which forwards
any accesses to the referenced element for "element-reference" pseudo
elements.

This allows us to, for instance:
 - Access the underlying `ComputedProperties` in getComputedStyle, which
   includes inline style.
 - Store and access `CustomPropertyData`
 - Access the layout node for "resolved value" computation
 - Apply animations from `update_animated_style_if_needed`

We register these with the originating element when calling
`set_associated_shadow_host_pseudo_element`, this requires us to append
the element to the tree beforehand since we need to be able to get the
shadow host.
2026-05-21 14:26:22 +01:00
Callum Law
977c054e77 LibWeb: Rename use_pseudo_element
`associated_shadow_host_pseudo_element` is clearer on what this is.
2026-05-21 14:26:22 +01:00
Aliaksandr Kalenik
6b912038d3 LibWeb+WebContent: Route compositor through in-process IPC
LibWeb still exposed the concrete CompositorThread to Page,
Navigable, and EventHandler, so compositor IPC would have leaked the
thread implementation into callers. The old thread APIs also bundled
page presentation callbacks and main-thread wakeups into the same
object, which made it awkward for WebContent to put an actor boundary
in between.

Introduce CompositorHost and context handles as the caller-facing API,
and move shared compositor protocol values out of CompositorThread. Add
WebContentCompositor IPC endpoints and route PageHost through a paired
in-process transport. The actor owns CompositorThread with explicit
main-thread and UI presentation clients, while screenshot completion is
serialized on the WebContent event loop using request IDs.

The intention for introducing IPC here is to prepare for moving the
compositor thread into a separate process.
2026-05-21 11:45:06 +01:00
Andreas Kling
30aae77901 LibWeb: Delegate focus from shadow hosts
Handle the delegatesFocus branch of get-the-focusable-area before
rejecting non-focusable focus targets. This lets host.focus() move focus
to the first focusable delegate in the shadow tree, or preserve an
already-focused descendant.

Treat delegatesFocus shadow hosts as focus delegates even when tabindex
would otherwise make the host focusable. Skip inert delegate candidates,
and reject inert shadow hosts before looking for a delegate. Check focus
inertness through shadow-host ancestry so direct focus cannot enter
inert shadow subtrees.

Rebaseline the disabled delegatesFocus WPT now that this behavior
passes. Cover delegated focus, hidden and inert delegate candidates,
tabindex hosts, inert hosts and direct delegates inside inert hosts, and
hosts without any focusable delegate.
2026-05-21 08:56:05 +02:00
Andreas Kling
94302775bf LibWeb: Map document element focus to the viewport
Apply the focusing steps' get-the-focusable-area mapping before
rejecting a non-focusable target. This preserves documentElement.focus()
by mapping the non-focusable document element to the Document viewport.

Also map rendered navigable containers with content navigables to their
active document, while leaving hidden containers unfocused. Preserve
Window focus events for child document viewports reached through iframe
focus, while still suppressing the top-level viewport surrogate events.

Treat rendered object elements as focusable through their default
non-null tabindex, even when they show fallback or image content instead
of a child navigable.

Keep the spec focus-chain common-tail handling intact for viewport
focus. The Document object is only our surrogate for the viewport, so
designate viewport focus from the new focus target without dispatching
Window focus/focusin events for that top-level surrogate.

Pass that viewport surrogate as the fallback target for fragment
scrolling and NavigateEvent focus reset, so unfocusable body or fragment
targets still clear stale element focus.

Cover documentElement.focus() in both the activeElement and focus-chain
tests, including a tabindex document element that remains focused as an
element. Cover object focus with and without a child navigable, hidden
object focus attempts, iframe focus events, hidden iframe focus, and
blurring a focused iframe after it becomes hidden. Also cover viewport
fallback for intercepted navigation focus reset and fragment scrolling
to an unfocusable target.
2026-05-21 08:56:05 +02:00
Andreas Kling
99b1780d57 LibWeb: Reject non-rendered elements as focus targets
Do not let elements inside display:none subtrees become focus targets.
The HTML focusable-area model only allows elements to be focusable when
they are rendered, delegate rendering to their children, or are relevant
canvas fallback content.

Preserve blur for the current focused area after script hides it, since
the unfocusing steps operate on the old focus target. Check display:none
through the flat-tree style parent chain, so slotted controls inside
hidden slot subtrees cannot become focused.

Cover hidden ancestors with materialized computed style, display:none
controls, display:contents, hidden focused controls, and slotted cases
inside hidden and visible shadow-tree subtrees.
2026-05-21 08:56:05 +02:00
Tim Ledbetter
11379e7c67 LibWeb: Clear selection when no find in page matches are found
Previously, if the find in page query was updated and no matches were
found we would keep the old selection instead of clearing it.

`window.find` behaves differently from the find in page UI and
preserves the old behavior.
2026-05-20 21:32:00 +02:00
Timothy Flynn
f0d7e28f55 LibWeb+LibWebView+UI: Move SelectedFile factory to LibWebView
This factory is only used by the UI. An upcoming commit will make it
depend on LibFileSystem. LibWeb currently does not link LibFileSystem,
and doing so would push LibWeb in the wrong direction (we should be
doing less file IO in LibWeb, not more).
2026-05-20 21:09:22 +02:00
Shannon Booth
de6aec04e8 LibGC: Default-construct ConservativeVector from the global heap 2026-05-20 20:37:55 +02:00
Shannon Booth
387cd6e2e2 LibGC: Default-construct RootVector from the global heap
Similar to GC::Root<T>, make GC::RootVector<T> constructible without
explicitly passing a Heap.

This is implemented by having RootVectorBase use GC::Heap::the() for
heap-free construction.
2026-05-20 20:37:55 +02:00
Andreas Kling
8eb74bf747 LibWeb+LibWebView: Preserve crashed page URLs on crash
Load the browser-generated crash page as a synthetic response for the
URL that was active when WebContent exited. This keeps the session
history entry, response URL, and created Document aligned with the same
navigation URL, so reload targets the original page without creating a
local document for an HTTP(S) history entry.

Suppress history metadata updates from the generated page and declare
an inert rel=icon. Fallback favicon loading now follows the HTML
condition that no link with the icon keyword exists, which avoids the
credentialed /favicon.ico request from the crashed origin.
2026-05-20 20:17:45 +02:00
Sam Atkins
9996403e73 LibWeb/CSS: Extract base class from MediaFeature
`<media-feature>` and the upcoming `<size-feature>` from `@container`,
share the same syntax and almost all of their behaviour. To avoid a lot
of duplication, pull as much as possible into a FeatureQuery template
class that they will both inherit from.

MediaFeatureValue is renamed FeatureValue as it's also shared by both.

No behaviour change.
2026-05-20 13:00:50 +01:00
Sam Atkins
34382a2aca LibWeb/HTML: Add missing include for KeywordStyleValue 2026-05-20 13:00:50 +01:00
Tim Ledbetter
b67d73a661 LibWeb: Apply ::first-letter pseudo-element styles
We now apply first letter styles by splitting text with a first-letter
style applied into 2 `TextSliceNode` objects.  The
`DOM::Text` layout  node always points at the non first-letter slice
and the first-letter slice is  reachable via
`TextSliceNode::first_letter_slice()`.

First letter splitting works by `TreeBuilder` walking a block
container's inline descendants to find the first typographic letter
unit per the pattern given in  css-pseudo level 4, which is then
wrapped in an anonymous inline box styled with the `::first-letter`
computed properties.

Consumers that map between DOM offsets and layout geometry
are updated to visit all slices of a `DOM::Text` through
`TextOffsetMapping`.
2026-05-20 12:09:19 +01:00
Andreas Kling
5fedacb7de LibWeb: Move textarea Home and End by line
Make unmodified Home and End in textarea use the current line
boundary instead of the whole control. Keep modified Home and End on
the existing whole-control path so Ctrl+Home and Ctrl+End still jump
across the textarea.

Update the textarea keyboard navigation test to cover the fixed line
movement and the preserved modified-key behavior.
2026-05-20 12:26:20 +02:00
Andreas Kling
f7411a36a1 LibWeb: Notify clients when reload starts
Emit the existing page_did_start_loading notification when a
top-level reload starts repopulating the document. Normal navigation
already sends this notification earlier in the algorithm, but reload
enters through the session history path and skipped the UI signal.

This lets browser chrome show its loading indicator for reloads without
frontend-specific reload button hooks.
2026-05-20 09:37:33 +02:00
Tim Ledbetter
ee55344997 LibWeb: Stop completed image fetches from retaining the prior document
When an image fetch finished or failed, the cached request object
released its fetch controller before releasing its load-event delayer.
Releasing the delayer decrements the document's load-event delay count,
which can re-enter the HTML parser end check and fire the document load
event. If anything triggers a same-URL image fetch during that
re-entry,  the cached request gets a fresh fetch controller and the
request get's kept alive, which also keeps the assocaited window and
document objects alive.
2026-05-20 01:47:14 +02:00
Zaggy1024
8cc00c09fa LibWeb: Only update the media controls' timeline while playing 2026-05-19 16:37:59 -05:00
Aliaksandr Kalenik
6063650261 LibWeb: Stop using VideoFrameSource for video frame updates
Future compositor-process work needs to push video frame updates without
going through VideoFrameSource. That object cannot be shared through
IPC, so video display-list resources now use stable VideoFrameResourceId
values and the current frame is sent through explicit resource/update
commands.
2026-05-19 22:11:15 +02:00
Aliaksandr Kalenik
262a2796b2 LibWeb: Paint iframe surfaces through compositor queue order
Represent main-thread presents as compositor commands so iframe presents
remain ordered before later parent display-list and present work. Nested
painting now enqueues the child present without blocking the main
thread.

When a nested present publishes to a compositor surface owned by another
context on the same page thread, update that target context directly
inside the compositor loop. This keeps the iframe surface available
before the queued parent present replays its display list.
2026-05-18 20:11:31 +02:00
Aliaksandr Kalenik
81b5b343d9 LibWeb: Share WebContent compositor thread across pages
Move compositor-thread ownership to WebContent's PageHost so every Page
object in one WebContent process registers its navigables on the same
compositor thread. This covers auxiliary pages created by window.open(),
while worker and SVG helper pages continue to skip compositor thread
creation.

Keep page presentation keyed by page id. Each presenting context records
the page id it presents for, and static compositor entry points route
ready-to-paint, async scrolling, and viewport scrollbar events to that
page's presenting context on the shared thread.
2026-05-18 20:11:31 +02:00
Martin Chrástek
437c8b1d19 LibWeb: Implement legacy-clone of session storage shed on window.open
When a new window is opened via window.open() with an opener
(non-null), the session storage must be cloned from the opener's
storage shed into the new window's storage shed. This implements
the legacy-clone a traversable storage shed algorithm from the
Storage spec.
2026-05-18 16:38:15 +02:00
Aliaksandr Kalenik
93bbdf1f55 LibWeb: Use compositor surface IDs for embedded content
Display lists kept canvas and nested navigable content alive through
ExternalContentSource objects. That made the resource graph depend on
process-local object identity instead of a stable surface handle, which
blocks compositor process isolation and made teardown-sensitive embedded
content harder to reason about.

Allocate CompositorSurfaceId values for canvases and child navigables,
publish their backing stores to the owning compositor, and paint them
with DrawCompositorSurface. Child navigables now publish to parent
compositors by CompositorContextId instead of raw object pointers, so
the in-process path uses the same stable addressing model required by a
remote compositor.

Clear and skip stale child surfaces during teardown, preserve Skia
canvas state while drawing compositor surfaces, and add display-list
coverage for canvas and iframe compositor surfaces. The nested navigable
async-scrolling baseline now expects DrawCompositorSurface.
2026-05-18 15:27:59 +02:00
InvalidUsernameException
46e91c7ba6 LibWeb: Invalidate img-element when loaded from list of available images
When loading an image, there are two success paths: Either the image is
loaded through fetch, or it is part of the list of available images
already and doesn't need to be downloaded anymore.

Only the fetch code path was invalidating style and layout, meaning that
an image loaded from the list of available images was not visible until
something else caused an invalidation.

To fix this, perform the same invalidation in both code paths.

This fixes that most of the images on https://bleepingcomputer.com/ were
not loading until hovered. They are using
[`bLazy.JS`](https://github.com/dinbror/blazy), which loads the files on
a disconnected `img` element and then swaps out `src` or `srcset` on the
actual `img` element once the load has completed.

The `requestAnimationFrame`-dance in the testcase is there to ensure
that the test fails reliably without this change applied.
2026-05-18 12:54:49 +02:00
Andreas Kling
3d3e6f4226 LibJS+LibWeb: Keep cached script source text lazy
Avoid decoding warm-cache script responses into full UTF-16 SourceCode
buffers when a bytecode cache sidecar is available. SourceCode now keeps
the original immutable source bytes and source encoding, then decodes
only when full source text or a Function.toString() range is requested.

Compute the bytecode cache source hash while streaming decoded code
points from the response bytes, so cache validation does not force an
intermediate UTF-8 string. Function and class source text metadata now
stores SourceCode ranges instead of views into a materialized buffer.
2026-05-18 09:18:35 +02:00
Andreas Kling
b849af70b8 AK+LibWeb: Reject impossible Variant visit overloads
Make Variant::visit reject typed visitor overloads that cannot be
called for any variant alternative. This catches stale visitors after a
variant payload type changes instead of falling through to a generic
overload.

Update fetch body consumers that still expected ByteBuffer after the
body payload moved to Core::ImmutableBytes.
2026-05-18 01:21:34 +02:00
Andreas Kling
318fb4f2d0 LibWeb: Preserve immutable consumed body bytes
Keep consumed response body bytes in Core::ImmutableBytes instead of
requiring a ByteBuffer. This lets responses that already arrived as
file-backed immutable data keep that representation through body
consumption, while streamed responses can still adopt their
accumulated ByteBuffer without another copy.

Update the body consumers that only inspect bytes to read from
immutable byte views. Font loading still copies at its existing
ownership boundary, where the off-thread preparation path takes a
ByteBuffer.
2026-05-18 01:21:34 +02:00
Andreas Kling
936bb9ca53 LibWeb: Use Rust preload scanner
Replace the C++ speculative HTML parser token walk with the Rust
preload scanner. Keep URL resolution, duplicate suppression, and fetch
issuance in C++ so the scanner only emits base href updates and fetch
candidates.

Use the scanner callback result to stop iteration when the speculative
parser has been stopped.

Update parser comments that still described speculative mock element
production.
2026-05-18 00:23:52 +02:00
Andreas Kling
411c6654e8 LibWeb: Add Rust preload scanner
Add a Rust scanner that walks pending HTML parser input and emits base
href updates or speculative fetch candidates. Keep URL parsing and fetch
issuance in C++ for now, where the Document and request objects live.

Allow the scan callback to stop iteration so the C++ speculative parser
can preserve its stop hook once it is wired up.

Expose a shared Attribute helper for resolving interned local names and
use it from the Rust parser and preload scanner instead of repeating the
same lookup pattern.

Cover link rel handling, preload destination filtering, crossorigin
mapping, and template/foreign-content skipping with Rust unit tests.
2026-05-18 00:23:52 +02:00
Andreas Kling
1c7519f9ef LibWeb: Treat fragment parser documents as disconnected
Keep the temporary document used by HTML fragment parsing from
running post-connection work while the parser is staging nodes there.
This lets scripts from Range.createContextualFragment() remain
unstarted until the returned fragment is inserted into the real
document, and removes the script-specific preparation guard.

Strengthen parser coverage so contextual fragment scripts must wait
until the fragment is applied before running.
2026-05-17 15:35:56 +02:00
Andreas Kling
ccf5a278ab LibWeb: Keep deferred document.close cleanup on its parser
document.close() can defer script-created parser cleanup while a
parser-blocking script is pending. If document.open() installs a new
parser before the old parser resumes, the deferred action must clean up
the parser that scheduled it instead of the document's current parser.

Capture that parser before installing the deferred action. This keeps
the parked cleanup from affecting a parser installed by a later
document.open() call.
2026-05-17 15:35:56 +02:00
Andreas Kling
29784ea397 LibWeb: Remove the C++ HTML tree builder
Delete the old C++ tree-construction implementation and helper classes
that became unused once the Rust parser is unconditional. Remove the C++
stack of open elements, active formatting elements, speculative mock
element, and tree-builder-only token storage.

Keep the C++ parser entry points that still own LibWeb DOM integration,
encoding detection, tokenizer bridging, incremental parsing, and the
speculative parser support used by resource discovery.
2026-05-17 15:35:56 +02:00
Andreas Kling
a7ece4b062 LibWeb: Make the Rust HTML parser unconditional
Remove the runtime selector between the old C++ tree builder and the new
Rust implementation. Always construct HTML documents and fragments with
the Rust parser now that it matches the existing tests.

Simplify dump-html-tree by dropping the backend option that only made
sense while both parser implementations were available.
2026-05-17 15:35:56 +02:00
Andreas Kling
f49335f210 LibWeb: Align declarative shadow root parsing
Teach the Rust parser to recognize declarative shadow root templates and
pass the parsed mode, slot assignment, clonable, serializable, and
focus-delegation flags to the C++ DOM host.

Expose shadowRootSlotAssignment reflection with the spec-defined named
missing and invalid value defaults, and extend the ShadowDOM text test
coverage for the reflected property and parser-created shadow roots.
2026-05-17 15:35:56 +02:00
Andreas Kling
54879bc916 LibWeb: Complete Rust HTML tree construction
Finish the Rust implementation of the spec tree-construction algorithms
needed by the LibWeb test suite. Add the remaining table modes, foster
parenting, scope helpers, adoption agency handling, ruby/list/form and
select cases, frameset state, foreign-content edge cases, and parser
host callbacks.

Preserve behavior that depends on the C++ DOM integration, including
parser-created custom element reactions, fragment quirks mode, arbitrary
fragment namespaces, template fragment mode, fragment form ownership,
MathML annotation-xml boundaries, contextual fragment scripts, parser
script source positions, document.close() parser state, void-element
insertion, and duplicate attribute tracking.

Add focused tests for the parser edge cases that are easy to regress at
the boundary between the Rust tree builder and the C++ DOM host.
2026-05-17 15:35:56 +02:00
Andreas Kling
de12062515 LibWeb: Wire Rust parser scripts and fragments
Preserve Rust parser state across tokenizer runs and stop cleanly when
a parser-blocking script has to execute. Thread the pending script back
through the existing C++ parser entry point so document.write(), input
insertion points, and script bookkeeping continue to use the normal
LibWeb machinery.

Add the fragment parser setup needed by innerHTML and contextual
fragment parsing, including context elements, form ownership, tokenizer
state selection, text coalescing, and foreign-content integration.
2026-05-17 15:35:56 +02:00
Andreas Kling
2e9875770e LibWeb: Add initial Rust HTML tree construction
Implement the first Rust tree builder pass around the tokenizer and the
LibWeb DOM host hooks. Cover the document setup, insertion-mode
dispatch, ordinary body insertion, basic table handling, active
formatting element reconstruction, and foreign-content routing.

Leave the C++ parser available at runtime so the new path can be tested
against the old implementation while the remaining tree-construction
algorithms are filled in.
2026-05-17 15:35:56 +02:00
Andreas Kling
09296315c2 LibWeb: Add Rust HTML parser host plumbing
Add the C++ and Rust scaffolding that lets the tree builder live in
Rust while the DOM remains owned by LibWeb. Keep the exported surface
small: Rust stores parser state, and C++ provides node creation,
insertion, script, template, and GC hooks.

Route dump-html-tree through the selectable parser backend so the new
implementation can be exercised beside the existing parser while it is
being brought up.
2026-05-17 15:35:56 +02:00
Andreas Kling
5b63cb5f37 LibWeb: Avoid unsafe tokenizer state conversion
Replace the FFI tokenizer state transmute with an explicit conversion
from the incoming numeric value. The old code range-checked against the
last state before transmuting, which matched today's contiguous enum but
left the conversion dependent on that layout detail.

Returning early for unknown values keeps the FFI boundary tolerant while
removing a source of possible invalid enum discriminants.
2026-05-17 15:35:56 +02:00
Andreas Kling
11e69d5e49 LibWeb: Support dump tools without resource loading
Allow parser dump utilities to run without installing a ResourceLoader.
Short-circuit resource fetch entry points used by links, stylesheets,
and shared resource requests when no loader is present.

Keep those failures local to headless utility use so dump-html-tree can
parse real pages without a full browser page loader or request service.
2026-05-17 15:35:56 +02:00
Andreas Kling
edf909f83d Utilities: Add dump-html-tree
Add a small parser utility for inspecting tree-construction output in
the same spirit as dump-html-tokens. Print an annotated DOM tree so
parser changes can be compared without launching the browser.

Keep a silent iteration mode for external benchmark tools, where the
parser still builds the DOM but the utility avoids serialization and
stdout work.
2026-05-17 15:35:56 +02:00
Andreas Kling
541828dbb1 LibWeb: Respect overflow axes for wheel scrolling
Keep the compositor scroll node max offset as the real scroll range,
even for axes that cannot be scrolled by wheel input. Track wheel
scrollability separately so hidden axes are skipped during async wheel
scrolling without clamping away an existing programmatic offset.

Use the viewport-propagated root and body overflow values when deciding
whether viewport axes accept wheel input. Apply wheel deltas only on
axes that can be wheel-scrolled in async metadata and main-thread wheel
default actions, while preserving CSSOM scroll offsets on hidden axes.

Add async scrolling coverage for hidden-axis wheel targeting, preserved
programmatic hidden-axis offsets, and body overflow-x: hidden blocking a
horizontal viewport wheel scroll despite pseudo-element overflow.
2026-05-17 14:19:36 +02:00
Andreas Kling
28e648714d LibWeb: Stop internal IDB databases retaining realms
The process-wide IndexedDB database registry stores internal database
objects in GC roots. Those objects do not need a JavaScript shape or
realm, but they inherited one from PlatformObject. This let an internal
database keep its creating realm, window, and script graph alive.

Make the internal database construct a plain GC cell instead. Callers
provide a heap when they need snapshots of associated connections. This
means the database no longer needs to remember its creating realm.

On x.com, the rooted internal database subgraph shrank from the whole
page graph, including 24k executables, to the database metadata itself.
2026-05-17 00:29:18 +02:00
Andreas Kling
f1c151a17f LibWeb: Release completed link element fetches
HTMLLinkElement only needs to retain its FetchController while a linked
resource fetch is in flight, so that a later attribute change can stop
the old request. Once the current stylesheet/icon/preload fetch has
produced its response, keeping the controller alive retains FetchParams,
the Request, and the request client unnecessarily.

Clear the in-flight controller as each current linked resource fetch
finishes. Stale callbacks from older generations still return without
touching a newer controller.
2026-05-17 00:29:18 +02:00