Commit graph

79403 commits

Author SHA1 Message Date
Shannon Booth
2bc0ea3945 Tests/LibWeb: Sync to latest URLPattern WPT test data 2026-06-15 13:45:37 +02:00
sideshowbarker
602e7fe2bd LibGfx: Reject a BMP V5 ICC profile offset that points out of bounds
Problem: A BMP V5 image whose embedded ICC profile offset points past
the end of the file triggers an OOB read.

Cause: The bounds check summed the profile offset, the file-header size,
and the profile size in 32-bit arithmetic. So, a large offset (e.g.
0xfffffff0) wraps the sum back into range and passes the check. The
decoder then returns a span pointing far past the end of the file.

Fix: Compute the sum in 64 bits — so an out-of-bounds offset can no
longer wrap, and the profile’s rejected.

Fixes: https://github.com/LadybirdBrowser/ladybird/issues/9967
2026-06-15 20:19:33 +09:00
sideshowbarker
9bde8a5c88 LibGfx: Avoid undefined behavior on a BMP with an INT_MIN height
Problem: Decoding a BMP whose height is INT_MIN triggered a UBSan error.
A top-down BMP legitimately uses a negative height — and unlike width,
it’s not rejected, so it can be INT_MIN.

Cause: decode_bmp_pixel_data() took the magnitude of the i32 width and
height with abs(). Negating INT_MIN is undefined behavior.

Fix: Widen to i64 before taking the absolute value — so the magnitude of
INT_MIN is representable. The resulting out-of-range dimension is still
rejected by Bitmap::create — so only the undefined behavior changes.

Fixes: https://github.com/LadybirdBrowser/ladybird/issues/9994
2026-06-15 09:44:27 +02:00
sideshowbarker
20b1129352 LibGfx: Fix heap overflow applying Exif transpose to non-square images
Problem: Decoding a non-square image whose Exif orientation is 5
(transpose) writes one pixel past the end of the destination bitmap —
an ASan heap-buffer-overflow in ExifOrientedBitmap::set_pixel.

Cause: oriented_position() mapped orientation 5 by composing the
“flip-horizontally” and “rotate-90-clockwise” helpers. Each helper
mirrors using the source width. But after the rotate, the point is
already in the transposed coordinate space — where the relevant
dimension is the source height. For a non-square image, that composition
produces x-coordinates past the destination width. Only square images
happened to stay in bounds. The destination bitmap is the transposed
size — so the out-of-range column wrote past its allocation.

Fix: Map orientation 5 directly as a transpose across the main diagonal:
source (x, y) to destination (y, x).

Fixes https://github.com/LadybirdBrowser/ladybird/issues/10102
2026-06-15 09:31:12 +02:00
Aliaksandr Kalenik
69654a3a7c Compositor: Use GPU bitmap stores with Direct3D
The compositor already used a GPU surface with bitmap readback when a
Vulkan Skia context existed but no native shared surface path was
available. The new Windows Direct3D backend has the same constraint for
now: it can render with Skia on the GPU, while publication still uses
shareable bitmaps.
2026-06-15 04:50:29 +02:00
Aliaksandr Kalenik
3ded5bdcdf LibGfx: Add a Direct3D Skia backend
With Windows backend selection fixed to Direct3D, LibGfx needs a native
GPU context that can feed Skia directly. Add a Direct3DContext helper
that owns the DXGI adapter, D3D12 device, and direct command queue, then
pass that state to Skia through GrDirectContext::MakeDirect3D..
2026-06-15 04:50:29 +02:00
Aliaksandr Kalenik
d858c7219b Meta: Use Direct3D instead of Vulkan on Windows
Windows has a platform-native GPU stack based around Direct3D and DXGI.
The browser's Windows integration will need to share GPU resources with
Skia, ANGLE, and the UI process through that stack, especially when
backing stores move from bitmap readback to shared handles. Keeping
Vulkan as the Windows backend would put painting on a parallel API that
does not match the resources the rest of the native Windows pipeline
needs to exchange.
2026-06-15 04:50:29 +02:00
Andreas Kling
1f36340419 LibJS: Remove unused C++ local variable wrapper
The Rust bytecode generator only passes local variable names to C++ now,
and no C++ code observes declaration kind metadata from LocalVariable.
Store local names directly as Utf16FlyString values and remove the stale
C++ wrapper type.
2026-06-15 02:41:57 +02:00
Andreas Kling
1979d24783 LibJS: Remove unused bytecode instruction stream iterator
InstructionStreamIterator no longer has any C++ users now that bytecode
block collection has moved to Rust. Remove the iterator and include the
bytecode field types needed by generated C++ instruction definitions
directly in Instruction.h.
2026-06-15 02:41:57 +02:00
Andreas Kling
e5bcffc3d5 LibJS: Move bytecode block counting to Rust
Use the Rust bytecode dumper's basic block collection logic for the
metadata block count. This removes the last C++ bytecode label walk and
lets us delete the generated C++ label and operand visitor helpers.
2026-06-15 02:41:57 +02:00
Andreas Kling
984d3033e9 LibJS: Remove obsolete bytecode dump formatting helpers
The Rust bytecode dumper now formats exception handler labels, raw
operands, builtins, labels, and registers. Remove the C++ dump-only
formatters and flatten Operand to expose only the runtime value-array
layout that C++ still observes.
2026-06-15 02:41:57 +02:00
Andreas Kling
7a6af95db3 LibJS: Move bytecode instruction dumping to Rust
Generate Rust bytecode dump helpers from Bytecode.def and route
Executable::dump() through them for instruction stream formatting.

