Commit graph

79502 commits

Author SHA1 Message Date
Andreas Kling
4daec8f6e0 LibWeb: Use Event storage for MouseEvent relatedTarget
Store MouseEvent's relatedTarget in the inherited Event field instead of
keeping a second slot on MouseEvent.

Event dispatch retargets and updates the inherited field while building
the event path. The second slot left JS listeners observing stale or
null relatedTarget values during mouse and pointer boundary events.

Add coverage for boundary events between sibling elements.
2026-06-18 12:40:37 +02:00
Callum Law
8ebdd6d41e LibWeb: Schedule rendering update on AVC only style change
b583fd skipped display list invalidation for AVC only style changes
which also meant that we no longer marked the navigable as needing a
repaint or requested the next frame.

This commit updates `set_needs_accumulated_visual_contexts_update` to do
so.

This makes the animation when hovering icons on
https://chrede88.github.io/L1nkr paint intermediate frames not just the
first and last.
2026-06-18 12:26:22 +02:00
Callum Law
64f866cae2 LibWeb: Support number/percentage interpolation for scale
Previously we didn't support interpolating component values of `scale`
from a number to a percentage (or vice versa). This also caused
interpolation from `none` to a percentage value to fail since the
fallback value is number based.

This makes the transition run when hovering buttons on
https://chrede88.github.io/L1nkr/ rather than being discrete.
2026-06-18 12:26:22 +02:00
Callum Law
2c6aa4d272 LibWeb: Apply null transform properties on style recomputation
When applying style in `Layout::Node::apply_style` we previously ignored
null `rotate`, `translate`, and `scale` values which left the old values
in place in the case of nonnull -> null changes.

Fixes #10125
2026-06-18 12:26:22 +02:00
Sam Atkins
147d4595c6 LibWebView: Restore RFC cookie storage behavior
In 11b053b154 I accidentally changed the
behaviour of CookieJar::set_cookie() to not match what the RFC
requires, particularly when dealing with too-long paths. This commit
restores the original behaviour, now that the validation required by
DevTools happens elsewhere, before set_cookie() is called.
2026-06-18 11:37:36 +02:00
Sam Atkins
953251351d LibHTTP: Validate direct cookie conversion
DevTools edits cookies as concrete fields rather than Set-Cookie
strings. Validate direct Cookie objects while converting them back to
ParsedCookie so invalid edits can be reported without making the RFC
storage algorithm stricter.
2026-06-18 11:37:36 +02:00
Sam Atkins
680dc78dac LibHTTP: Reuse cookie domain attribute parsing
The Cookie to ParsedCookie conversion stripped a leading dot and
lowercased the cookie domain itself. Use the existing Domain attribute
parser instead, so edited cookies follow the same ASCII validation and
normalization as Set-Cookie parsing.
2026-06-18 11:37:36 +02:00
Sam Atkins
b1547d467e LibHTTP+LibWebView: Share Cookie conversion
Nothing about `parsed_cookie_from_devtools_cookie()` is specific to
DevTools, so move it to ParsedCookie.h as `parse_cookie()` instead.
2026-06-18 11:37:36 +02:00
sideshowbarker
9f7a328d9b LibWeb: Reject canvas toDataURL()/toBlob() when not origin-clean
Problem: Drawing a cross-origin image onto a 2D canvas clears its
origin-clean flag, but toDataURL() and toBlob() ignored that flag and
serialized the bitmap regardless. So, a page could read back the
cross-origin pixels it shouldn't (per spec) be allowed to access.

Cause: The origin-clean checks in to_data_url() and to_blob() were left
as FIXMEs. Only getImageData() enforced the flag.

Fix: Throw a SecurityError exception from both serialization entry
points when the canvas isn't origin-clean — matching getImageData() and
the spec. The same check also implements the previously-stubbed
origin-clean step in the WebDriver canvas-encoding algorithm.

