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.
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
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.
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.
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.
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.
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().
The inline and replaced paint phase walks every descendant even for
block-only contexts. Track whether a stacking context has inline or
replaced descendants while the stacking-context tree is built, then
skip the phase when it cannot produce display-list commands. This adds
one bool to StackingContext.
Stacking contexts already collect non-positioned floating descendants
while building the paint tree. Use that list to avoid walking the
whole context for the float paint phase when no float can be painted.
PaintableBox::record_hit_test_items() is called for every paint phase,
but it only emits box hit-test entries during the background and
overlay passes. Return before touching the hit-test display list during
the other phases so cached paint replay stops repeating no-op work.
The hyperfine delta is within noise.
DisplayListRecorder::replay_cached_commands() always entered the
display-list decoder to update save nesting, even when a paintable had
no cached commands. Empty command caches are common on the
ViewportPaintable benchmark, so return before decoding when the cache
is empty.
Perhaps this made a difference with an older version of the IDL
generator, but as far as I can tell, this no longer has any effect.
Remove the use of this attribute to match the specification IDL
definition.
Remove BackgroundAction after ImageDecoder stopped using it. Drop its
dedicated test target and sources from LibThreading.
Replace the LibCore stream tests' remaining usage with explicit Thread
objects so the tree no longer depends on the removed API.
Dispatch image decode work to ThreadPool workers instead of the old
BackgroundAction helper. BackgroundAction funneled all jobs through one
background thread, so image decodes were still serialized. The pool
lets independent decode jobs run in parallel while completions are
posted back to the origin event loop.
Keep pending decode state as a small cancel flag. Make animated
sessions ref-counted with a mutex so overlapping frame requests cannot
race shared decoders once jobs run in parallel.
Problem: The abortsignal-timeout.html test was (still) intermittently
failing under CI — printing “…at least 10 milliseconds: false”.
Cause: The test asserts AbortSignal.timeout(10) fired >= 10ms later,
measured as a wall-clock time of performance.now() delta + 1ms fudge.
But that involves timings from two *different* clocks: performance.now()
uses CLOCK_MONOTONIC, while the timeout timer is armed and fired against
CLOCK_MONOTONIC_COARSE (the event-loop clock) — which is quantized to
the kernel tick, and which lags the precise clock by up to a tick. Thus,
a 10ms coarse-scheduled timeout can fall short of 10ms of precise time
by up to one tick. So what was likely happening is: When that shortfall
exceeds the 1ms fudge (coarse-tick kernels, or ticks delayed under CI
load), the delta landed under 10ms. The 1ms fudge added by 6fa32fbf69
narrowed but never closed the race — because the check gates on host
timer/clock precision, rather than on AbortSignal behavior.
Fix: Drop the wall-clock timing assertion. Keep the deterministic checks
that actually exercise AbortSignal.timeout: The abort fires, its
reason is TimeoutError, and the event is trusted. And add a synchronous
check that the signal isn’t aborted immediately after creation – which
confirms the abort is deferred, without racing the clock.
After `Native.css` was removed in the last commit only
`libweb-buttonfacedisabled` and `libweb-buttonfacehover` remain in use,
so the rest can be removed.
Resolving these colors was also the only use of `document` in
`ColorResolutionContex` so we can remove that too.
Replacing the text node's contents with the normalized value after each
keystroke made it impossible to type some inputs. For example, `1e`
would cause the text node to be emptied, making it impossible to type
`1e2`. Also, `time`, `date`, and other time-related input types had no
intermediate valid values, so it was genuinely impossible to type in
them.
Additionally, typed numbers weren't being parsed as floats before
normalization, so even just typing `1.` would clear the text node, so
it was impossible to type a fractional number.
This isn't strictly correct as it stands currently, since the size
attribute isn't supposed to affect type="time" and others, but those
types currently end up with zero width instead.
Size could probably be applied through shadow DOM style, and the input
layout box would simply allow content sizing.
The `font-family` descriptor may not be present, so handle that
gracefully. We already did so, but now it's an official part of the
spec.
Corresponds to:
75299e7be1cfb59f593a
Problem: Borked layout on (flex-styled) “D&D Beyond” site.
Cause: FormattingContext::box_baseline() was applying the box’s
vertical-align unconditionally. But vertical-align shouldn’t be
consulted for flex items or grid items.
Fix: Skip vertical-align handling in box_baseline() when the box is a
flex or grid item.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/9840
This change gives each shadow root its host before appending its
children, and asserts that a root has no children when it's assigned to
a host. This ensures the children inherit the correct connectedness.
Otherwise, without this change, the user-agent shadow trees for color
and file inputs append their children before the shadow root is given
a host which, if the input element has already been inserted, means the
children stay marked disconnected despite being present in the rendered
tree. Disconnected nodes then skip layout invalidations they should
trigger.
Fixes a crash when submitting a prompt on https://chatgpt.com
Create the wasm utility event loop with
Core::EventLoop::initialize_for_current_thread() so it follows the same
process-lifetime model as other program main loops.
Make EventLoop::current() enforce the presence of a current event loop
directly, and make EventLoop::pump() verify that it is pumping the
current thread event loop. This keeps the one-loop-per-thread invariant
explicit across the public EventLoop entry points.
Post off-thread font, script, and DNS completion work back to direct
Core::EventLoop references. These callbacks target the process main
loop, which is intentionally kept alive for the lifetime of the
process.
Pass direct Core::EventLoop references through media producer and
playback plumbing that posts work back to the main thread. The browser
process main loops stay alive for the process lifetime, so these paths
no longer need weak event loop references.
Update LibMedia tests to pass their stack event loop directly to the
producer helpers.
Store direct Core::EventLoop references in WebDriver and the
Compositor when callbacks post back to the process main loop. The
main event loop is intentionally kept alive for the lifetime of these
services, so these paths no longer need WeakEventLoopReference guards.
Add an explicit initializer for process-lifetime event loops and use it
for browser, helper service, and utility main loops. This preserves weak
event loop references for cross-thread users while making main thread
loop lifetime independent of normal program teardown.
Replace the per-thread EventLoop stack with a single thread-local
pointer. Constructing an EventLoop now requires that the current thread
does not already have one, and exec() and spin_until() operate only on
that current loop instead of pushing a temporary nested loop.
LibLine was the last user that needed nested Core event loops, so the
stack allocation and pthread cleanup machinery can go away.
Use libedit's readline-compatible interface for the JavaScript REPL so
line editing, history, and tab completion no longer depend on LibLine.
The REPL keeps its existing multiline input and completion behavior,
but no longer provides LibLine's live syntax highlighting.
Remove the unused LibLine dependency from the wasm utility and delete
the LibLine library from the build now that it has no remaining
consumers.
This adds a tier-up mechanism at loop edges, making it so we can
seamlessly (ish) transition between interpreted and native code so we
can start running wasm code immediately after validation while
compilation happens in the background, and switching to native code
eventually once we hit a big enough function that would benefit from
being compiled to begin with.
When collapsed vertical tabs are expanded on hover, the collapse check
used QCursor::pos() against the vertical tabs rect. On some platforms,
after the cursor leaves the browser window entirely, that position can
remain at the last in-window coordinate, so the tabs stay expanded.
UA and user stylesheets do not have owner nodes or owner rules, so their
matched rules cannot be mapped through the generic stylesheet identifier
helper. Share the built-in UA stylesheet enumeration and map UA rules by
the matched CSSStyleSheet object, so that they stay in sync with any
future changes.
Resolve applied-rule stylesheet identities through StyleSheetsActor and
include Firefox parentStyleSheet, line, and column fields on rule forms.
Firefox can then show matched rules as stylesheet rules and open the
corresponding CSS source location from the Rules panel.
Include parser rule locations and stylesheet identities in the applied
style rule data sent to DevTools. This gives the protocol layer enough
information to map matched rules to existing stylesheet resources
without guessing from displayed rule text.
Collect the style rules that apply to an inspected element and expose
them through the existing DOM node inspection path. This gives Firefox's
Rules panel real rule forms instead of the previous empty getApplied
response.
Extend the existing DOM node inspection request with an options payload
and carry it through the browser process, WebView, IPC, and WebContent.
This lets later DevTools requests forward Firefox's top-level flags
without changing any inspected-node behavior yet.