Add a small Rust runtime::value helper for decoding encoded LibJS
Values so immediate Value operands are formatted on the Rust side. C++
callbacks remain only for local names and GC-backed Value payloads that
still need LibJS object access.

Remove the generated C++ to_byte_string_impl() methods and the old
Instruction::to_byte_string() dispatch. The bytecode dump tests cover
output compatibility.
2026-06-15 02:41:57 +02:00
Andreas Kling
5aac297558 LibWeb: Keep child navigable history updates coherent
Normalize the target step again at the end of applying a history
step, since iframe removal can leave the originally computed target
step unused before the asynchronous application finishes. Let the UI
history snapshot use the same used-step mapping when it serializes a
current item for the UI process.

Handle late child-frame navigation commits whose original nested
history entry disappeared before finalization. Removed iframes have no
live nested history list to update, and initial about:blank still needs
its first real navigation to replace the remaining initial child entry.

Add coverage for iframe pushState before nested history readiness and
for removing and recreating an iframe after an initial same-document
history update.
2026-06-15 01:15:09 +02:00
Aliaksandr Kalenik
5d8880a899 Compositor+WebContent: Initialize WebContent transport peer pid
A WebContent display-list update can send compositor resource
attachments over the WebContent-to-compositor transport. On Windows,
serializing an attachment requires the destination process id, but this
secondary transport never exchanged peer pids before the first message.

That left TransportSocketWindows with m_peer_pid == -1 and hit the
serialize_attachments() verification when WebContent tried to send the
first attachment-bearing compositor update. Add InitTransport to this
endpoint and run it immediately after WebContent creates the compositor
connection, before any other IPC uses the channel.
2026-06-15 00:50:02 +02:00
Shannon Booth
c39ff8eb81 Tests: Attempt to unskip some MacOS IPC related tests
We have since fixed a lot of issues with this implementation, and
have had other worker tests enabled without issue. Let's hope that
the flake issues with these tests have now been fixed.
2026-06-15 00:26:10 +02:00
Shannon Booth
0d656c3027 LibWeb: Record abspos inline static positions as line-box markers
The static position of an absolutely positioned inline child is the
in-flow insertion point on the line where it appears. Previously this
was reconstructed after layout by walking previous siblings for a
line-box fragment. That lookup could match a fragment from an earlier
line and collapse multiple abspos children onto the same position,
especially in white-space preserving content.

Instead, drop a zero-width static-position marker into the line box at
the insertion point when each abspos child is encountered. The marker is
carried through normal line post-processing, including float intrusion,
text-align, justification, trailing-whitespace trimming and ellipsis, so
the final static position is resolved from the line itself.