Fixes: https://github.com/LadybirdBrowser/ladybird/issues/10009
2026-06-18 10:52:42 +02:00
Jelle Raaijmakers
d642f7d85a LibWeb: Do not dump number of children for StackingContexts
The number of children a SC has is not that useful in dumps, when all
its children are dumped anyway.
2026-06-18 10:50:08 +02:00
Callum Law
8ebdaeab69 LibWeb: Transfer animation ownership to AnimatedBitmapDecodedImageData
Previously animation ownership was a messy split between
`AnimatedBitmapDecodedImageData` and the consumers (i.e.
`ImageStyleValueResource`, `HTMLImageElement`, and `SVGImageElement`)
with `AnimatedBitmapDecodedImageData` owning the frames and a current
frame index, and the consumers owning the rest of the state (e.g. loop
count, timers to drive the animation forward, their own current index).

This had a couple of main issues:
 - While `AnimatedDecodedImageData` partially synchronized animations by
   dropping unexpected advancement notifications, this didn't apply to
   other animation state which meant, for instance, that a later started
   consumer could drive the animation of an earlier one past the max
   loop count (albeit without invalidating the earlier consumer).
 - Multiple consumers didn't share frame timings, meaning animations
   could be up to a full frame out of sync visually.
 - Animations were paused depending on whether there were any consumers,
   this is different to the behavior in other browsers (where they
   continue regardless of whether there are any consumers).
 - It was an overgeneralization of how animations need to work - only
   `AnimatedBitmapDecodedImageData` works with an indexed frame model,
   with animated SVGs (although not yet implemented) relying on their
   internal event loop to be driven forward.

Given the above the new approach implemented in this commit is:
 - The API for `DecodedImageData` is animation system agnostic, only
   exposing `default_frame`, `current_frame`, and `restart_animation`
   methods not reliant on providing a specific frame index.
 - `AnimatedBitmapDecodedImageData` owns its own timer, loop count,
   etc. The animation starts when the first consumer registers and ends
   when the document is hidden or becomes inactive (or completes in the
   case of finite animations).
 - Consumers are invalidated by `AnimatedBitmapDecodedImageData` when
   required.

Tests have been added for:
 - Animations being paused when the document becomes inactive and
   restarted when it becomes active again.
 - Frame timings being synchronized across consumers.
 - Restarts triggered by `HTMLImageElement` applying to all consumers.
 - Processing ending once a non-infinite animation plays to completion.

The tests to ensure animations are cancelled when consumers are removed
(e.g. `animated-background-image-timer-stops-when-hidden.html`) have
been updated to assert the inverse since animation state is now per
resource not per consumer.
2026-06-18 10:44:25 +02:00
Callum Law
27381e9b00 LibWeb: Remove index based frame getters for ImageStyleValue
`ImageStyleValueResource::frame` was unused and `ImageStyleValue::frame`
was only ever used to get the current frame so it can just be inlined.
2026-06-18 10:44:25 +02:00
Callum Law
3852b3f5a8 LibWeb: Rename AnimatedDecodedImageData
To `AnimatedBitmapDecodedImageData`. This better reflects what it is and
frees up `AnimatedDecodedImageData` to be used as an abstract class in a
later commit.
2026-06-18 10:44:25 +02:00
Callum Law
a7881ca3eb LibWeb: Register DecodedImageData consumers as clients
In a future commit, ownership of animation will be transferred from
these clients to `AnimatedDecodedImageData` and we will need a way to
invalidate them for new frames.

This also revealed some `ImageProvider`s which don't yet support
animated images (e.g. `<input type="file">`, `<object>`, etc) but that
is left as a FIXME for now.
2026-06-18 10:44:25 +02:00
Callum Law
74e04ed258 LibWeb: Add DecodedImageData::default_frame helper
The index based `frame(size_t, ...)` getter is going to be removed in a
future commit.
2026-06-18 10:44:25 +02:00
Callum Law
4428eba205 LibWeb: Simplify ImageStyleValueResource
`ImageStyleValueResource` now holds a reference to a
`HTML::SharedResourceRequest` for it's entire lifetime.

