Commit graph

17524 commits

Author SHA1 Message Date
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
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
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
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
Callum Law
565fd82879 LibWeb: Run removed_from for descendants when shadow root removed
This is only relevant for UA-internal shadow roots (specifically those
created by `HTMLInputElement` and `MediaControls`) since they are the
only ones which can be removed from their hosts.

Previously after removing a shadow root from it's host we left it's
descendants' paintables' caches to be 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 run the `removed_from` steps for the shadow tree's elements
before removing the shadow root from its host in line with how we handle
removal of DOM nodes in other cases - this clears their paintables'
caches immediately while the DOM nodes are still alive.

Fixes an intermittent crash in Layout/input/pdf-viewer.pdf
2026-06-14 19:39:15 +09:00
Aliaksandr Kalenik
ac0e0833e7 LibJS: Enable AsmInterpreter on Windows
Enable the asm interpreter on Windows for both x86_64 and ARM64. The
x86_64 backend now emits COFF assembly using the Win64 ABI. It handles
argument registers, non-volatile register saves, shadow space, SEH
unwind directives, and raw-native sret lowering. Its epilogue is left
as normal x64 instructions instead of ARM64-style SEH epilogue
directives, which older ClangCL assemblers reject.

The AArch64 backend now emits Windows ARM64 COFF assembly as well,
including COFF relocations, .rdata dispatch tables, SEH unwind metadata,
frame sizing, handler alignment rules, and raw-native sret lowering.
CMake selects COFF for Windows asmint output and enables generation for
both Windows architectures.

AsmIntGen coverage checks the Windows x64 epilogue output and the ARM64
COFF unwind output. test-js and test262 have no regressions with asmint
enabled compared with the C++ interpreter.
2026-06-14 05:01:27 +02:00
Andreas Kling
f52852cd83 LibWeb: Avoid sorting InvalidationSet hashes
Keep the cached equality precheck, but compute the set hash with
order-independent aggregate values instead of materializing and sorting
the per-property hashes.

This avoids allocation and sorting in a hot equality path while leaving
correctness to the existing full property comparison after hash matches.
2026-06-13 23:41:39 +02:00
Andreas Kling
0fca7d1a6e LibCore: Own addrinfo results without OwnPtr
Store the getaddrinfo result pointer directly in AddressInfoVector and
free it with freeaddrinfo from the destructor. This keeps the special
cleanup logic local to LibCore instead of relying on OwnPtr custom
deleter support.
2026-06-13 22:49:15 +02:00
Andreas Kling
2464e2ebfa LibWeb: Allocate layout used values with bump allocator
Store UsedValues separately from the sparse layout index pages. The
pages now hold pointers for O(1) lookup by layout index, while the
values are allocated from a uniform bump allocator owned by the paged
store.

This keeps pointer stability for containing-block links and avoids
placing large Optional<UsedValues> slots directly in every page.
2026-06-13 22:49:00 +02:00
Tim Ledbetter
b0c25736f9 LibWeb: Scale image-set() natural size by the selected resolution
The <resolution> of the chosen image-set() option overrides the image's
natural resolution, so the image-set()'s natural dimensions are the
selected image's pixel dimensions divided by that resolution.
2026-06-13 21:27:40 +02:00
Aliaksandr Kalenik
255ca9d99d LibWeb: Unify display list command playback hooks
Switch DisplayListPlayer and DisplayListPlayerSkia to overloaded
play_command() methods generated from ENUMERATE_DISPLAY_LIST_COMMANDS.
2026-06-13 20:41:03 +02:00
Aliaksandr Kalenik
21fcafe605 LibGfx: Reduce Painter to the bitmap-compositing interface
After 2D canvas stops using Gfx::Painter as its drawing backend, the
base Painter interface only needs to describe bitmap compositing work
that still happens outside PainterSkia. Narrow the interface to
clear_rect, fill_rect and draw_bitmap, which covers GIF/APNG frame
compositing, CSS cursor bitmap painting, canvas readback and the Android
UI blit.
2026-06-13 20:41:03 +02:00
Aliaksandr Kalenik
73352ef2d2 LibGfx+LibWeb: Paint 2D canvas via record-and-replay
Move CanvasRenderingContext2D onto the same record-and-replay model that
the compositor-process path will use, but keep playback local for now.
Draw calls append CanvasCommandList entries and flush/readback paths
replay the commands into a local CanvasCommandPlayer-owned surface.
2026-06-13 20:41:03 +02:00
Aliaksandr Kalenik
d7cb7c4c15 LibGfx: Add CanvasCommandPlayer
Once canvas commands can be sent to another process, the receiver needs
an endpoint that owns the persistent surface and validates command data
before it reaches Skia. Add CanvasCommandPlayer for that role.

The player replays CanvasCommandList deltas through concrete PainterSkia
APIs and keeps painter state across play() calls, matching the way a
compositor-hosted canvas surface will accumulate mutations over time.
Initialize ops allocate or resize the backing surface so creation,
resize and repaint all flow through the same command stream.
2026-06-13 20:41:03 +02:00
Aliaksandr Kalenik
714cf827db LibGfx: Add CanvasCommandList
Moving 2D canvas rasterization into the Compositor process needs a wire
format for canvas mutations that does not depend on LibWeb state. Add
CanvasCommandList as an apply-once log of drawing operations whose
operands are Gfx value types and whose IPC encoders can be shared by
WebContent and the compositor side.
2026-06-13 20:41:03 +02:00
Andreas Kling
956a2b96d5 LibWeb: Allocate layout and painting objects with mimalloc
Add class-local allocation macros for operator new/delete through AK's
malloc helpers. The macros can optionally choose a HeapPartition.
Add Layout and Painting partitions, plus basic partition stats helpers.

Use the new partitions for LibWeb layout and painting object hierarchies
and layout-state side data.
2026-06-13 19:08:08 +02:00
Andreas Kling
f47b6f3270 LibWeb: Reduce CSS parser token memory usage
Store CSS token payloads in a variant so each token only carries the
state needed by its type. Keep delimiter, number, hash, string, and
dimension data separate instead of storing every possible payload on
every token.

Use a smaller component-value token for function and block boundary
metadata. These component values only need token type, original source
text, and source positions, so avoid embedding full token payload
storage inside every Function and SimpleBlock.

Shrink CSS source positions to explicit 32-bit counters. Guard the C++
and Rust tokenizer paths against overflow. Add size assertions for the
hot Token and ComponentValue types so future growth is intentional.
2026-06-13 14:57:52 +02:00
Andreas Kling
49730156ae LibWeb: Avoid media rule reevaluation for matchMedia
Separate MediaQueryList change reporting from stylesheet media rule
invalidation. Creating matchMedia() objects evaluates their own baseline
state, but should not make the next style update walk all active
stylesheets when the media environment has not changed.

This avoids continuous stylesheet media query reevaluation during
YouTube video playback, where repeated matchMedia() creation can make
style flushes do unnecessary work.
2026-06-13 14:00:53 +02:00
Shannon Booth
790b9bd36a LibWebView: Add async cookie deletion internals
Add Internals.deleteAllCookies(), backed by an async WebContent to
browser request and ack pair. CookieJar can now clear transient and
persisted cookies. Note that we only delete all cookies associated
with the current URL so that tests are able to run in parallel with
one another without impacting shared cookie state.
2026-06-13 10:18:33 +02:00
Aliaksandr Kalenik
5b856595b3 Meta+LibWeb/WebGL: Route all GL calls through generated GLFunctions
LibWeb's WebGL implementation currently reaches ANGLE by calling glFoo()
throughout the WebGL context and extension code. That ties the WebGL
spec layer to the concrete GL executor. A future backend that records
operations, sends them to another process, or executes them from the
Compositor would otherwise need to duplicate the WebGL logic or edit
every call site again.

Introduce GLFunctions as an explicit boundary between WebGL semantics
and GL execution. GLFunctions.json lists the GL entry points used by the
implementation, and the generator emits one forwarding method per entry
point. OpenGLContext implements those methods today, so the current
in-process ANGLE path keeps the same behavior while all callers go
through a single replaceable interface.

That boundary is needed before canvas/WebGL rendering can move to the
Compositor: the WebGL context code can keep doing validation, state
tracking, and spec-visible error handling in LibWeb, while a later
implementation can record the same GL calls and replay them where the
canvas surface is produced. The JSON source also gives the recorder and
replayer one shared description of argument shapes, avoiding two
hand-written views of the GL API drifting apart.
2026-06-13 01:58:43 +02:00
Aliaksandr Kalenik
60f27523c6 LibIPC: Adopt Mach OOL payloads on receive
Mach transport already sends payloads as out-of-line virtual-copy
regions, but the receive path immediately copied each payload into a new
Vector and deallocated the kernel mapping. That made the IPC IO thread
touch every byte before the main thread could decode the message.

Add ReceivedMessageBytes as the raw-message byte storage and let the
Mach transport adopt the OOL region directly. The mapping now lives
until the raw message storage is destroyed, so invalid descriptor paths
and normal queue teardown both release it through the same destructor.
Socket transports keep their existing receive copy path by wrapping
vectors in the same storage type, and the direct raw-message consumers
now decode from its ReadonlyBytes view.
2026-06-13 00:27:57 +01:00
Aliaksandr Kalenik
f0ed472429 LibIPC: Move IPC payloads through post_message
MessageBuffer::transfer_message() handed a MessageDataType to transport
APIs that accepted Vector<u8> const&. That forced the inline-capacity
vector to be materialized as a plain Vector<u8>, and the Mach transport
then copied the same payload again into its pending-send queue.

Make the transport API take MessageDataType by value and pass the
encoded buffer with take_data(). The Mach pending queue now stores the
same type so the payload can move directly to the IO thread. The socket
transport keeps queued messages as owned headers plus moved payloads
instead of copying the payload into an AllocatingMemoryStream, while
preserving the existing chunked send and fd acknowledgement behavior.
2026-06-13 00:27:57 +01:00
Tim Ledbetter
45ca0c1158 LibWeb: Skip meta http-equiv processing outside a document tree
The pragma directives specification steps should only run when a meta
element is inserted into the document, meaning it is in a document tree
after the insertion steps have run. We previously ran the pragma
algorithms for any insertion, so inserting a meta element with
`http-equiv=content-language` into a detached subtree dereferenced a
null document element.
2026-06-13 10:51:37 +12:00
Tim Ledbetter
b8ff139f9c LibCompress: Remove PackBitsDecoder
This is no longer used.
2026-06-12 22:37:49 +02:00
Tim Ledbetter
3cddcc8461 LibGfx+LibWeb: Remove TIFF image decoding
This is no longer widely supported by other engines.
2026-06-12 22:37:49 +02:00
Tim Ledbetter
6224045e5f LibGfx: Extract Exif parsing from the TIFF decoder 2026-06-12 22:37:49 +02:00
Andreas Kling
f619caf621 LibGfx: Preserve imported Linux DMABUF handles
Keep the Linux DMABUF handle alongside the bitmap wrapper when imported
shared images reach the UI process. This lets consumers import the same
GPU backing store directly instead of only reading it through the mapped
bitmap.