Resolve marker-only trailing lines before removing them, so they can
provide static position without contributing line height.
2026-06-14 22:12:06 +02:00
Shannon Booth
96aa4b3ad3 LibWeb: Only apply CSS transforms to transformable elements
Add Node::is_transformable() per the CSS Transforms spec and gate
transform handling on it, so non-replaced inline boxes are no longer
transformed.
2026-06-14 22:12:00 +02:00
Shannon Booth
a8cb98ccf7 Tests: Support WPT reftests with multiple references
Store reftest expectations as a list of match/mismatch reference URLs
and evaluate each reference in sequence.

This lets test-web run WPT reftests that specify multiple reference
relations, such as tests with both match and mismatch links.
2026-06-14 22:12:00 +02:00
Shannon Booth
de90aeb07c Tests/LibWeb: Re-import floats reftests with their mismatch references
Re-import these tests now that the importer supports multiple
references, so their mismatch *-notref.xht files are present instead
of pointing at unimported paths.
2026-06-14 22:12:00 +02:00
Shannon Booth
06f4ac367e Meta: Support importing WPT reftests with multiple references
Collect all match and mismatch links when identifying WPT reftests
instead of rejecting tests with more than one reference.

Map and rewrite every imported reference URL so tests with both match
and mismatch expectations can be imported.
2026-06-14 22:12:00 +02:00
Andreas Kling
ea72bd3863 Tests: Wait for mirrored history before UI traversal
Wait for the WebDriver session history test to observe the UI-process
mirror after a same-document pushState setup before it starts testing a
browser UI history traversal.

The script-visible URL changes before the asynchronous session history
snapshot reaches the UI process, especially in sanitizer CI. The test
already needs the UI and WebContent histories to match at this point, so
wait for that condition directly instead of sampling the mirror at once.
2026-06-14 21:23:28 +02:00
Andreas Kling
a29e1f5cf3 LibJS: Remove unused Executable::dump_to_string
The bytecode dump path only writes directly to stderr now.
Remove the unused string-returning dump API.

Also remove the private helper mode that only existed for that API.
2026-06-14 20:27:59 +02:00
Andreas Kling
ef8ac6ea7d LibJS: Remove unused C++ bytecode block classes
The Rust bytecode generator now owns basic block construction.
The old C++ BasicBlock class no longer has any users.