We also `VERIFY` that we have created a resource (by registering a
client) before calling `ImageStyleValue::image_data` rather than
silently failing.
2026-06-18 10:44:25 +02:00
Callum Law
2335941e43 LibWeb: Register ImageObservers for all mask-images
As of 114c8a7 we paint all mask layers, not just the first, so we should
likewise observe all `mask-image` values, not just the first.
2026-06-18 10:44:25 +02:00
Callum Law
11ab66c752 LibWeb: Notify ImageStyleValue::Clients on animation
Previously image animations driven by `ImageStyleValueResource`
invalidated clients using `on_animate`, this was only implemented by the
`background` presentational attribute of `HTMLBodyElement`.

It now uses `notify_clients_did_update` which is implemented by all
clients.
2026-06-18 10:44:25 +02:00
Callum Law
ce7a963344 LibWeb: Guard ImageRequest::fetch_image against redundant fetches
All other callers of `SharedResourceRequest::fetch_resource` guard based
on `needs_fetching` so let's do that here as well (and add a `VERIFY` so
that future callers don't make the same mistake).
2026-06-18 10:44:25 +02:00
Callum Law
373327a207 LibWeb: Remove AnimatedDecodedImageData::m_highest_requested_frame
This was only ever set, not read.
2026-06-18 10:44:25 +02:00
Callum Law
d98c5d1b03 LibWeb: Inline image scaling mode computation
This allows us to remove the `frame_rect` accessor.

This also fixes a bug where we computed the scaling mode based on the
clipping rect rather than the draw rect for `ImagePaintable`
2026-06-18 10:44:25 +02:00
Callum Law
d3c0cfdc71 LibWeb: Respect SVG intrinsic sizing during object fitting
Previously we used the `frame_rect` size, this is the same as the
intrinsic size for bitmap images but is `OptionalNone` for SVG which
caused us to always fall back to the `image_rect` and thus not apply
any scaling for SVGs regardless of whether they had intrinsic sizing.
2026-06-18 10:44:25 +02:00
Aliaksandr Kalenik
f6f68ece44 Services: Deny GPU operations in WebContent
WebContent no longer creates a GPU-backed Skia context, so its Linux
sandbox does not need the broad GPU device syscall allowance. Remove
allow_gpu_device_operations() from the renderer policy while keeping the
narrower file descriptor ioctl allowances used by IPC transport setup.
2026-06-18 10:25:44 +02:00
Aliaksandr Kalenik
724ca7cc24 LibSandbox: Allow TCGETS2 fd queries
WebContent is about to stop using the broad GPU device sandbox
allowance. That also removes the accidental permission for every ioctl,
which exposes ordinary terminal attribute queries made while printing
diagnostics.

The media decode error path can ask stderr for TCGETS2 while reporting a
corrupt video frame. Allow that narrow fd metadata query alongside
TCGETS, FIONBIO, and FIONREAD so renderer processes can keep the GPU
ioctl denial without crashing the media decode-error coverage.
2026-06-18 10:25:44 +02:00
Aliaksandr Kalenik
23885e7b4d LibWeb+WebContent+WebWorker: Drop display list player type selection
WebContent no longer chooses between CPU and GPU display list players,
and the remaining callers always use Skia raster playback. Remove the
PageClient virtual and now-single-value enum, then play SVG image and
cursor display lists directly.
2026-06-18 10:25:44 +02:00
Aliaksandr Kalenik
40d446d558 LibWebView+WebContent: Stop creating GPU Skia backend in WebContent
Canvas and display list rasterization now run in the Compositor
process, so WebContent no longer needs its own Skia GPU backend. Drop
the WebContent --force-cpu-painting option and stop forwarding it when
launching the renderer. The flag remains available for Compositor.
2026-06-18 10:25:44 +02:00
sideshowbarker
33d969682b Tests: Wait for session history convergence in UI history assertions
Problem: TestWebDriverSessionHistory failed intermittently on the slower
sanitizer CI runners. The UI history already matched what’s expected,
but webContentHistoryMatchesUI was still false — because the snapshot
was caught mid process-swap. The failing assertion varied from run to
run, making it almost certainly a sampling race.

Cause: A cross-site history navigation swaps the WebContent process and
re-seeds its history, and the UI-process mirror converges to that
asynchronously — after the script-visible navigation has finished. But
expect_ui_session_history sampled the mirror once, and asserted right
away — so it could read the state before convergence.