Also require exported Vulkan shared images to be sampleable, since the
Qt Vulkan presentation path needs to sample compositor backing stores.
2026-06-12 21:45:22 +02:00
Tim Ledbetter
b4b0233ba1 LibSandbox: Permit faccessat2, faccessat and fstatfs
SDL enumerates connected input devices through libudev whenever a
device is added or removed, which probes per-device metadata using
`faccessat2` and `fstatfs`. These calls run after the seccomp filter is
installed, and neither syscall was permitted, so connecting a gamepad
killed the WebContent process with SIGSYS. We now permit `faccessat`
alongside `faccessat2` because glibc's `faccessat` wrapper falls back
to it on kernels without `faccessat2`.
2026-06-12 21:44:10 +02:00
Andreas Kling
6134119353 LibWeb: Keep non-subject :has() dependency sticky
Keep the non-subject :has() affected bit across element style
recomputation. This bit can be discovered while matching descendant
selectors, and recomputing the anchor itself may not revisit those
selectors before a later mutation needs the dependency for targeted
:has() invalidation.

This avoids stale descendant style after targeted :has() invalidation
when a previous recompute cleared the anchor-side dependency metadata.
Repeated style invalidation tests cover the previously flaky case.
2026-06-12 15:13:29 +02:00
Andreas Kling
a0459a3ff3 LibWeb: Avoid broad invalidation for nth-child filters
Property invalidation inside :nth-child(... of ...) used to become a
whole-subtree invalidation plan. That is broader than needed for
property changes that only affect the filtered sibling list, such as
:has() becoming true or false for one sibling.

Add an invalidation plan bit that marks the element and structurally
affected siblings instead. Keep whole-subtree invalidation when a
stronger plan already requires it, and cover both :nth-child and
:nth-last-child filters with :has() regression tests.
2026-06-12 15:13:29 +02:00
Andreas Kling
8d75e310c5 LibWeb: Target structural pseudo-class match sets
Use structural-position pseudo-classes as subject match filters while
building style invalidation plans. Selectors such as `.menu:has(> .flag)
> :first-child` can then carry a concrete right-hand match set instead
of widening the `:has()` invalidation plan to the whole subtree.

Keep these pseudo-classes out of trigger-property sets since structural
topology mutations are handled separately. This avoids adding unrelated
cold topology recomputes while still letting the affected boundary
children be invalidated directly.

Add a regression test that mutates the child class used by `:has()` and
asserts that the old whole-subtree path does not produce excessive no-op
style recomputations.
2026-06-12 15:13:29 +02:00
Andreas Kling
baaaea6cf1 LibWeb: Reduce over-invalidation for :has() selectors
Feature-filter :not() arguments in :has() when the same compound also
has a concrete tag, id, class, or attribute selector. Bare negations
still stay conservative, but anchored negations no longer make unrelated
subtree mutations walk every :has() candidate.

Also avoid installing the whole-subtree :has() fallback for rightmost
complex :is()/:where() arguments that only use descendant or child
combinators. Keep the fallback for non-rightmost and sibling-combinator
cases where the existing plan cannot represent the nested selector
context.

Add counter-based style invalidation coverage for both cases.
2026-06-12 15:13:29 +02:00
Andreas Kling
4c87227078 LibWeb: Track interaction pseudo-classes in :has() metadata
Record hover, focus, focus-visible, focus-within, and target pseudo
classes in :has() invalidation metadata. This lets the existing
property invalidation path schedule :has() ancestor invalidation only
for scopes whose :has() selectors mention the changed pseudo-class.

Interaction pseudo-class invalidation previously scheduled :has()
ancestor invalidation for every style scope containing any :has()
selector. That kept selectors like .wrapper:has(:focus) * correct, but
also caused unrelated hover and focus changes to fan out through broad
:has() descendant invalidation rules.

Update style invalidation coverage so unrelated hover changes avoid the
extra :has() walk, while a descendant :has(:focus) rule still restyles
its affected descendants when focus changes.
2026-06-12 15:13:29 +02:00
Jelle Raaijmakers
de664c4c12 LibWeb: Restore context after culled display list effects
Effect culling can stop a visual context switch after applying
some ancestor contexts. The player left those contexts on the painter
stack even though the target command was skipped.

Restore the painter stack back to the common ancestor when effect
culling aborts the switch.
2026-06-12 04:59:57 +01:00
Jelle Raaijmakers
db04e1b819 LibWeb: Annotate compute_transform() with CSS Transforms 2 steps
Quote the transformation matrix computation steps from the spec
verbatim, which documents that we do not yet apply the offset property
(step 6).
2026-06-12 01:10:24 +02:00
Jelle Raaijmakers
b06cbbf81e LibGfx+LibWeb: Use matrix helpers in TransformationStyleValue::to_matrix
Using the new perspective_matrix() helper resolves a FIXME in
AccumulatedVisualContext as well.
2026-06-12 01:10:24 +02:00
Jelle Raaijmakers
f1ade8186a LibWeb: Drop unused include from PaintableBox.h 2026-06-12 01:10:24 +02:00
Jelle Raaijmakers
7390818b5a LibWeb: Apply the z component of transform-origin
compute_transform() resolved transform-origin to a 2D point, so 3D
rotations pivoted around the element's own plane. Build the conjugation
T(0, 0, z) * M * T(0, 0, -z) into the matrix instead; this composes
with the 2D origin at paint time into the full 3D conjugation.
2026-06-11 22:13:24 +02:00
Sam Atkins
4050c32dab Everywhere: Make use of Badge with multiple or derived types
Now that Badge can have multiple types, and a Badge of a derived class
can convert into a Badge of the superclass, we can simplify a few method
signatures and overloads.
2026-06-11 21:55:56 +02:00
Zaggy1024
ae04222247 LibMedia: Don't display video frames that are late
Frames are considered late if the time is ahead by half their duration.
The fudging is necessary because Matroska (and perhaps other formats)
store their frame durations in different time units than their
timestamps.

Skipping these should make it clear when decoding is running behind,
instead of displaying the video in slow motion while audio runs at a
normal rate.

To give an accurate counting for video playback quality when it is
implemented, we'll most likely want to count all pulled frames in an
update as dropped if the last frame is dropped. Otherwise the frame
drop count will only increase at the display rate when decoding is
continually running behind.
2026-06-11 21:49:55 +02:00
Zaggy1024
c58b9be7d5 LibMedia: Stop clearing video sinks' frames early on moving seeks
This is already handled by the seeking state enum later. We could end
up displaying nothing if MovedPosition isn't immediately followed by a
displayable frame.
2026-06-11 21:49:55 +02:00
Sam Atkins
2629c36dcc LibWeb/HTML: Make disabled select disable its option/optgroup children
Corresponds to:
f7b4402195
2026-06-11 19:07:27 +02:00
Sam Atkins
e3c1fb99d1 LibWeb/HTML: Add resource timing URL to iframes
Corresponds to:
9ef207c159
...but also fills in some FIXMEs we already had.
2026-06-11 19:07:27 +02:00
Sam Atkins
8f32063bd1 LibWeb/HTML: Update image naturalWidth/naturalHeight spec steps
Partly corresponds to:
4ff60b0849

We don't actually implement image densities yet, but this gives us a
FIXME as a clear point to implement that.
2026-06-11 19:07:27 +02:00
Sam Atkins
d501148f46 LibWeb/HTML: Break up step 15 of "update the image data"
Corresponds to:
fc559a5fd5

No code changes.
2026-06-11 19:07:27 +02:00
Sam Atkins
7158294dfb LibWeb/HTML: Correct button activation steps to use element not this
Corresponds to:
60c8816e32

Spec only, no code changes.
2026-06-11 19:07:27 +02:00
Sam Atkins
c60134158c LibWeb/HTML: Don't prepare_script() when src attribute is removed
Corresponds to:
c22fb1b32c

We already behaved this way, this just brings us in line with the spec.
2026-06-11 19:07:27 +02:00
Sam Atkins
0b9e59f61f LibDevTools: Allow editing Web Storage
Firefox sends the same storage actor mutation requests for Web Storage
that it uses for cookies. Handle addItem, editItem, removeItem, and
removeAll for localStorage and sessionStorage actors.

Apply the changes through the browser-process storage jar and emit the
matching store update packets so the Storage panel stays current after a
DevTools-initiated edit.
2026-06-11 16:08:33 +01:00
Sam Atkins
a75e9f23db LibWeb+LibDevTools: Report Web Storage changes
Firefox keeps the Storage panel current by sending store update packets
when localStorage or sessionStorage changes. Forward successful Web
Storage mutations to the storage actors and emit the matching update or
clear packet.

Use listener IDs for storage updates so the local and session storage
actors can subscribe independently.
2026-06-11 16:08:33 +01:00
Sam Atkins
ddb4bdadd7 LibDevTools: Populate DevTools Web Storage
Firefox exposes localStorage and sessionStorage through the same
storage actor protocol used by cookies. Add matching resources for the
current tab so the Storage panel can list key/value pairs.

Read the values through WebContent rather than directly from the
browser process. Session storage lives in LibWeb, and using the same
path for both stores keeps the actor independent of the backing store.
2026-06-11 16:08:33 +01:00
Sam Atkins
5b5f848689 LibDevTools: Make ErrorOr -> JsonValue helpers public
We want these for local/session storage too, so avoid duplicating them.
2026-06-11 16:08:33 +01:00
Sam Atkins
9e4cd527aa WebContent+LibWebView: Add dumping for session storage 2026-06-11 16:08:33 +01:00
Shannon Booth
ecb6c90aeb LibWeb: Track CORS-cross-origin image data for canvas tainting
Propagate the CORS-cross-origin state from image fetch responses through
SharedResourceRequest, ImageRequest, and the available image cache.

Use that state when drawing HTML images to canvas so cross-origin image
data taints the canvas correctly.
2026-06-11 17:01:48 +02:00
Sam Atkins
aa4139d002 LibDevTools: Allow adding and removing DevTools cookies
Firefox enables the Storage panel cookie toolbar from the storage traits
and calls addItem, removeItem, removeAll, or removeAllSessionCookies
for the selected host.

Advertise those operations and route them through the existing cookie
mutation delegate. Deletions reuse the visible storage host matching so
bulk actions stay scoped to the cookie tree item Firefox selected.
2026-06-11 15:03:47 +01:00
Sam Atkins
4113968e77 LibDevTools: Allow editing DevTools cookies
Firefox sends editItem when a cookie table cell is changed. Handle
that request by locating the original cookie, applying the edited
field, and forwarding the replacement through the delegate mutation
hook.

Return Firefox-style errorString values so invalid edits can be
rejected without changing the table contents.
2026-06-11 15:03:47 +01:00
Sam Atkins
76a10bb82d LibHTTP: Expose cookie date parser
DevTools needs to parse the same cookie expiry timestamp syntax that
Set-Cookie accepts. Expose the existing RFC6265 cookie-date parser so
callers do not need to duplicate a stricter HTTP-date parser.
2026-06-11 15:03:47 +01:00
Sam Atkins
11b053b154 LibWebView: Add DevTools cookie mutation helpers
DevTools needs to edit and delete cookies from the browser process. Add
a small mutation surface to CookieJar and expose it through the DevTools
delegate while preserving the existing cookie notification path.
2026-06-11 15:03:47 +01:00
Sam Atkins
47204bd3dd LibDevTools: Report cookie storage changes
Firefox keeps the Storage table current through storesUpdate messages
from the storage actor. Forward browser cookie change notifications to
the cookies actor and classify visible rows against a fresh cookie
snapshot.

The existing cookie-change notifications report cookies that are
relevant to a specific page, whereas DevTools wants all cookies
relevant for a host, so we end up having to provide two different sets
of cookies to `notify_cookies_changed()`.
2026-06-11 15:03:47 +01:00
Sam Atkins
20f922cbdb LibWebView+LibDevTools: Populate DevTools cookies
Firefox asks the cookies actor for rows after selecting a Storage host.
Read the browser cookie jar through the DevTools delegate and serialize
matching cookies with the fields Firefox expects.