Label no longer needs to translate from BasicBlock.
Remove the now-empty Label.cpp from the build as well.
2026-06-14 20:27:59 +02:00
Andreas Kling
0af548b27d LibJS: Sync AsmInt program counter before slow paths
Move the execution context program counter update from ASM_TRY() to the
generated slow-path call boundary. Slow paths still enter C++ with the
current bytecode offset visible to stack and source location code, while
ASM_TRY() only handles completion unwrapping and exception dispatch.
2026-06-14 20:27:59 +02:00
Andreas Kling
ad7002ba99 LibJS: Pass instruction pointers to AsmInt slow paths
Have generated AsmInt calls pass the current instruction pointer as a
third argument to slow-path handlers. This lets the C++ handlers use a
typed Op pointer directly instead of refetching bytecode from the VM and
recomputing the instruction address from the program counter.
2026-06-14 20:27:59 +02:00
Andreas Kling
213403542c LibJS: Remove AsmInt slow path stats collection
Remove the optional slow path hit counters from AsmSlowPaths.cpp. This
also drops the registration call from the AsmInt entry path, leaving
slow paths focused on executing the out-of-line instruction behavior.
2026-06-14 20:27:59 +02:00
Andreas Kling
97a6807ffa LibJS: Remove JS_BYTECODE_DEBUG
Remove the stale bytecode execution debug hook from Interpreter.cpp now
that bytecode dispatch always enters AsmInt directly. The remaining
bytecode dump flag is separate and still used by parser/codegen paths.
2026-06-14 20:27:59 +02:00
Andreas Kling
8fee268851 LibJS: Call AsmInt directly from run_executable
Remove the empty AsmInterpreter wrapper and the VM::run_bytecode()
trampoline now that the bytecode interpreter only enters AsmInt. Move
the stack-limit check and generated assembly entry call into
run_executable(), then drop the stale wrapper source file and includes.
2026-06-14 20:27:59 +02:00
Andreas Kling
060ba41a84 LibJS: Remove unused VM interpreter helpers
Remove VM helpers that became unused after bytecode execution stopped
using the generic interpreter path. The AsmInt entry path now owns these
transitions directly.
2026-06-14 20:27:59 +02:00
Andreas Kling
2aa9535635 LibJS: Move final simple opcodes into AsmInt
Move the remaining simple SetLexicalEnvironment, IsCallable and
LeavePrivateEnvironment opcodes into the AsmInt DSL. These handlers do
not need C++ slow-path support.
2026-06-14 20:27:59 +02:00
Andreas Kling
c1415a544f LibJS: Split AsmInt slow paths out of Interpreter.cpp
Move the C++ slow paths used by AsmInt into their own translation unit.
This leaves Interpreter.cpp focused on VM entry and bytecode metadata
helpers instead of carrying the slow-path implementation body.
2026-06-14 20:27:59 +02:00
Andreas Kling
6e6726b612 LibJS: Move instruction bodies into AsmInt slow paths
Move the remaining bytecode instruction implementations out of
execute_impl() and into AsmInt slow paths. Remove the execute_impl()
bodies once their only caller is gone, leaving instruction classes as
bytecode data containers.
2026-06-14 20:27:59 +02:00
Andreas Kling
7c8e3732c7 LibJS: Remove AsmInt generic fallback dispatch
Remove the generic fallback dispatch once every bytecode opcode has a
real AsmInt handler. Invalid dispatch table entries still route through
the fallback function as a defensive trap.
2026-06-14 20:27:59 +02:00
Andreas Kling
5bc002d71c LibJS: Move property and call handlers into AsmInt
Move property access, iterator, object property iterator, import, class
and argument-array call opcodes out of the generic fallback path. Keep
the semantic work in C++ slow paths and dispatch to them from AsmInt.
2026-06-14 20:27:59 +02:00
Andreas Kling
058f63efd2 LibJS: Move control and binding handlers into AsmInt
Move the remaining control-flow, conversion, creation, delete, binding,
private-name and environment-related fallback handlers into AsmInt. This
keeps the generic fallback path shrinking while leaving complex behavior
in C++ slow paths.
2026-06-14 20:27:59 +02:00
Andreas Kling
fff128a8cc LibJS: Move simple bytecode handlers into AsmInt
Move simple fallback handlers into the AsmInt DSL or dedicated slow-path
calls. This covers straightforward allocation, environment setup,
argument creation, completion state, template object, async iterator and
function allocation opcodes.
2026-06-14 20:27:59 +02:00
Andreas Kling
5ca52d2a77 LibJS: Remove generic bytecode interpreter
Remove the C++ bytecode interpreter dispatch loop now that AsmInt is the
only bytecode execution engine. Keep the existing AsmInt fallback path
for instructions that have not yet been moved into assembly or C++ slow
path handlers.
2026-06-14 20:27:59 +02:00
Tim Ledbetter
48f845b3b4 LibWeb: Record SVG hit-test geometry in absolute coordinates
Previously, SVG path hit geometry was recorded in the enclosing <svg>
element's local coordinate space rather than absolute page coordinates,
so SVG shapes were only hittable when the <svg> sat at the document
origin
2026-06-14 17:45:28 +02:00
Tim Ledbetter
5b1120d0f4 LibWeb: Hit-test SVG paths against their fill geometry
Previously, hit testing for SVG paths used the path's bounding box.
2026-06-14 17:45:28 +02:00
sideshowbarker
c2db5c0dcb LibWeb: Fix a crash when selecting across an element with no layout box
Problem: Crash when dragging a text selection across an element with no
layout box (e.g., a display:contents element).

Cause: set_user_selection() looks for a user-select:contain ancestor by
walking up the tree via two while-loop conditions that called
layout_node()->user_select_used_value() for each element. But elements
without layout boxes have no layout nodes. So that can dereference null.

Fix: Check layout_node() in the tree-walking while conditions.

Fixes: https://github.com/LadybirdBrowser/ladybird/issues/10062
2026-06-14 17:40:21 +02:00
Andreas Kling
67030ceead LibWebView: Complete WebDriver same-document traversals
Complete pending WebDriver navigation waits when WebContent confirms
that a same-document history traversal step was applied. These
traversals do not always produce a load event, and waiting only for a
later session history snapshot could let the WebDriver command return
before the UI had observed the applied step.