Fix: When a converged state is expected, wait for it instead of sampling
once: Poll until the UI history matches and WebContent matches the UI.
2026-06-18 10:23:49 +02:00
Jelle Raaijmakers
9ed75e4f50 LibWeb/CSS: Retain length precision in PercentageOr<T>
Instead of operating within the (saturating) CSSPixels constraints,
calculate the expected value using a floating point calculation first
and then create the CSSPixels value.
2026-06-18 09:59:41 +02:00
sideshowbarker
a38407d457 LibWeb: Unregister a “use” element from its document when finalized
Problem: Discarding a document that contains an SVG “use” element could
abort the process with a !is_in_list() verification failure in the
IntrusiveListNode destructor. That surfaced intermittently in our style-
invalidation stress tests, depending on GC sweep order.

Cause: A “use” element connected to a document registers itself in the
document’s list of “use” elements and unregisters during its removal
steps. A GC’ed “use” element is swept without running those removal
steps — so it stays linked. When it’s destroyed before its document,
its list node is still linked — and the destructor aborts.

Fix: Override finalize() to unregister the “use” element before
destruction. The collector finalizes every dying cell before destroying
any of them. So, the node is always unlinked in time — the same approach
DocumentObserver and NavigationObserver already use.
2026-06-18 09:39:47 +02:00
Aliaksandr Kalenik
aa1926159e Services: Move GPU runtime access to Compositor
WebGL rasterization now happens in the Compositor process, but the GPU
runtime Landlock rules still lived only in WebContent. ANGLE initializes
native EGL when a page creates a WebGL context, which happens after the
Compositor sandbox is installed, so loading libEGL.so.1 and the
Mesa/GLVND driver stack was denied.

Grant the Compositor access to native GL/Vulkan driver and configuration
paths, DRI devices, /sys, LD_LIBRARY_PATH entries, the Mesa shader
cache, and executable mappings required by the driver stack.

Remove the corresponding late filesystem access from WebContent.
WebContent still initializes its Skia GPU backend before installing its
sandbox, so it does not need to open the GPU runtime afterward; keep the
GPU device seccomp allowance there because Skia continues to issue
operations on already-opened GPU fds for display-list painting.
2026-06-18 08:22:09 +02:00
Aliaksandr Kalenik
d96dc6535f LibWeb+Compositor+WebContent: Simplify nested context composition
Nested navigables were represented through compositor surface ids owned
by the parent context. That forced CompositorState and ContextState to
maintain bidirectional attach/detach bookkeeping, publish child
snapshots into a surface map, and keep presentation mode variants just
to distinguish UI presentation from parent composition.

Record the child compositor context id directly in the display list and
let the compositor resolve it against the painting parent at playback
time. Child contexts now keep their parent context id and latest
rendered surface, while parents no longer track child maps or compositor
surface ids. UI presentation is represented separately from parent
composition, so closing a page only stops client presentation and nested
contexts keep using set_parent_context.
2026-06-18 07:08:34 +02:00
Aliaksandr Kalenik
1b5bdb2b41 LibWeb+LibWebView+WebWorker: Initialize transport peer pid on Windows
WebWorker control connections can transfer handles from the browser
process to the worker process, including RequestServer and ImageDecoder
transport handles sent during worker startup. On Windows, serializing
those attachments needs the destination process id so DuplicateHandle
and WSADuplicateSocketW can target the peer process. WebWorker was
excluded from the generic helper-process InitTransport handshake,
leaving the transport without a peer pid before any attachment-bearing
message was sent.

Add InitTransport to the WebWorker server endpoint, implement the
server-side peer pid exchange, expose the message type through
WebWorkerClient, and let the shared helper launcher perform the
handshake for workers as it does for other Windows IPC clients.
2026-06-18 04:06:30 +02:00
Tim Ledbetter
7bb200a663 LibWeb: Add fast_is to SVGTextContentElement 2026-06-18 01:27:28 +02:00
Tim Ledbetter
9d359d9d7c LibWeb: Add fast_is to SVGClipPathElement 2026-06-18 01:27:28 +02:00
Tim Ledbetter
7218794aaa LibWeb: Add fast_is to SVGPatternElement 2026-06-18 01:27:28 +02:00
Tim Ledbetter
d86936f09c LibWeb: Add fast_is to SVGGradientElement 2026-06-18 01:27:28 +02:00
Andreas Kling
b583fd3b79 LibWeb: Skip repaint for visual context-only style changes
Let style changes that only rebuild compatible accumulated visual
contexts avoid marking the display list dirty. This lets transform
and nonzero opacity updates send visual context tree updates without
recording a new display list.