This keeps mutation support disabled, but makes existing cookies visible
in the Storage panel.
2026-06-11 15:03:47 +01:00
Sam Atkins
deec1ec2c3 LibDevTools: Add cookie storage actor
Firefox discovers Storage panel data through watcher resources. This
adds a read-only cookies actor with the fields and empty store response
expected by the Storage panel.

Mutation traits are reported as unsupported for now.

DevTools storage resources all have a "host" key derived from the URL,
which we produce in `storage_host_for_url()`.
2026-06-11 15:03:47 +01:00
Sam Atkins
b2724268fe LibWebView: Notify cookie-change listeners after changing them
Cookie listeners may query the jar while handling a notification. For
example, DevTools does this when the Storage panel computes whether a
cookie was added, changed, or deleted.

Insert the cookie before sending the notification, so that listeners see
the new state, not the old one.
2026-06-11 15:03:47 +01:00
Andreas Kling
31ffb2f214 LibWeb: Use the id cache for document element get_element_by_id()
ParentNode::get_element_by_id() only used the cached id-to-element map
when called on a document or shadow root; on any element it fell back
to a linear walk of the subtree. The document element's inclusive
subtree contains every element in the document, so the document's
cache gives the same answer.

This matters because SVGSVGElement::children_changed() resolves the
document URL fragment with get_element_by_id() on itself whenever the
document URL has a fragment. SVG sprite sheets are typically fetched
via URLs like sprite.svg#icon-name, and the sprite's outermost svg
element is its document element, so every child appended during
parsing rescanned the growing document. These lookups were 2.3% of
all CPU samples when loading chatgpt.com.
2026-06-11 15:28:59 +02:00
Andreas Kling
c419bb526b LibWeb: Track connected SVG use elements in a per-document list
Every SVG element insertion, removal, attribute change, and children
change walked the entire document looking for use elements to notify
about possible referenced-subtree changes. On pages with large SVG
documents this is quadratic: loading chatgpt.com spent 7% of all CPU
samples in these full-document scans, nearly all of it while parsing
an SVG icon sprite sheet.

Instead, keep every use element connected to a document's node tree in
an intrusive list owned by that document, and only iterate that list
(usually empty or tiny) when an SVG element changes.

Subtleties:

- A use element inserted by the same subtree insertion as its
  referenced element, but after it in tree order, used to be found by
  the document-wide scan from the referenced element's insertion
  steps. Now SVGUseElement::inserted() re-resolves the reference if
  the shadow tree is still unpopulated. A new test covers both tree
  orders.

- Node.moveBefore() runs moving steps without insertion or removal
  hooks. Now SVGUseElement::moved_from() updates list membership when
  moving across document-tree and shadow-tree boundaries. A new test
  covers both directions.

- Removal hooks run after the subtree has been detached, so use
  elements being removed alongside the changed element may still be
  registered. Filter them out structurally via root().is_document(),
  since Node::is_connected() is a flag that is updated in hook order
  and can still be stale at this point.
2026-06-11 15:28:59 +02:00
Sam Atkins
e7aad5a9d3 LibWeb: Connect iframe referrerpolicy to ancestorOrigins
Corresponds to:
e161310ae7

This unfortunately isn't testable as we don't implement enough of
ancestorOrigins to be able to observe it.
2026-06-11 14:25:27 +01:00
Sam Atkins
935b9e8e41 LibWeb/DOM: Give Document ancestor origin lists 2026-06-11 14:25:27 +01:00
Zaggy1024
9e2a820884 LibMedia+LibWeb: End media element playback based on the pipeline EOS
Instead of comparing the current time to the duration, the playback
manager now has an explicit Ended state that jumps to the duration. The
element simply reacts to that to trigger the ended event and attribute,
along with all the other steps involved.

This moves the ended event to fire after the seeked event, which
matches other browsers' behavior. The spec doesn't explicitly say which
order they should fire in.
2026-06-11 05:49:14 -05:00
Zaggy1024
da4e8b2b2b LibWeb: Pass the media element as an argument to task steps
Since the queued task callback is already capturing the media element
weakly, we may as well directly use that in the steps that need to
interact with the element, which is the majority of them.

Also, root the element in the callback. This ensures that any queued
tasks will fire events before the element gets collected.
2026-06-11 05:49:14 -05:00
Zaggy1024
390ac120ad LibWeb: Update media element ready state when setting current position
The time marches on steps are invoked from a few places where updating
the ready state isn't needed.
2026-06-11 05:49:14 -05:00
Zaggy1024
47200f9e6d LibMedia: Don't change pipeline state from Error outside seeks 2026-06-11 05:49:14 -05:00
Zaggy1024
5a120bff33 LibMedia: Use a combined status to exit the seeking/buffering states
Instead of tracking in-flight seeks across all the sinks in the seeking
state handler, move the logic to PlaybackManager to determine the
overall status and then notify the state of that status to potentially
trigger resumption.

The buffering state handler can then share essentially the same logic
instead of having the playback manager specifically track the blocked
tracks for it.
2026-06-11 05:49:14 -05:00
Zaggy1024
042b458f75 LibMedia: Stop skipping seeks to the same timestamp in PlaybackManager
Our optimizations in the pipeline to skip video seeks that land in the
already-queued data achieve largely the same result, but with more
correctness.
2026-06-11 05:49:14 -05:00
Zaggy1024
d2c993dec0 LibMedia: Route current time through the playback state handler
This has no effect on the user experience, and likely also produces the
same timestamps during a seek as before. However, it is needed in order
to ensure that the future Ended state is always at the duration.
2026-06-11 05:49:14 -05:00
Zaggy1024
e2e2635752 LibMedia: Make PipelineStatus::Pending take precedence over HaveData
This matches the mixer's behavior, it won't mix data once it reaches
any Pending status on any input.

Doing this will allow seeking to also rely on the combined status
function to determine when to resolve.
2026-06-11 05:49:14 -05:00
Zaggy1024
eeeabcaef1 LibMedia: Remove an unnecessary lock in the audio sink's state dispatch
Both fields used in the deferred invoke are written by the main thread,
we shouldn't need to worry about a race here.
2026-06-11 05:49:14 -05:00
Zaggy1024
d0edc33597 LibMedia: Make video sinks with current frames dispatch HaveData
It's not correct to dispatch Pending if we have a current frame, and
may cause seeks to remain unresolved if they check for the current
status.
2026-06-11 05:49:14 -05:00
Zaggy1024
fa0c02acb1 LibMedia: Ensure that video sink updates only resolve current seeks
The same check as in the wake handler's deferred dispatch.
2026-06-11 05:49:14 -05:00
Zaggy1024
4fcb714327 LibMedia: Only clear decoded data producers' halt status on move
We don't need to proactively reset this anymore with the break out of
halting being determined by seek IDs instead. This will ensure that a
halting status upon a fast-path seek will still remain correct.
2026-06-11 05:49:14 -05:00
Zaggy1024
5f384cbb05 LibMedia: Simplify error wait handling in the decoded data producers
Checking for a seek within the error wait loop wasn't necessary, and
unlocking/relocking could actually lose a wake anyway. Callers always
break out of the decode loop into the thread loop, so this will still
seek immediately as before.
2026-06-11 05:49:14 -05:00
Zaggy1024
c047d62279 LibMedia: Track when demuxers move position even upon errors
Otherwise, we can lose the signal if a seek is aborted after it has
moved the demuxer, making the sink not output until it reaches the time
of the last data it pulled.
2026-06-11 05:49:14 -05:00
Zaggy1024
338c33a0ed LibWeb: Pin the media controls' time progress to the scrub position
When scrubbing, make the timeline progress match exactly to the cursor
position. Also, set the timestamp to match that progress. Both are not
allowed to change until the scrub completes.

This makes the UI stable while scrubbing after the end of the media
data in subsequent commits that jump the time to the duration at EOS.
2026-06-11 05:49:14 -05:00
Zaggy1024
2f9a42ff44 LibWeb: Swallow rejected play() promises in media controls
Whenever the controls' timeline is clicked, it pauses the media element
before seeking, then play()s on mouseup. However, the play() returns a
promise that resolves when the media actually becomes playable at the
new position. If that takes long enough that a second click pauses the
element again, then that play() promise gets rejected, and an unhandled
rejection is logged.

To prevent that, mark all play promises as handled to silence them.
2026-06-11 05:49:14 -05:00
Zaggy1024
6af0f54b15 LibWeb: Update the media controls' timeline upon progress firing
Otherwise, we don't update the buffered ranges visual when paused for
a blocked seek.
2026-06-11 05:49:14 -05:00
Sam Atkins
e0cc71d2d0 LibWeb/HTML: Ignore if select has multiple to determine placeholder
Corresponds to:
d59fb13c28

WPT has tests for this, but we don't implement listbox layout for select
so there's no testable difference here.
2026-06-11 14:46:37 +12:00
Andreas Kling
af8557c3b5 LibWeb: Avoid pruning live CSS image resources
Keep decoded image resources alive while they are backing a CSS image
resource for the document. Pruning these entries can make background
images temporarily non-paintable during display-list recording, causing
visible blank frames until the resource is requested again.
2026-06-11 01:27:57 +02:00
Zaggy1024
57a78f2b59 LibWeb: Transfer load delayers when elements are adopted
Otherwise, the load event will block the original document until GC
runs.

Without this, media-load-task-after-adoption.html would wait for the
idle timeout to trigger a garbage collection, which could sometimes
cause the test to time out entirely.
2026-06-11 00:34:12 +02:00
Andreas Kling
ddbc3e2006 LibSandbox: Add macOS service sandboxing
Add Seatbelt-based macOS sandboxing for the browser service processes.
The shared profile builder grants only the filesystem, network, Mach,
and process execution permissions each service needs, with fatal sandbox
violation reporting enabled so denials are visible during development.

Wire sandbox profiles into WebContent, WebWorker, RequestServer,
ImageDecoder, and Compositor. Keep Landlock and Seatbelt APIs visible
only on the platforms that use them. Allow RequestServer resource
substitution files explicitly, preserve read access for read-write cache
paths, and only grant renderer process execution for an existing
Cranelift helper.
2026-06-10 21:16:41 +02:00
Tim Ledbetter
3424c08b27 LibImageDecoders: Decode GIFs using wuffs
Replace the homegrown GIF parser and LZW decompressor with the wuffs
GIF decoder, which is memory-safe by construction and already used in
other engines via Skia.

One behavior change is that `loop_count()` now reports the correct
value, since the raw value stored in the file does not include the
first frane and should be incremented by 1 to be compatible with what
callers expect.
2026-06-10 20:29:11 +02:00
Timothy Flynn
1a99bdad29 LibWebView+UI: Add a small history application menu
This currently just contains a menu item to open about:history. But in
the future, we can add a list of recently closed / recently visited
pages as well.
2026-06-10 20:27:36 +02:00
Timothy Flynn
f72a18095d LibWebView+UI: Remove the clear-everything history store API
This was only used by the AppKit UI's history menu. We have more fine-
grained control over deleting history in about:settings#privacy.
2026-06-10 20:27:36 +02:00
Timothy Flynn
496c88d0c9 LibWebView: Add about:history to view, query and mangage browser history
This adds a WebUI to view the local browsing history, with controls to
search and delete entries. The APIs used to search history are paginated
to prevent excessive query sizes.
2026-06-10 20:27:36 +02:00
Timothy Flynn
409e5edbf1 LibURL+LibWeb+LibWebView: Move internal URLs to their own header
This nearly eliminates the compilation impact of adding a new WebUI URL.
2026-06-10 20:27:36 +02:00
Andreas Kling
19dd5bef60 LibJS: Isolate object property storage
Add a JSObjectStorage heap partition and route heap-backed property
storage (both named and indexed element buffers) through it.