This keeps the WebDriver session history test from racing into later
commands while a previous same-document traversal is still settling.
2026-06-14 17:38:44 +02:00
Andreas Kling
b26ee62819 WebContent: Wait for WebDriver history traversal completion
Keep WebDriver Back and Forward waiting after accepted history
traversals, even when the traversal does not change the top-level
entry. UI-owned session history can still complete same-document
traversals asynchronously, so returning immediately let later
commands race with a pending traversal and observe stale history
state.

The WebDriver session history test covers this path. Give that test a
larger CTest timeout so sanitizer CI has enough room for the full
script.
2026-06-14 17:38:44 +02:00
Andreas Kling
69f1c0e432 LibWeb: Avoid invalid WebDriver key modifier values
Clear key modifier bits through their underlying integer values when
releasing WebDriver keys. The enum bitwise complement can otherwise
materialize values outside the KeyModifier enumerators, which trips
UBSan when browser history shortcut actions release Alt or Meta.

The WebDriver session history test covers this through browser shortcut
back and forward actions.
2026-06-14 17:38:44 +02:00
Andreas Kling
fd2e9e0fb3 Tests/LibWebView: Cover browser history recovery
Add a browser-driven WebDriver scenario for process swaps, renderer
crashes, nested frame history, reloads, and POST replacement cases. The
test drives the browser through the same UI-owned history paths used by
real back and forward actions.

Cover canceled navigations, javascript: no-op loads, source-document
traversal checks, and restored scroll state after crash recovery.
2026-06-14 17:38:44 +02:00
Andreas Kling
0aaae1ac76 Tests/LibWeb: Cover UI-owned session history
Teach test-web to expose the UI-process history dump. Add focused
navigation tests for same-document traversal, fallback traversal, and
cross-document browser back and forward behavior. The expectations
assert document state and the UI-owned history snapshot.
2026-06-14 17:38:44 +02:00
Andreas Kling
24f37c6732 LibWebView: Keep browser history in the UI process
Use the LibWebView history mirror to preserve traversable session
history across WebContent process swaps. WebContent reports snapshots to
the UI process, and new renderers can be seeded from the mirror.

Browser back and forward now resolve through the UI-owned used history
steps. WebContent still runs the spec traversal path when the current
renderer has enough matching state to do so.

Handle canceled and no-op UI navigations without leaving speculative
history entries or pending WebDriver waits behind. Preserve traversal
precheck state across synchronous IPC shutdown, and avoid overwriting a
restored target entry's persisted scroll state before the document has
adopted that entry.
2026-06-14 17:38:44 +02:00
Andreas Kling
44ae6d3438 Tests/LibWebView: Cover the UI history model
Add fast coverage for merging WebContent snapshots into the UI-owned
session history mirror. The tests exercise seeding, nested histories,
reload state, replacement entries, and traversal target selection.
2026-06-14 17:38:44 +02:00
Andreas Kling
78bb7b8d45 LibWebView: Add a UI session history model
Add a browser-side model for top-level history entries and history step
coordinates. This gives the UI process a structure to mirror WebContent
history across process swaps.

Add debug dumping support alongside the model so traversal state can be
inspected while working on back and forward behavior.
2026-06-14 17:38:44 +02:00
Andreas Kling
9e2ec2dc5c LibWeb: Add session history serialization support
Add structured helpers for the history data mirrored by LibWebView.
Cover POST resources, history state, navigation API state, scroll
positions, and entry metadata.

Keep this below the UI model so browser-side history code can move data
through typed objects instead of ad-hoc strings.
2026-06-14 17:38:44 +02:00
Callum Law
6c13a3f37d LibWeb: Clear paintables for continued layout nodes in removed_from
Block-in-inline splitting can create multiple layout nodes per DOM node,
only the last of which is tracked in DOM node's `m_layout_node`.

Previously `DOM::Node::removed_from` only cleared paintable caches for
the tracked layout node, leaving the other nodes to have their caches'
cleared during the next layout update.

This was fine prior to 9340d2d, when layout nodes kept the relevant DOM
nodes alive, however, layout nodes now only keep weak references so
these DOM nodes can be GC'd before the paintables' caches are removed
causing a crash.

We now clear the paintables for the tracked layout node and it's
continued nodes during `removed_from` while the relevant DOM node is
still alive.
2026-06-14 19:39:15 +09:00