Keep repainting changes that affect display-list contents or can change
visual context tree compatibility, including zero-crossing opacity,
transform invertibility crossings, background-attachment, clipping,
mix-blend-mode, and perspective. Schedule accumulated visual context
updates for animations independently of repaint so animated
transform/effect updates keep reaching the document.

Cover compatible visual context reuse, incompatible tree shapes, and the
display-list invalidation cases with focused LibWeb tests.
2026-06-18 00:12:42 +02:00
Andreas Kling
1b8072371b LibWeb: Preserve compatible visual context tree versions
Let accumulated visual context updates keep the previous tree version
when rebuilt with the same shape. Display lists reference visual
context tree versions, so keep compositor-only updates on the old
version unless the tree structure changes.

Add coverage for version reuse and incompatible tree shapes.
2026-06-18 00:12:42 +02:00
Andreas Kling
be5320b67c LibJS: Evaluate ToNumber for out-of-bounds typed array writes
The interpreter's fast path for PutByValue on a typed array treated an
out-of-bounds index as a silent no-op and returned without touching the
value. That is observably wrong: TypedArraySetElement evaluates
ToNumber(value) before checking the index, so a value with a valueOf
side effect must still have that side effect run even when the store is
ultimately discarded.

Fall back to the slow path on an out-of-bounds or otherwise invalid
index instead of reporting success. The slow path runs the full
TypedArraySetElement algorithm, which performs the coercion and then
discards the write. Direct assignment now matches Reflect.set, which
already went through the slow path.

Fixes the staging/sm typed array out-of-bounds ToNumber test262 case
and adds a test-js regression covering direct assignment, Reflect.set,
and Reflect.defineProperty.
2026-06-17 21:24:33 +02:00
Andreas Kling
a3db2d1986 LibJS: Support source text access in JSON.parse revivers
The JSON.parse-with-source proposal (now part of ES2026) gives a
reviver a third "context" argument. For a primitive value that was
not modified by an earlier reviver call, the context has a "source"
property holding the matched JSON source text; for objects, arrays,
and forward-modified values it is an empty object.

We already had JSON.rawJSON and JSON.isRawJSON, but the reviver only
received two arguments. Implement the missing half by building a JSON
Parse Record snapshot while parsing: each primitive records the
trimmed raw token from simdjson, and arrays and objects record their
child records keyed by index and property name. InternalizeJSONProperty
threads the matching record down the tree, creates the context object,
and only attaches "source" when the record's stored value still equals
the live value (SameValue), which suppresses source for values a
reviver replaced or appended.

The record values live in heap storage the GC does not scan, and a
reviver can detach the originals from the object graph mid-walk, so
the snapshot's values are kept rooted for the duration of the walk.

Closes the six json-parse-with-source test262 failures and adds
test-js coverage for primitive source text and forward modification.
2026-06-17 21:24:33 +02:00
Aliaksandr Kalenik
7ca410c66c LibWeb: Stop storing compositor surfaces as display list resources
Compositor surfaces are only used for nested navigables now. The
display list command already carries the CompositorSurfaceId, but
playback still resolved that id through DisplayListResourceStorage and
WebContent exposed IPC for direct surface updates and clears.

Keep published child surfaces as PaintingSurface entries on the
compositor ContextState and pass that map into Skia display list
playback. Publishing and detaching nested contexts now update the parent
cache entirely inside the compositor, so WebContent no longer needs
update_compositor_surface or clear_compositor_surface messages.
2026-06-17 20:20:24 +02:00
Aliaksandr Kalenik
91bcd50224 LibGfx+LibWeb: Store Skia images with display list resources
DisplayListPlayerSkia kept a separate DecodedImageFrameSkiaImageCache
that was pruned during flushes. That made Skia image lifetime
independent of display list resource lifetime, even though resource
storage is what knows when image frames and compositor surfaces are no
longer needed.