These buffers are directly shaped by script-visible object and array
operations, so keeping them separate from the general heap makes a
corruption primitive less useful against unrelated allocations.
2026-06-10 17:36:54 +02:00
Andreas Kling
8a8625b399 LibWasm: Require virtual storage for wasm32 memory
Reserve the wasm32 virtual address space when creating an i32 memory.
Crash if the reservation fails instead of using ByteBuffer storage.

This keeps wasm32 memory on the virtual path used for fault recovery.
2026-06-10 17:34:16 +02:00
Andreas Kling
45c499d185 LibJS: Isolate ArrayBuffer backing stores
Move owned ArrayBuffer and SharedArrayBuffer data blocks into the
ArrayBuffer heap partition. Keep unowned and host storage explicit, so
Wasm memory and external LibWeb buffers stay outside this partition.

Introduce DataBlock::OwnedBackingStore as the LibJS-owned byte storage
representation. Expose byte spans instead of a ByteBuffer object, giving
ArrayBuffer one allocation boundary that can later grow toward guarded
or caged storage.

Let callers that need ByteBuffer data copy from backing-store bytes.
Keep TransferArrayBuffer zero-copy by moving the DataBlock directly
instead of materializing a ByteBuffer in between.

Update the Wasm typed-array test helper to compare viewed byte ranges
after ArrayBuffer stops exposing ByteBuffer identity.
2026-06-10 14:50:10 +02:00
Ali Mohammad Pur
90b86fd82b LibWasm: Correctly track section ordering requirements 2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
a51383e8af LibWasm: Constrain code section to its declared size 2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
34fd6d87f4 LibWasm: Delete Frame's move operator=
This is not used and is a footgun anyway.
2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
c414f31ecf LibWasm: Correctly handle memory64's addr types in the interpreter 2026-06-10 14:10:57 +02:00
Ali Mohammad Pur
f81717d4c8 LibWasm: Allow allocating max-size wasm32 memories
We used to disallow allocating 65536 pages, but that's fine as per spec.
2026-06-10 14:10:57 +02:00
Jelle Raaijmakers
e0ca142184 LibWeb: Prevent flex/grid margin collapsing with its contents 2026-06-10 13:11:47 +02:00
Andreas Kling
37e7526367 LibGfx: Split image decoders into a separate library
Move the image loader sources and decoder-only dependencies from LibGfx
into a new LibImageDecoders library. This keeps the APNG-enabled PNG
loader out of processes that only need core graphics and image writers.

Link the ImageDecoder service, direct decoder tests, fuzzers, test-web,
and the image utility against LibImageDecoders where they still decode
images in-process.
2026-06-10 11:55:48 +02:00
Shannon Booth
5ef34ecb7a LibURL: Use libpsl for public suffix matching
Replace the generated public suffix table and custom matcher with a
direct LibURL PublicSuffixData implementation backed by libpsl. This
drops our PSL download/generator path and uses the same library already
used by libcurl.

Performance is comparable before and after, while LibURL binary size
is smaller.
2026-06-10 11:43:44 +02:00
Timothy Flynn
67c9c62262 LibSandbox: Allow fcntl F_DUPFD_QUERY in seccomp policy
Mesa uses F_DUPFD_QUERY during AMD winsys initialization to check if
two DRM file descriptors refer to the same open file description. This
happens while creating WebGL contexts through ANGLE/EGL, and was being
trapped by the renderer sandbox on sites such as YouTube.
2026-06-09 23:42:36 +02:00
Andreas Kling
0c7fda8735 WebContent: Sandbox renderer processes on Linux
Add opt-in Linux renderer sandbox support to WebContent and WebWorker.
Ladybird and test-web pass --enable-sandbox through when requested, and
the renderer services only install the shared sandbox when that flag is
present.

Share one renderer policy for both services. Allow resource, font,
shared library, WebGL, Wasm, audio, and local IPC paths needed at
runtime, while keeping renderer filesystem writes mediated by Landlock.

Allow Mesa and PulseAudio to probe their standard runtime state without
escaping the renderer sandbox. Return EPERM for scheduler and priority
changes so library initialization can fall back instead of crashing on a
seccomp violation.
2026-06-09 19:35:09 +02:00
Andreas Kling
ea1ecdad5a RequestServer: Sandbox the process on Linux
Add opt-in Linux sandbox support to RequestServer. Ladybird and test-web
pass --enable-sandbox through when requested, and RequestServer only
installs the sandbox when that flag is present.

Allow reads for resolver and TLS configuration, plus the configured
certificate locations. Create and allow writes to the Ladybird cache
root, so libcurl alt-svc files and HTTP disk-cache files stay inside the
single writable tree. Also allow the systemd-resolved runtime directory
when present, since /etc/resolv.conf can point there.

Extend LibSandbox with owned Landlock paths, an add-if-exists helper,
read/write Landlock access, and reusable seccomp groups for filesystem
writes and network syscalls. Include POSIX file locks and socket byte
count ioctls needed by libc resolver and cache paths. Reuse the new
Landlock helper from Compositor as well, and allow its Mesa shader cache
directory so GPU startup can populate shader cache files after
sandboxing.
2026-06-09 19:35:09 +02:00
Andreas Kling
c38d03ba25 Compositor: Allow sandboxed font resource reads
Compositor still needs to decode font resources from display-list IPC
after startup. Let its sandbox grant read-only access to configured font
directories and bundled resource fonts through Landlock, and allow
read-only open plus metadata syscalls in the seccomp policy.

Preload the same font directories before installing the sandbox so the
Compositor can handle display lists that reference system-backed fonts.
The full test-web suite completes without Compositor sandbox crashes.
2026-06-09 19:35:09 +02:00
Andreas Kling
a69fd61eaf Compositor: Sandbox the process on Linux
Add opt-in Linux sandbox support to Compositor. Ladybird and test-web
pass --enable-sandbox through when requested, and Compositor only
installs the sandbox when that flag is present.

Install the sandbox after Compositor has initialized platform, font, and
GPU state so startup probing can complete before filesystem access is
removed. Compose the runtime seccomp policy from LibSandbox building
blocks and add an explicit GPU device operations group for driver IPC
through already-open descriptors.
2026-06-09 19:35:09 +02:00
Andreas Kling
ba87a32626 LibSandbox: Add reusable sandbox building blocks
Move the Linux no_new_privs, Landlock, and seccomp policy plumbing
into LibSandbox so individual services can describe the privileges they
need without copying the BPF and kernel feature detection machinery.

Keep ImageDecoder's sandbox policy service-local by composing the new
building blocks in SandboxLinux.cpp. This preserves the existing syscall
allowlist while making the policy easier to audit and reuse.
2026-06-09 19:35:09 +02:00
Andreas Kling
cca5a6dd37 ImageDecoder: Sandbox the process on Linux
Add --enable-sandbox to Ladybird and test-web, pass it through to
ImageDecoder, and make ImageDecoder install its Linux sandbox only when
the option is present.

The Linux implementation enables no_new_privs, configures glibc malloc
to avoid late CPU-count probes in helper threads, applies an empty
Landlock ruleset when available, and installs a seccomp filter for the
helper IPC, shared memory, threading, and decoding syscalls.

Deny plain read-only filesystem probes without granting file access, so
common runtime feature checks can observe the sandbox instead of
terminating the helper during normal decoding.
2026-06-09 19:35:09 +02:00
Tim Ledbetter
0be802797a LibGfx: Cache font-independent shape data in the font shaping cache
The shaping cache previously stored HarfBuzz buffers keyed by string,
and `shape_text()` rebuilt a fresh `GlyphRun` on every call. Cache the
font-independent shape data instead, so repeated shaping of the same
input skips both the HarfBuzz call and the glyph-vector build.
2026-06-09 17:35:54 +02:00
Tim Ledbetter
e3b359ccab LibWeb: Stop mutating the input glyph run in append_glyph_run 2026-06-09 17:35:54 +02:00
Jelle Raaijmakers
1a5b7f9ea2 LibWeb/CSS: Implement contrast-color() function 2026-06-09 17:23:26 +02:00
Jelle Raaijmakers
49cdf582ff LibGfx: Implement WCAG's contrast ratio in Color
We're going to implement the `contrast-color()` CSS function in the next
commit, and the spec advises to use the contrast ratio definition as
described in WCAG 2. So let's replace our `Color::contrast_ratio()`
implementation by that.

Co-authored-by: InvalidUsernameException
 <InvalidUsernameException@users.noreply.github.com>
2026-06-09 17:23:26 +02:00
Jelle Raaijmakers
d42b0f72ae LibGfx: Remove unused Color::to_grayscale()
Co-authored-by: InvalidUsernameException
 <InvalidUsernameException@users.noreply.github.com>
2026-06-09 17:23:26 +02:00
Callum Law
6a6b505c5a LibWeb: Handle empty values in StylePropertyMap.set()
The spec doesn't say how to handle this so we just match Chrome's
behavior of throwing a `TypeError` (without clearing the existing
value).