Make DisplayListResourceStorage own an opaque stored image-frame
resource that holds the decoded frame and its lazily-created SkImage.
Removing image frames or compositor surfaces now drops the decoded frame
and Skia image together, while transactions still carry only Skia-free
decoded frames.
2026-06-17 19:17:10 +02:00
Aliaksandr Kalenik
e03e407f43 LibWeb: Stop linking ANGLE into WebContent
LibWeb still needs ANGLE GLES headers for WebGL constants and
types, but the host GL entry points now live in the Compositor. Copy
ANGLE compile interface onto LibWeb and stop linking ANGLE through
LibWeb so WebContent no longer inherits that dependency.
2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
54a07a08b4 LibWeb+Compositor: Move OpenGLContext in Compositor namespace 2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
7efdb8a900 LibWeb+Compositor: Move OpenGLContext in Compositor 2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
116668651b LibWeb+Compositor: Avoid canvas readback for canvas drawImage
2D canvas rendering now lives in the compositor, but drawing one canvas
into another still converted the source HTMLCanvasElement into a
DecodedImageFrame in WebContent. That forced a compositor readback for
every drawImage(canvas, ...) call before sending the destination canvas
commands back to the compositor.

Teach the canvas command stream to carry a DrawCanvas command that names
the source canvas surface. The destination 2D context now flushes the
source canvas, records that command, and immediately flushes the
destination command list so the compositor copies the source surface at
the drawImage call boundary. Bitmap sources continue to use DrawBitmap,
and true readback APIs still read pixels explicitly.
2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
f215d9bb9a LibWeb+WebContent: Restore canvas contexts after Compositor loss
Compositor-backed canvas contexts keep their transports tied to a single
Compositor connection. When that connection dies, the 2D backing
storage and WebGL GL objects disappear with it, but WebContent does not
surface the loss to canvas contexts or create fresh host contexts after
reconnect.

Track compositor loss through the WebContent connection, mark WebGL
contexts lost, dispatch the standard context events, and rebuild the
remote proxy when the page opts into restoration. For 2D canvas, queue
the canvas context loss steps, discard the dead backing storage, and
create new storage before firing contextrestored.
2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
a80babffb6 LibWeb+Compositor: Run canvas contexts in the Compositor
Canvas rendering is a major remaining path where WebContent directly
owns GPU-facing drawing state. Back 2D and WebGL canvas contexts with
remote Compositor transports, so WebContent talks to canvas surfaces
through IPC while the Compositor owns the rasterization resources.

This is a large step toward GPU sandboxing because canvas GPU work now
lives behind the Compositor boundary. It also gives OffscreenCanvas the
process-independent canvas plumbing that HTMLCanvasElement now uses,
making worker-owned canvases possible without another WebContent-local
rendering path.
2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
5f0e95de13 Meta+LibWeb+Compositor: Add remote canvas transports
The display list can now refer to canvas ids, but WebContent still had
no channel for creating or updating those canvas resources in the
Compositor. Both 2D and WebGL canvases would have had to grow the IPC
plumbing in the same commit that changes the rendering contexts.

This adds the Compositor-side CanvasHost, WebContent transport objects,
and the IPC/CMake pieces needed to allocate, update, read back, and
destroy remote canvas contexts. The rendering contexts are not switched
over yet, keeping this as plumbing for later commits.
2026-06-17 19:07:32 +02:00
Aliaksandr Kalenik
9a8a7798ec Meta+LibWeb: Generate WebGL command proxy scaffolding
Moving WebGL execution into the Compositor needs a serializable command
stream and a client-side proxy that can queue commands before sending
them over IPC. The existing generator metadata only described direct GL
wrappers, so generated code could not distinguish async commands from
sync calls or object factory methods.

This teaches the WebGL metadata and generators about command streams and
adds the unused LibWeb proxy/list types. No rendering behavior changes
yet; the later host wiring can build on these generated interfaces
without mixing the metadata churn into that commit.
2026-06-17 19:07:32 +02:00