Fixes #9969.
Fixes #9970.
2026-06-09 17:15:25 +02:00
Callum Law
e9932ffe89 LibWeb: Preserve original value on invalid StylePropertyMap.set input
Only remove the existing value once the input is fully validated and
internal representations have been created.
2026-06-09 17:15:25 +02:00
Tim Ledbetter
24d6b4994b LibJS: Add ordinary-object fast path to CopyDataProperties
The `CopyDataProperties` AO is used to implement object spread syntax.
The generic path calls `[[OwnPropertyKeys]]` to materialize a key list
and then performs a separate lookup through ``DescriptorArray::find()`
for every key.

For ordinary objects we now instead walk the shape in insertion order
and read each value directly by its storage offset, avoiding both the
key-list allocation and the per-key descriptor lookups. The fast path
is guarded to ordinary objects with no intrinsic accessors, no exotic
indexed access, packed-or-simpler indexed storage, and no excluded
values, falling back to the generic algorithm otherwise.

This is roughly 2x faster on a tight object spread microbenchmark.
2026-06-09 16:56:54 +02:00
Tim Ledbetter
36ed97128a LibJS: Stop scanning the shape once an enumerable string key is found 2026-06-09 16:56:54 +02:00
Tim Ledbetter
126df1fb21 LibJS: Return optional IterationDecision from property iteration methods 2026-06-09 16:56:54 +02:00
Sam Atkins
c7015a8647 LibWeb: Remove unused test variant metadata API
Remove internals.loadTestVariants and the IPC forwarding that reported
variant metadata back to WebView. test-web now identifies WPT variants
during collection, so no loaded document needs to expose this test-only
hook.
2026-06-09 16:48:33 +02:00
Andreas Kling
13a804dbf6 LibWeb: Compact generated CSSStyleProperties bindings
Stop emitting every generated CSS property accessor as an IDL attribute.
Instead, generate a compact CSSStyleProperties initializer that installs
all property aliases from a table and dispatches through one native
function class carrying the UTF-16 property name.

This keeps the generated binding file focused on cssFloat and moves the
large property list into a simple generated table.
2026-06-09 11:48:02 +02:00
Andreas Kling
df7c715b4e LibWeb: Remove FlyString property-name overload
Remove the PropertyNameAndID::from_name overload that accepted
FlyString. Parser declarations still store their token names as
FlyString, but the conversion to UTF-16 now happens explicitly at those
boundaries.
2026-06-09 11:48:02 +02:00
Andreas Kling
7272c26c7b LibWeb: Store CSS descriptor names as UTF-16
Move DescriptorNameAndID to Utf16FlyString so CSS descriptor APIs can
keep using the CSSOM property-name string without round-tripping through
FlyString.

Keep parser declaration tokens and DevTools error payloads on their
existing FlyString types at their boundaries.
2026-06-09 11:48:02 +02:00
Andreas Kling
96521f7df0 LibWeb: Take UTF-16 names in Typed OM property maps
Move StylePropertyMap, StylePropertyMapReadOnly, and the CSS.supports
property-name overload to Utf16FlyString. Request the UTF-16 binding
conversion path for their IDL property-name arguments.
2026-06-09 11:48:02 +02:00
Andreas Kling
d641bfd7e2 LibWeb: Store custom property names as UTF-16
Move PropertyNameAndID, custom property data, registered custom
properties, and Typed OM associated property names to Utf16FlyString.

This removes the FlyString storage boundary from CSS property-name
handling and lets CSSStyleProperties keep the name it receives from
CSSOM instead of converting it back to UTF-8.
2026-06-09 11:48:02 +02:00
Andreas Kling
388ec003ca LibWeb: Take UTF-16 names in CSS property APIs
Move the remaining CSSStyleDeclaration property-name APIs to
Utf16FlyString. This lets CSSOM binding and generated accessor code
pass JS property names without first constructing FlyString values.

Keep internal custom-property and descriptor storage unchanged for now.
Those remaining FlyString conversions are at storage boundaries that
will be migrated in follow-up commits.
2026-06-09 11:48:02 +02:00
Andreas Kling
22a26babc5 LibWeb: Take UTF-16 names in get_property_value
Change get_property_value() to take a Utf16FlyString so generated CSS
property accessors can pass their JS property names through without
constructing FlyString instances first.

Keep the existing internal descriptor and custom-property storage shape
for now, and convert at those boundaries while the remaining CSS
property APIs are migrated separately.
2026-06-09 11:48:02 +02:00
Tim Ledbetter
ed6aec8dfa LibCrypto: Restore cached tag when a failed ASN1 read is rolled back
Previously, the stack would be restored to its previous position but
the tag would retain its old value, leading to an inconsistent state.
2026-06-09 08:02:44 +01:00
sideshowbarker
532636d6e7 LibWeb: Remove ChunkSteps & ReadAllOn* dead code from Streams reader
Drop no-longer-reachable ChunkSteps & ReadAllOn* callbacks from Streams.
(Seems they got orphaned by the changes in c14d5f27f9 and eb0a51faf09.)
2026-06-09 16:45:19 +12:00
Tim Ledbetter
d19fb87441 LibWeb: Clip nested display lists to their destination rect
SVG image content drawn outside the image's viewport escaped the image
box, because `PaintNestedDisplayList` playback translated to the
destination rect without clipping to it. We now clip it during playback.
2026-06-08 21:17:02 +01:00
Shannon Booth
20bfc49083 LibURL: Preserve trailing dots in public suffix matching
PublicSuffixData handled trailing-dot hosts incorrectly when a PSL rule
matched, causing returned public suffix and registrable-domain results
to drop the trailing dot.

Make PublicSuffixData skip leading dots for matching, ignore a single
trailing dot while running the PSL algorithm, and append that trailing
dot back to returned results.
2026-06-08 20:19:06 +02:00
Shannon Booth
9b80ac00be LibURL: Move registrable-domain PSL lookup to PublicSuffixData
Move the registrable-domain helper from URL into PublicSuffixData and
name it find_matching_registrable_domain().

This keeps it alongside find_matching_public_suffix(), making it clear
that both APIs only return results matched from the PSL data, while
Host::public_suffix() implements the URL Standard fallback to the
top-level domain.
2026-06-08 20:19:06 +02:00
Shannon Booth
ac344a5196 LibURL: Clarify PSL matching API names
Rename PublicSuffixData's raw lookup helpers to make it clear that they
only return public suffixes matched from the PSL data.

This distinguishes them from Host::public_suffix(), which implements the
URL Standard definition and falls back to the top-level domain when no
PSL rule matches.

We need both layers because address bar handling needs the raw lookup to
decide whether input should be treated as a URL or as a search.
2026-06-08 20:19:06 +02:00
Tim Ledbetter
d625deaccf LibWeb: Invalidate style when form control validity changes 2026-06-08 19:28:37 +02:00
Tim Ledbetter
4c205c109e LibWeb: Track validity pseudo-classes for style invalidation 2026-06-08 19:28:37 +02:00
Tim Ledbetter
de0b733bed LibWeb: Implement suffering from bad input for input elements
Email field support is left unimplemented because we don't have a way
to convert email addresses to punycode.
2026-06-08 19:28:37 +02:00
Andreas Kling
048facc0b1 LibWeb: Avoid min-content sizing for fitting fit-content heights
Measure max-content before min-content for definite fit-content heights.
When the max-content height is no larger than stretch-fit, the clamp
resolves to max-content and min-content cannot affect the result.

Both intrinsic height measurements use the same available width, so this
preserves the existing width-dependent sizing behavior.
2026-06-08 19:10:25 +02:00
Andreas Kling
a92418c812 LibWeb: Avoid min-content sizing for fitting fit-content widths
Measure max-content before min-content for definite fit-content widths.
When the max-content width is no larger than stretch-fit, the clamp
resolves to max-content and min-content cannot affect the result.

Leave height sizing unchanged because its intrinsic measurements depend
on the width passed into the layout.
2026-06-08 18:10:13 +02:00
Andreas Kling
d7a5fca98b LibWeb: Avoid min-content sizing for fitting abspos boxes
Measure the preferred width first in absolutely positioned
shrink-to-fit cases. When it fits within the constraint equation's
available width, the preferred minimum width cannot change the result.

Keep the static-position branch setting the resolved content width
before reading the static position, but avoid the min-content layout
when it is not needed.
2026-06-08 18:10:13 +02:00
Andreas Kling
565df0da77 LibWeb: Avoid min-content sizing for fitting floats
Measure a floating auto-width box's max-content width before falling
back to its min-content width in the definite available-width branch.
If max-content already fits, shrink-to-fit resolves to that value and
the min-content contribution cannot affect the used width.

Also avoid the paired shrink-to-fit intrinsic measurement when an
intrinsic sizing constraint only needs one side of the contribution.
2026-06-08 18:10:13 +02:00
Andreas Kling
62d8757298 LibWeb: Avoid unneeded shrink-to-fit layout passes
When an inline-level box uses shrink-to-fit sizing, we do not always
need both intrinsic width calculations. Definite available space can use
the max-content width alone when it already fits, while min-content and
indefinite constraints only need the corresponding intrinsic width.

Avoiding the unused intrinsic layout pass keeps the sizing logic
equivalent while reducing work for common inline-block layouts.
2026-06-08 18:10:13 +02:00
Andreas Kling
c746bd5049 LibWeb: Avoid needless :has() descendant fanout
When an element was affected by :has() in subject position,
pending :has() mutation invalidation also applied the pseudo-class
invalidation plan for that element. If the same element had ever been
observed in a non-subject :has() selector, that plan could invalidate
the element's whole descendant subtree even when the mutation could
only require the subject element itself to recompute style.

Keep subject-position :has() invalidation to the element itself, and
run the descendant fanout only for non-subject involvement after the
existing mutation feature filter says that fanout may be affected.
Track the strongest invalidation applied to each anchor, so a later
batched mutation can still upgrade earlier anchor-only work to a
descendant fanout.

Extend the filter to treat known state pseudo-classes as concrete
mutation features, so a :hover mutation does not conservatively match
unrelated selectors such as :has(dialog:modal).

Scope boundary selectors are kept conservative where needed: when an
@scope boundary contains :has(), the scope root's match can activate or
deactivate style rules for descendants, so it still records descendant
involvement.

Add coverage for unrelated hover and batched mutation cases on elements
whose ancestors have both subject and non-subject :has() involvement,
ensuring descendant no-op recomputation stays bounded without dropping
required descendant fanout.
2026-06-08 17:16:18 +02:00
Andreas Kling
bae4434780 LibWeb: Avoid sibling walks for last-child invalidation
Track last-child and backward positional selector dependencies
separately on parent nodes. A last-child or only-child selector can only
change the element at the trailing edge, so insertions and removals can
invalidate that element directly instead of walking every previous
sibling.

Keep the previous-sibling walk for selectors such as nth-last-child and
last-of-type, where every previous element's from-end position may
change.
2026-06-08 17:16:18 +02:00
Andreas Kling
62a5ee7ff9 LibWeb: Guard pseudo-class invalidation by selector features
Include tag and attribute selectors in guarded pseudo-class invalidation
plans. This keeps selectors like a:hover .target from applying work to
unrelated descendants when :hover changes on other elements.

Store both original and lowercase attribute names for invalidation keys.
HTML attribute mutations still hit lowercase selector buckets, while SVG
and MathML selectors such as [viewBox] keep their case-sensitive guards.
Use the same names for :has() metadata and mutation feature filtering so
attribute changes do not get filtered out after metadata lookup.

Match tag invalidation properties against lowercased local names, like
invalidation data and rule cache buckets do. The regression tests cover
SVG hover fanout and case-sensitive :has() attribute mutation.
2026-06-08 17:16:18 +02:00
sideshowbarker
8e74650416 LibWeb: Fix crash when reading a detached or out-of-bounds stream chunk
Problem: Crash when reading a ReadableStream whose chunk is a Uint8Array
backed by a detached ArrayBuffer.

Cause: The ReadLoopReadRequest::on_chunk code skipped existing guards
when extracting the chunk bytes — leading to bytes() getting called on
the detached buffer, which tripped an assert.

Fix: Read the chunk through Uint8Array::data() — which guards for the
case where the view is detached (or out-of-bounds). That aligns things
with what the sibling IncrementalReadLoopReadRequest was already doing.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9965
2026-06-08 13:45:00 +02:00
sideshowbarker
086e860b48 LibGfx: Fix misaligned u32 store in BMP RLE24 decompression
Problem: Decoding a BI_RLE24 BMP binds a u32 reference to a misaligned
address, gets flagged by UBSan while decompressing the run-length data.

Cause: The decompressed RLE24 buffer holds 24-bit pixels at a 3-byte
stride (decode_bmp_pixel_data reads it back with LE read_u24) — but each
pixel was getting stored with a 4-byte write at 3-byte-strided offsets.

Fix: Store the 24-bit value as three LE bytes — so the write
matches the stride and is always aligned. Size the buffer to the
real 3-bytes-per-pixel total, and bound-check the 3-byte write.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9958
2026-06-08 13:43:21 +02:00
Tim Ledbetter
525ce459fc LibWeb: Avoid stale DataTransferItem access after clearing data
Previously, clearing a DataTransfer's data removed entries from the
drag data store without updating the associated `DataTransferItem`
objects. An item obtained beforehand kept an index that no longer
referenced a valid entry, so reading its kind or type accessed an
out of bounds element of the now-empty list and crashed. We now keep
the item objects in sync when clearing data, placing any stale ones
into the disabled mode.
2026-06-08 13:40:22 +02:00
Callum Law
3c4076597e LibWeb: Avoid Vector allocation in parse_coordinate{_pair_}_sequence
Previously we would often return a `Vector` just for the caller to
iterate over it a single time and disregard it. We instead now skip the
`Vector` allocation and second iteration by executing a callback as we
parse each value in the sequence.
2026-06-08 12:39:39 +01:00
Callum Law
5fbb8d82e7 LibWeb: Move SVG::parse_elliptical_arc_argument inline
`SVG::parse_elliptical_arc` was the only user and moving it inline
allows us to avoid a `Vector` allocation.
2026-06-08 12:39:39 +01:00
Callum Law
b33b9a6747 LibWeb: Parse SVG coordinate pair as Gfx::FloatPoint
We ended up converting this to a `Gfx::FloatPoint` in all but one place
any way so this just skips some extra handling and `Vector` allocations.

Also makes `parse_coordinate_pair_{double|triplet}` return `Vectors`
store data inline to avoid a heap alloc.
2026-06-08 12:39:39 +01:00
Callum Law
1026991820 LibWeb: Specialize SVG::PathInstruction structs
Previously we had a single `PathInstruction` struct which stored it's
data in a `Vector<float>`. We now define `PathInstruction` as a
`Variant<>` of structs storing data inline (note that the remaining
`Vector` properties will be replaced with `Gfx::FloatPoint` in a future
commit) - this avoids a `Vector` allocation and avoids magic indices
when accessing data.
2026-06-08 12:39:39 +01:00
Callum Law
8ab9eaf44e LibWeb: Simplify SVG::PathInstruction dumping
This updates dumping to reflect the fact that each instruction only ever
contains a single set of arguments, and that `ClosePath` does not have a
concept of absoluteness (i.e. 'Z' and 'z' are equivalent).
2026-06-08 12:39:39 +01:00
Callum Law
337748e3d8 LibWeb: Avoid string value copy in SVGPathElement::attribute_changed 2026-06-08 12:39:39 +01:00
Callum Law
743922b868 LibWeb: Avoid copying instructions in AttributeParser::parse_path_data
We throw away the parser immediately afterwards so we can just `move()`
instead of copying
2026-06-08 12:39:39 +01:00
Andreas Kling
8c63243b51 LibWeb: Avoid inflating 0fr grid rows from hidden overflow
Use the grid item minimum contribution when an intrinsic flexible track
sizing pass sees a scroll-container item crossing only zero-flex
tracks. This keeps collapsed 0fr rows from contributing their hidden
contents to an ancestor flex item's automatic height.

Add a text test covering an overflow-hidden grid item in a 0fr row
inside a column flex container, matching the dashboard sidebar pattern.
2026-06-08 10:06:07 +02:00
sideshowbarker
a82c7939d9 LibWeb+UI/AppKit: Implement macOS IME support
This makes macOS IME input in web content work as expected.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9712
2026-06-08 10:23:14 +09:00
Andreas Kling
42a6253d64 LibWeb: Avoid idle callback churn in hidden documents
Do not start idle periods for hidden documents. This prevents
background tabs from promoting chained requestIdleCallback work into
new idle tasks immediately.

Also avoid queueing a follow-up idle task after the last runnable idle
callback has been consumed.

This fixes an issue where opening GitHub links in background tabs would
cause their WebContent processes to churn 100% CPU until you open them.
2026-06-08 01:56:11 +02:00
Shannon Booth
2dc3e3da55 Meta: Remove obsolete Lagom host-tools build 2026-06-08 01:11:40 +02:00
Shannon Booth
4a681c9148 Libraries: Remove LibIDL
Move the overload-resolution metadata types into LibWeb::WebIDL and
update the Python generator and overload resolver to use them.

LibIDL no longer has any users after the C++ bindings generator removal,
so remove the library and unlink it from LibWeb.
2026-06-08 01:11:40 +02:00
Andreas Kling
5c169091de LibWeb: Propagate outerText replacement exceptions
Propagate exceptions from the outerText replace step instead of assuming
that replacement always succeeds. Replacing the document element with a
rendered text fragment can legitimately fail with a DOMException.

Add a reduced crash test for setting outerText on documentElement.
2026-06-08 01:04:08 +02:00
Andreas Kling
0d947fa833 LibGfx: Clamp HarfBuzz font scaling
Clamp the CSS pixel size used for HarfBuzz font scales before passing
it to the int-sized HarfBuzz API. Also accumulate shaped advances
in double precision while measuring text. Very large web-provided font
sizes can otherwise overflow before layout clamps dimensions.

Add a reduced crash test for laying out text with a huge font size.
2026-06-08 01:04:08 +02:00
Andreas Kling
19dd7aaf5c LibWeb: Tolerate unpainted fragments in layout dumps
Avoid asking PaintableFragment for geometry or text when dumping an
unpainted fragment. Some SVG inline subtrees can generate fragments for
nodes that intentionally have no paintable, and diagnostic dumps should
still be able to describe them.

Add a reduced SVG crash test that dumps a layout tree with unpainted
inline fragments.
2026-06-08 01:04:08 +02:00
Andreas Kling
dc98a11f4e LibWeb: Handle var() in grid placement shorthands
Preserve unresolved values while serializing grid-row and grid-column
shorthands. The serializer can only test for the auto placement keyword
after confirming that the longhand value is a grid track placement.

Add a reduced crash test covering CSSOM serialization after assigning
var() to grid-row-end and grid-column-end.
2026-06-08 01:04:08 +02:00
Andreas Kling
e18d78eb2d LibWeb: Handle degenerate repeating gradients
Normalize zero-length repeating gradients to a solid average color
before painting code expands or tiles their stops. CSS Images defines
this case as an average over the same color stops with an arbitrary
non-zero distance, avoiding division by a zero repeat length while
painting.

Add a reduced crash test covering zero-length repeating linear, radial,
and conic gradients.
2026-06-08 01:04:08 +02:00
Andreas Kling
613a04e4df LibWeb: Skip styleless nodes for rendered text
Rendered text collection needs computed style only for nodes that are
being rendered. A stale layout node can remain without style or a styled
parent, so treat that as not rendered instead of asserting while reading
innerText or outerText.

Add reduced crash coverage for reading outerText from a style element
after disabling and adopting it into another document.
2026-06-08 01:04:08 +02:00
Andreas Kling
3fcd95327e LibWeb: Avoid cross-root Selection extend comparisons
Selection.extend() can keep an old anchor that is no longer orderable
with the new focus after a selected shadow host is detached. Collapse
to the new focus in that case and avoid comparing boundary points from
different shadow-including roots.

Add reduced crash coverage for extending a selection after detaching
the shadow host that held the old anchor.
2026-06-08 01:04:08 +02:00
Andreas Kling
ecb3080ac6 LibWeb: Tolerate unpainted SVG ancestors
SVG absolute rect computation walks from the containing SVG root up
through layout containing blocks. Some anonymous or otherwise unpainted
ancestors can appear in that chain, so skip those boxes instead of
assuming every ancestor has a paintable box.

Add crash coverage for SVG content under a foreignObject nested in SVG
font content, matching the reduced structure from the fuzzer bucket.
2026-06-08 01:04:08 +02:00
Andreas Kling
57bf4bec64 LibWeb: Ignore invalid body background hints
The body background attribute can fail to produce an image style
value. Applying presentational hints should ignore the attribute in
that case instead of asserting.

Add reduced crash coverage for updating style after an invalid body
background hint is adopted into the active document.
2026-06-08 01:04:08 +02:00
Andreas Kling
485ca67164 LibWeb: Skip inactive media element tasks
Media element tasks are queued as element tasks. The element can move
to another document before the queued task runs.

Abort the task if the media element's current document is no longer
fully active. This preserves the media resource fetch invariant.

Add reduced crash coverage for adoption into an inactive document.
2026-06-08 01:04:08 +02:00
Andreas Kling
e23c657144 LibWeb: Avoid SVG getBBox paintable downcasts
SVG foreignObject elements expose SVGGraphicsElement methods, including
getBBox(), but their layout boxes create SVGForeignObjectPaintable,
rather than SVGGraphicsPaintable. Only SVGGraphicsPaintable stores the
computed SVG transform data, so use it only when that paintable kind is
present.

Add reduced crash coverage for calling getBBox() on a rendered
foreignObject element.
2026-06-08 01:04:08 +02:00
Andreas Kling
fe51d6ce5d LibWeb: Handle blurring nodes without a browsing context
DOMParser-created documents do not have a browsing context, but elements
created in them can still be passed to the HTML blur() steps. The
unfocusing steps only have a top-level focus chain when the old target
finds itself in a browsing context, so return early when there is none.

Add reduced crash coverage for blurring a body element created in a
DOMParser document.
2026-06-08 01:04:08 +02:00
Andreas Kling
7afc862bc0 LibWeb: Handle BarProp without a top-level context
BarProp.visible first handles a null browsing context, but the
top-level browsing context lookup can also return null when the
relevant document is no longer fully active. Return true in that
case instead of dereferencing the null result.

Add a reduced Crash/HTML test from the domato fuzz-00063 sanitizer
finding that reads menubar.visible through an inactive frame window.
2026-06-08 01:04:08 +02:00
Andreas Kling
8f1dd07ae0 LibWeb: Stop SVG continuation recreation at non-box elements
When inline continuation restructuring recreates an inline ancestor
chain, SVG resource descendants can decline to create layout nodes.
Stop reconstruction at that point instead of dereferencing a null
layout node, and create the before wrapper when the nearest block
ancestor has no last child.

Add a reduced Crash/SVG test covering a block gradient inside a
paint server, reduced from the domato fuzz-00436 sanitizer finding.
2026-06-08 01:04:08 +02:00
Andreas Kling
eb2200e33d LibWeb: Resolve editing background colors without layout
removeFormat computes effective command values for nodes in the active
selection. Hidden editable elements can be selected without having a
styled layout node, but background-color resolution only needs an
element color context.

Use the element color context instead of requiring
Layout::NodeWithStyle. Add reduced crash coverage for removeFormat with
a hidden button.
2026-06-08 01:04:08 +02:00
Andreas Kling
998fa908db LibWeb: Skip stale find-in-page range endpoints
Text blocks used by find-in-page can contain positions for nodes that no
longer form a valid live Range by the time matches are converted back to
DOM ranges. The offset checks handled stale text lengths, but endpoints
could also be disconnected or belong to different roots.

Reject those stale matches before constructing the Range. Add reduced
crash coverage for inserting text after a textarea and immediately using
window.find() to select that text.
2026-06-08 01:04:08 +02:00
Andreas Kling
9815f0d94d LibWeb: Avoid zero border radius overlap divisors
The border-radius overlap algorithm scales by L_i / S_i for each side
whose adjacent radii exceed the side length. If layout produced a
negative border box dimension, a side with a zero radius sum could be
mistaken for an overflowing side and passed to CSSPixelFraction as a
zero denominator.

Use non-negative side lengths for the normalization step and only divide
by nonzero radius sums. Add reduced crash coverage for an output element
whose negative letter spacing produces this geometry during painting.
2026-06-08 01:04:08 +02:00
Andreas Kling
227ca68d36 LibWeb: Skip style containment checks without style
The layout tree builder checks style containment after updating a node.
This scopes quote nesting to the containing subtree. Some layout nodes
lack style or a styled layout parent.

Only ask for style containment when computed values are available. Add
reduced crash coverage for the domato assertion.
2026-06-08 01:04:08 +02:00
Andreas Kling
7b3d33f062 LibWeb: Guard SVG animated length conversion
SVG animated length accessors read computed geometry properties, but
those can contain CSS sizing keywords such as fit-content. Those values
are not length-percentage values and must not be converted as one.

Only convert length, percentage, and calculated values. Fall back to the
existing zero length for other computed values, matching the auto path.
Add a crash test for reading height.baseVal on an SVG filter primitive
with fit-content height.
2026-06-08 01:04:08 +02:00
Andreas Kling
51b831af9d LibWeb: Skip stale find-in-page text matches
Find-in-page builds live ranges from layout text block offsets. If the
DOM text node no longer contains the cached offset, constructing the
Range violates its boundary invariants.

Skip stale matches whose mapped offsets are outside the current text
node length. Add coverage for mutating text before window.find().
2026-06-08 01:04:08 +02:00
Andreas Kling
e359c03289 LibWeb: Only assign sticky frames with sticky insets
Some paintables can carry sticky positioning without receiving sticky
inset data from layout. They cannot produce sticky constraints for async
scrolling.

Only create sticky scroll frames when sticky inset data exists. Add a
crash test for a sticky ruby paintable.
2026-06-08 01:04:08 +02:00
Andreas Kling
b42cf66a9a LibWeb: Handle child navigables without active documents
A queued document unload can capture child navigables whose active
document is gone by the time the task runs. In that state there is no
child document to unload, but the parent's lifecycle counter still needs
to advance.

Run the unload completion step directly when a child navigable has no
active document. Add coverage for removing an iframe during a child
navigation.
2026-06-08 01:04:08 +02:00
Andreas Kling
4d868d7d82 LibWeb: Handle Range rects starting after last child
A Range boundary can point after a non-text container's final child.
Range::getClientRects() treated that offset as a child index and bound a
reference to null before walking the selected nodes.

Start at the node after the container in that case, matching boundary
handling used by selection painting. Add a crash test for a collapsed
range at the end of an element.
2026-06-08 01:04:08 +02:00
Andreas Kling
6eff400823 LibWeb: Avoid scrollbar painting without overflow data
Sticky inline paintables can have overflow:scroll without owning
scrollable overflow data. They cannot produce scrollbar geometry.

Return no scrollbar data when there is no overflow rectangle. Add a
crash test for a sticky inline bdi element.
2026-06-08 01:04:08 +02:00
Andreas Kling
e9b8c3f7c6 LibWeb: Skip COOP access reporting for inactive documents
WindowProxy property access can reach COOP access reporting after iframe
removal. That leaves the accessed active document not fully active.

The reporting algorithm only applies to fully active documents. Return
early for inactive documents instead of asserting. Add a crash test for
accessing a window proxy after iframe removal.
2026-06-08 01:04:08 +02:00
Andreas Kling
26e3f7e3a0 LibWeb: Handle scrollIntoView without scrollingElement
In quirks mode, document.scrollingElement can be null when the root and
body overflow values make the body potentially scrollable. The viewport
can still be a scrolling box for scrollIntoView().

Skip scroll-padding adjustment when there is no scrolling element. Add a
crash test for this null scrollingElement path.
2026-06-08 01:04:08 +02:00
Andreas Kling
dfa698b75e LibWeb: Avoid user-select lookup on unstyled layout nodes
Selection painting can happen before layout settles. Some layout nodes
then have no style or styled ancestor. They cannot contribute a
user-select exclusion.

Treat them as selectable for this check. Add a crash test reduced from a
domato case.
2026-06-08 01:04:08 +02:00
sideshowbarker
efa9388adc LibWeb: Fix use-after-free in live-collection filter captures
Problem: Holding form.elements while the form is detached + dropped hit
a use-after-free: the form is GC’ed while the collection’s still live.

Cause: HTMLCollection (and LiveNodeList too) was storing its filter as
an AK::Function — which the garbage collector doesn’t visit. When a
filter lambda captures a GC object (e.g. the form in form.elements) that
object has no GC edge keeping it alive. So it can be collected while the
collection using it’s still reachable — leaving a dangling pointer.

Fix: HTMLCollection and LiveNodeList are GC cells with their own
visit_edges. So, visit the filter’s (and sort’s) capture range there:
conservatively mark any GC object a captured lambda holds — to ensure
it’s kept alive as long as the collection’s reachable.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9948
2026-06-07 22:16:33 +02:00
Andreas Kling
9340d2d1a3 LibWeb: Make layout nodes refcounted
Move the layout tree from GC allocation to refcounted ownership so
removed layout and paint subtrees are destroyed synchronously instead
of waiting for the next GC sweep. This dramatically reduces GC memory
usage peaks after layout tree churn and makes it easier for memory use
to fall back after large document updates.

Update layout factories, tree traversal, SVG layout node creation,
paintable back-pointers, and pseudo-element layout links to use RefPtr
ownership.

Make display: contents follow the same shape as Blink and WebKit: the
element itself does not create a layout node, and its children are
flattened into the nearest layout parent. Wrap direct non-whitespace
text in an anonymous inline node when the boxless element contributes
inherited style to that text.

Use an internal inline wrapper for display: contents pseudo-elements
so generated content can still participate in layout, painting, hit
testing, and pseudo-element queries. Keep CSSOM reporting the computed
display value from the pseudo style, not the internal wrapper.

Remove the retained out-of-tree layout node list and its testing hook,
since the flattened model does not need a side owner for boxless
elements. Add coverage for inherited text style, dynamic insertion
order, pseudo-element hit testing, and computed style queries.
2026-06-07 20:52:49 +02:00
Andreas Kling
0b94af1109 LibWeb: Stop tracing CSS style values
Remove the visit_edges hook from CSS::StyleValue and stop asking CSS
properties, descriptors, computed values, and layout nodes to trace
through their style values.

Style values are refcounted data objects, so they should not be part of
the GC graph. Keeping this cleanup separate makes the later layout tree
ownership change smaller and easier to review.
2026-06-07 20:52:49 +02:00
Andreas Kling
9c040f1dd3 LibWeb: Make generated content text layout-owned
Stop creating unattached DOM Text nodes for string items in generated
CSS content. These text nodes are layout artifacts, so store their text
directly in a GeneratedTextNode instead of pretending they have DOM
backing.

Teach text shaping and first-letter splitting to read text through the
layout text source while keeping DOM-specific behavior behind an
optional DOM text accessor. This preserves generated first-letter
handling without rooting fake DOM nodes.

Add crash coverage for generated content surviving GC and rebaseline
layout dumps that now identify generated text explicitly.
2026-06-07 20:52:49 +02:00
Tim Ledbetter
3771bd5d4a LibURL: Advance past the '@' delimiter after batch-parsing userinfo
After batch-processing the userinfo, the authority state advanced the
parse pointer onto the '@' and relied on the end-of-loop increment to
step past it. That increment uses the byte length of the authority's
first code point, not the delimiter's. When the first code point was
multi-byte, the pointer overshot into the middle of a code point and
the next iteration sliced the string at a non-char boundary causing the
process to panic. We now step past the delimiter explicitly so we don't
need to rely on the end of loop increment to do so.
2026-06-07 11:29:43 +01:00
Zaggy1024
e24540330e LibWeb: Enable playback rates other than 1.0
The allowed range for now is 0.0-64.0. If that turns out to be too wide
a range, we'll reduce it.

Chromium and Firefox are more restrictive, only allowing between a
minimum non-zero number and 16.0. They also allow 0.0.
2026-06-06 19:58:17 -05:00
Zaggy1024
28f670f09f LibMedia: Implement audio time stretching with WSOLA
The algorithm is ported over from Chromium's, which produces very good
results for speech, while being not objectionable for music, especially
in the background.

Other algorithms were tested.

Phase vocoders:
- Bungee
- Signalsmith Stretch
- pvdoneright
All three of these exhibited the usual phase shifting artifacts,
causing speech to sound slightly shifted into the high end. Speech is
the main thing we want to optimize for, so these aren't ideal.

Sonic (TD-PSOLA) performs better than WSOLA for speech, especially at
rates higher than 2x, but makes background sounds/music garbled and
unpleasant. It is still worth considering for speech clarity, and could
be added as an optional feature.
2026-06-06 19:58:17 -05:00
Zaggy1024
543db2b828 LibMedia: Seek the mixer when toggling audio tracks
This has two benefits:
- Pausing and then disabling a track no longer has lingering audio from
  the disabled track
- The mixer starts mixing from the current time even after it has
  advanced past EOS, so it doesn't have to mix audio that won't play
2026-06-06 19:58:17 -05:00
Zaggy1024
dd72dfadff LibMedia: Pause the audio sink when its rate is set to 0 2026-06-06 19:58:17 -05:00
Zaggy1024
f0ab344a4e LibMedia: Handle outputting silence after EOS in the audio sink
This allows nodes downstream of the mixer to know the exact frame at
which EOS is reached.

More concepts have been introduced into PipelineStatus.h to make each
condition in the pipeline clearer about its intent.
2026-06-06 19:58:17 -05:00
Zaggy1024
fad02e6bab LibMedia: Move AudioPlaybackSink's sample spec into its thread data
This will allow it to be used from the processor thread in subsequent
commits.
2026-06-06 19:58:17 -05:00
Zaggy1024
769dbd6888 LibMedia: Avoid sleeping if the audio processor sees a ready status
This could cause an upstream transition from Pending to HaveData to
never unblock the audio processor thread if that transition happened
between setting the wait flag and re-checking the status for
MovedPosition at the start of the processor loop.

This wasn't observable with the existing pipeline simply because it was
near impossible to run down the upstream data to get a Pending status.
2026-06-06 19:58:17 -05:00
Zaggy1024
30843326f6 LibMedia: Reset downstream sleep status before calling the wake handler
This allows the downstream node to query status and sleep again
synchronously, which is needed for nodes that need multiple input
blocks before they can produce output and wake their downstream nodes.
2026-06-06 19:58:17 -05:00
Zaggy1024
7ddbc2d7dd LibWeb+LibMedia: Wire up setting the pipeline's playback rate
However, the playback rate is still limited to 1.0 at the element,
because audio stretching is not yet implemented.
2026-06-06 19:58:17 -05:00
Zaggy1024
47207b69e6 LibMedia: Remap audio time based on block durations in media time
This will allow the media time to advance faster or slower on a per-
block basis, so that playback rate doesn't lose timing.
2026-06-06 19:58:17 -05:00
Zaggy1024
13d04e44c2 LibMedia: Move AudioBlock's timing info into a separate class
This will be used to account for playback rate in audio timing.
2026-06-06 19:58:17 -05:00
Zaggy1024
ee66ccb4af LibMedia: Add information to AudioBlock to allow time scaling
By decoupling media duration from frame duration, we can allow audio
blocks to make up more or less time independent of the amount of actual
data.
2026-06-06 19:58:17 -05:00
Zaggy1024
9ca1db3bb8 LibMedia: Rename timing getters in AudioBlock
This new naming will make timescale modifications more comprehensible.
2026-06-06 19:58:17 -05:00
Zaggy1024
c8c64e4819 LibMedia: Store raw audio data as planar
This avoids strided loads for vectorized audio data processing loops.
2026-06-06 19:58:17 -05:00
Aliaksandr Kalenik
317dca7aaa LibWeb: Skip compositor metadata during display list painting
Display-list replay used to feed compositor-only metadata commands
through the normal painting path. Scroll nodes, wheel hit-test regions,
main-thread wheel regions, and viewport scrollbar metadata do not draw
in the Skia player, but each command still paid visual-context
switching, clip rejection, and no-op dispatch overhead.

Keep those commands in the display list for async scrolling and dumps,
but skip them at the start of painting replay. This keeps the metadata
available to the compositor while removing thousands of no-op paint-side
commands from heavy scrolling pages.

With this change rasterization goes down from 13 ms to 1ms on my
computer for page in
https://github.com/LadybirdBrowser/ladybird/issues/9929
2026-06-07 00:35:36 +01:00
Andreas Kling
7c06c3fd14 LibWeb: Make computed style data refcounted
Move ComputedProperties and CascadedProperties out of the GC. They no
longer contain strong references to GC-managed data.

Keep computed styles alive from DOM elements and animation updates with
RefPtr. Pass style into layout constructors by reference, since layout
only copies the values it needs while building nodes.

Use GC::Weak for cascade source links, so entries no longer keep the
style declaration or shadow root alive.
2026-06-06 23:29:48 +02:00
Andreas Kling
222c1f7044 LibWeb: Move CSS image loading state to Document
Move the SharedResourceRequest, animation timer, and current frame
state out of ImageStyleValue and into a Document-owned table keyed
by resolved image URL. ImageStyleValue now keeps only URL metadata
and its client list, so image style values no longer need to trace
GC edges themselves.

Thread the Document through AbstractImageStyleValue APIs that need
decoded image data. CSS image fetches snapshot the stylesheet base URL,
referrer behavior, and origin-clean state instead of retaining the
stylesheet.

Remember each client's registered resolved URL when unregistering. This
keeps a later document base change from leaving an animated image
resource alive.

Add text coverage for inline relative image base URLs, stylesheet
referrers, imported stylesheet origin-clean behavior, inline @import
initiator type, and unregistering an animated background image after a
base element change.
2026-06-06 23:29:48 +02:00
Shannon Booth
8c7eae90c8 LibWeb: Preserve inline handler ordering after parse failure
On inline handler parse failure, keep the event handler map entry and
set its value to null instead of removing it. This preserves the handler
listener’s position so a later valid attribute value does not get
appended out of order.
2026-06-06 19:18:11 +02:00
Shannon Booth
a455d27e32 LibWeb/WebAssembly: Add missing WebIDL/Types.h include
This otherwise causes a compile error in a future commit where
the header happens to not be included transitively.
2026-06-06 19:16:52 +02:00
Timothy Flynn
4d51499809 LibSyntax+LibJS+LibWebView: Port the syntax highlighter to UTF-8
LibSyntax is the only remaining user of UTF-32 in the code base. Let's
use UTF-8 here.

Bonus: The tests added here for non-ASCII sources actually used to
crash the old UTF-32 implementation.
2026-06-06 18:42:18 +02:00
Timothy Flynn
87cdeda93c LibSyntax+LibJS+LibWeb+LibWebView: Remove unused syntax highlighter code
A future patch will port LibSyntax away from UTF-32. The less code that
needs to be ported, the easier that will be.
2026-06-06 18:42:18 +02:00
Timothy Flynn
e6c68e9e91 LibUnicode: Remove unused UTF-32 segmenter support 2026-06-06 18:42:18 +02:00
Shannon Booth
09d11bf2e3 LibWeb: Use FormDataEntryValue for FormData.get()
The bindings generator can now resolve nullable FormDataEntryValue
return types, so remove the expanded union spelling and the old FIXME.
2026-06-06 16:59:12 +02:00
Aliaksandr Kalenik
852c7a10f3 LibWeb: Let image paint callers own clipping
DecodedImageData::paint() used to take both a destination and a
clip rectangle even though most callers passed the same value. SVG
image painting used that API to wrap every nested SVG display list in
save/add-clip/restore, which put an unbounded command in front of
the bounded nested-list command and made offscreen SVG image content
harder to cull.

Move clipping to ImagePaintable, where the object-fit destination can
be compared with the replaced element box. CSS image and marker
painting continue to draw into their destination rect, while repeated
background images keep their explicit tile clip. The scaled decoded
image display-list command now stores only its destination rect and
uses that as its bounds; playback still clips decoded images to that
rect so bitmap rendering stays unchanged.
2026-06-06 13:23:21 +01:00
Tim Ledbetter
cdb8762c8f LibWebView: Add a --screenshot-path option
This option saves screenshots to the given location.
2026-06-07 00:20:19 +12:00
Shannon Booth
484f2dba79 LibWeb/Fetch: Implement CORS-preflight cache 2026-06-06 13:48:43 +02:00
Aliaksandr Kalenik
e9fe045de6 LibWeb: Do not copy nested display list command bytes
PaintNestedDisplayList carried both a display list resource id and an
inline copy of that resource's command buffer. Repeated SVG image paints
therefore duplicated the nested command stream in every parent display
list even though resource storage already owns and deduplicates it.

Drop the inline command byte span and replay nested display lists from
the resource table. Resource collection now follows the referenced
resource's command bytes as well, so cached paint data and compositor
transactions keep the same nested resource retention behavior.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9929
2026-06-06 11:30:15 +01:00
Andreas Kling
570ea59277 LibWeb: Run same-document commit handlers during entry update
Move Navigation API commit handler completion into a helper. This lets
same-document entry updates run currententrychange before the intercept
handlers. Keep same-document traversals from aborting the ongoing
NavigateEvent before that entry update runs.

Add text coverage for intercepted and non-intercepted same-document
history traversals updating the Navigation API current entry before
navigatesuccess.
2026-06-06 11:34:50 +02:00
Andreas Kling
3ec9733efe LibWeb: Resume intercepted history traversals
When a traverse navigate event is intercepted, queue the resume step
specified by the Navigation API. This keeps intercepted traversals from
stopping at URL update time.

Do not resume that queued step if the intercepted NavigateEvent was
aborted or replaced by a newer ongoing event before it runs. Add tests
for the basic intercepted traverse case and the superseded intercepted
traverse case.
2026-06-06 11:34:50 +02:00
sideshowbarker
e356fd8188 LibWeb: Paint heavily-tiled non-image backgrounds as a single pattern
Problem: On https://turbovision.in6-addr.net a tiny-background-size +
background-repeat tile over a large painted area crashed WebContent.

Cause: BackgroundPainting was recording one paint command per tile for
any repeating background that’s not a decoded image. A small tile over a
large area could produce literally millions of commands — resulting in a
display list exceeding MAX_MESSAGE_PAYLOAD_SIZE, and tripping an assert.

Fix: When a repeating AbstractImageStyleValue would emit more tiles than
a fixed threshold, record a single tile into a nested display list and,
reusing some existing SVG pattern machinery, fill the coverage rect with
a PatternPaintStyle. We render the tile once, and repeat it with a
tiling shader — so the display list holds a single command regardless of
tile count. Normal backgrounds keep their exact per-tile painting.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9876
2026-06-06 09:34:09 +01:00
Andreas Kling
6ecfcd3e68 LibWeb+LibJS: Cache decoded JS bytecode sidecars
Add a ref-counted decoded bytecode cache backing so bytecode cache
materialization can create fresh script or module records from a shared
decoded sidecar without passing around one-shot raw blob ownership.

Keep that backing in ExecutableBacking for records materialized from
bytecode cache sidecars, so the immutable decoded data stays alive for
as long as the installed record needs it.

Cover the shared backing path with a bytecode-cache test that
materializes and runs two scripts from one decoded backing.
2026-06-06 09:15:09 +02:00
Andreas Kling
72720bc229 LibWeb: Preserve JS bytecode in memory cache
Store JavaScript bytecode side data in the WebContent HTTP memory
cache and replay it when serving cached responses. Also update an
already-complete memory-cache entry when asynchronous bytecode cache
generation finishes, so the first source-only response does not keep
shadowing the disk-cache sidecar during same-process navigations.

Keep the HTTP memory-cache backfill keyed with the request headers that
populated the memory-cache entry, so Vary responses still receive their
generated bytecode sidecar.

Add LibHTTP coverage for round-tripping bytecode side data through a
memory-cache entry, attaching it after the response body has already
been cached, and matching Vary headers during updates. Add LibWeb
coverage for preserving the memory-cache request headers when cloning
responses.
2026-06-06 09:15:09 +02:00
Aliaksandr Kalenik
221219e00c LibWeb: Track out-of-flow descendant visual contexts
Accumulated visual contexts only recorded the state used by normal
descendants. Fixed descendants started from the visual viewport, and
absolute descendants rebuilt their state from the containing block. That
could drop CSS clip and clip-path nodes from ancestors between the
positioned box and descendant, even though those clips still apply.

Carry separate transient AVC states for normal descendants,
absolute-position descendants, and fixed-position descendants while
building the AVC tree. The top-down paintable walk adds effects and CSS
clipping to positioned descendant contexts, and containing blocks switch
those contexts back to the normal context.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/9909
2026-06-05 23:27:21 +01:00
Andreas Kling
ec421d7fa4 LibWeb+LibJS: Validate bytecode cache blobs off-thread
Warm cache hits used to validate bytecode cache blobs on the main
thread. Route script and module sidecars through a worker step that
decodes and validates the cache blob, then returns the validated blob
for main-thread materialization.

Keep the source bytes mmap-backed and avoid decoding the full source on
cache hits. The main thread still computes the UTF-16 source length so
validation can reject stale blobs before materialization.

Remove the decoded source length getter now that sidecar validation uses
the explicit validation API instead.
2026-06-05 21:55:55 +02:00
Andreas Kling
bb20f15965 LibJS: Prepare bytecode cache validation off-thread
Add an explicit validation entry point for decoded bytecode cache blobs.
This lets callers validate a blob before materialization while keeping
the existing validated-before-use invariant in place.

Make validation idempotent so a prevalidated blob is not walked again
when materialization reaches the same check. Keep the existing decoded
source length query for callers that still validate synchronously.

Route decoded cache blob owner destruction through the origin event
loop. This lets a worker decode or reject mapped bytecode without
releasing non-atomically refcounted ImmutableBytes off-thread, while
lazy cached function materialization can still retain mmap-backed
bytecode.
2026-06-05 21:55:55 +02:00
Andreas Kling
bf81464904 LibWeb+LibJS: Remove rust_pipeline_available
The Rust pipeline is always available now, so the getter only wrapped
code that always ran. Remove it and make the JavaScript fetch paths use
the off-thread Rust pipeline directly.

This also removes the unreachable synchronous fallback branches from the
classic script and module fetch paths.
2026-06-05 21:55:55 +02:00
Andreas Kling
0d05c89778 LibJS: Merge bytecode cache validation walks
Cache materialization used to validate source ranges and bytecode in
separate passes. That made function and class tables decode the same
payloads repeatedly before materialization decoded them again.

Make the materialization validator check source ranges, index bounds,
and bytecode in the same recursive walk. Nested cached function
executables are now decoded once for validation instead of once for
ranges and once for bytecode.
2026-06-05 21:55:55 +02:00
Andreas Kling
9143ad4c96 LibJS: Avoid revalidating cached bytecode executables
Cache blobs already validate decoded bytecode before rebuilding C++
Bytecode::Executable objects. Keep that as the only cache validation
pass and mark the decoded cache state once it completes.

Materialization now asserts that cache blobs and lazy cached function
records passed through validation before they can be installed or
decoded. This keeps the invariant without re-running the same validator
from rust_create_executable().
2026-06-05 21:55:55 +02:00