Cached display list command sequences used to carry their own
DisplayListResourceStorage. That kept resource ID sets and referenced
fonts, images, video frames, and nested display lists alive on every
cached phase, even though the command bytes already contain enough
information to discover those references when they are needed.
This makes cached command sequences store only command bytes. Resource
references are collected transiently from those bytes when a cache entry
is installed or invalidated. The navigable's central display list
resource storage now keeps cache reference counts, so compositor pruning
retains resources used by live cached commands without duplicating
storage in each sequence.
Use selection-specific caret hit testing while starting and extending
mouse selections. The public caret-position API keeps its normal line
ranking, but selection drags now snap below-line movement to line edges
and prefer the previous line when starting in a nearby inter-line gap.
Add coverage for dragging from message text, after-text space, gutters,
author names, avatar-adjacent areas, and row bottoms so these inert
message regions reliably start selection.
Add a debug-menu toggle for caret hit testing at the mouse position.
Paint the insertion rect and log the result so selection bugs can be
inspected without temporary probes.
Request frames and repaint invalidation when the overlay state changes.
Also repaint when the caret rect moves within the same text node.
Add the CSSOM View CaretPosition interface and expose the Document API.
Use retained hit-test data to populate offsetNode, offset, and
getClientRect().
Update IDL coverage and the window property baseline. Add a text test.
Build a hit-test display list while recording paint output. Use it as
source of truth for point hit testing instead of recursively walking the
paintable tree in reverse paint order.
The retained list records target paintables, visual context indices,
border radii, caret rects, and line metadata needed by hit testing. It
also keeps a spatial index so point queries inspect nearby items before
checking containment in paint order.
Refresh scroll state before hit testing so visual context transforms use
current scroll offsets. Add text tests for rounded hit regions and
selection across non-text content.
If a page contains multiple <link rel="icon"> elements, we would send
each of them to the UI process. We would then just use whichever was
sent last as the favicon in the UI.
We now only send the favicon that was chosen for the document. This
will either be the largest icon decoded from a link element, or the
singular fallback icon.
We currently pick the first favicon in reverse tree order. But we are
encouraged by the spec to pick the most appropraite icon. We now
consider the size of the decoded icon, and choose the largest.
Only use the preferred color scheme for a loading top-level canvas
when the root used color scheme has not been computed yet. Once a
layout tree exists, non-opted pages still resolve system colors with
the default light scheme, so forcing a dark canvas makes them disagree
until parsing finishes.
Extend the loading canvas test to cover the non-opted case and reset
the test-only preferred color scheme override before finishing.
Only use the loading-time top-level canvas fallback when the root
color-scheme value is still normal. An explicit light scheme on the
root element already gives the canvas a light used scheme, so replacing
it with the preferred dark scheme makes the viewport disagree with the
computed system colors until readiness advances.
Add internals coverage for the document canvas scheme and a text test
that exercises the loading state with a dark preferred color scheme.
Use document color schemes when choosing the canvas color for a root
whose color-scheme property is still normal. This keeps the transient
canvas aligned with the preferred scheme once a meta color-scheme has
been parsed, before style later recomputes the root used color scheme.
This avoids a light canvas frame while loading dark-capable pages in
dark mode without changing pages that explicitly force the root color
scheme.
Recompute supported color schemes through a setter that invalidates
style and media queries. Use the preferred color scheme for a loading
top-level document until metadata or root style gives it a more specific
canvas scheme.
Add coverage for dynamically inserting a meta color-scheme element.
Opt empty about:blank documents into both light and dark supported
color schemes. This covers both navigation-created about:blank documents
and the initial about:blank document created with a browsing context, so
dark mode can choose the dark Canvas color before page content arrives.
Display lists owned the accumulated visual context tree through a
ref-counted pointer. That tied visual-context state to display-list
lifetime and made compositor updates treat the two as one unit, even
though AVC trees need to become independently updateable compositor
state.
Make accumulated visual context trees plain versioned values, have each
display list store the compatible tree version, and pass the matching
tree alongside display-list updates and replay calls. Replay verifies
that the provided tree matches the display list before executing it.
This prepares the compositor for receiving AVC tree updates separately
from display-list updates: it now accepts the tree as a separate update
parameter, stores it next to the display list, and uses that stored tree
for replay and async-scroll hit testing. Nested display-list resources
carry their own tree snapshots for the same version check.
Add IPC structures and requests for inspecting grid layout data from
WebContent.
WebView forwards the async replies to LibDevTools and exposes the grid
highlighter hooks used by the protocol layer.
Parse Firefox grid highlighter options in WebContent and store them with
the active grid highlight.
Snapshot DevTools DOM mutation payloads immediately, but defer subtree
serialization until the target document's layout is up to date.
This avoids re-entering layout-backed DOM serialization from style and
layout updates, which could crash WebContent while DevTools was
listening for mutations.
Track whether WebContent still needs a beforeunload check and let the
frontends immediately remove a tab or window when no prompt can be
shown. WebContent still receives the close request so pagehide, unload,
and cleanup steps can run.
When the visible view is removed immediately, keep detached ownership of
the WebContent page until it reports that the top-level traversable
closed. If no acknowledgement arrives, release detached ownership and
ask ProcessManager to shut down the unused WebContent process.
Use the existing animated style update path when document style
recalculation reaches an element through inherited style recomputation.
Paused or filled animations can contain inherit, rem, rch, or other
font-relative keyframe values that depend on parent or root metrics.
Those dependencies can change even when the target's inherited computed
values do not otherwise change.
Make the document traversal opt in explicitly so animation-driven
inherited recomputation does not schedule another animation update while
propagating animated inherited values.
Add coverage for a media-gated root font-size change affecting a paused
rem-based animation. Update the font-stretch WPT expectation now that
its inherited-animation case passes.
Use the viewport metric dependency flags to restyle only elements whose
computed values can change after a viewport resize. Descendants that
inherit changed values are reached through the existing inherited-style
update path.
Keep targeted style reads correct by treating pending media query
evaluation as style dirtiness. Seed the style computer with the latest
viewport before resolving pending animated style, so viewport-unit
keyframes do not use stale metrics.
Share pseudo-element recomputation with inherited-style updates, so
pseudos stay current when their originating element changes only via
inherited values.
Schedule animated style updates when inherited style recomputation can
affect existing animations.
Add viewport resize coverage for media queries, inherited font metrics,
monospace font-size recascade, line-height percentages, font-relative
and pending viewport-unit animations, inherited pseudo-elements, direct
pseudo viewport dependencies, and canvas currentColor reads.
Use GC::WeakHashSet for the registry instead of IGNORE_GC. The notify
and layout update paths now snapshot the live weak entries into
RootVector before iterating, preserving the existing protection against
mutation while avoiding an unvisited strong GC container field.
Request a rendering update after document visibility changes back to
visible. Hidden documents can leave animation frame callbacks or CSS
animation work pending after their last rendering update is skipped,
so showing the page needs to schedule a fresh rendering tick.
Async scrolling display-list items were still recorded by helper
functions in LibWeb/Compositor even though they are produced while
walking the paint tree. That kept paint-time knowledge about boxes,
viewport state, and wheel-event regions in the compositor-facing code.
Move viewport setup and final metadata emission to ViewportPaintable,
and move per-box scroll-node, hit-test, scrollbar, wheel-region, and
sticky-area item recording to PaintableBox. AsyncScrollingState now
keeps the compositor-side conversion and lookup logic for consuming the
recorded metadata.
Notify the UI process with the solid canvas background color recorded
for the top-level document. This is the Canvas system color with the
effective document background composited over it, matching the color
used before normal painting.
Store that color on the view and use it when AppKit, Qt, and Gtk need
to fill areas exposed while an older bitmap is still on screen during a
window resize.
The layout loop added for container queries intentionally caps repeated
style/layout passes, since each layout can enqueue more size-query style
work. That cap should still apply, but absence of post-layout style work
does not by itself mean the document is clean.
Only leave the loop when there is no pending post-layout style work and
layout is up to date. Otherwise spend another capped pass flushing the
layout-only invalidation instead of falling through to the final
layout_is_up_to_date() verification.
Add crash coverage for a clientHeight read after nested container query
invalidations, matching the synchronous layout flush path.
When an embedded document was render-blocked, the parent display list
recording skipped drawing that iframe's compositor surface. Once the
child document later unblocked, only the child surface was repainted, so
the parent could keep replaying a display list that had no surface draw
command until another invalidation, such as resize, forced a recording.
Invalidate the containing iframe when a document's render-blocking set
becomes empty so the parent display list records the child surface. Add
a deterministic reftest that gates a render-blocking stylesheet on a
test-server signal, forcing the parent to paint the blocked iframe
before unblocking it.
Preserve leading BOMs when parsing already-decoded HTML strings, since
those strings do not go through the encoded byte decoder path.
Decoded markup from JS strings can also contain WTF-8 for lone surrogate
code units. Keep the common scalar UTF-8 path to a single validation and
copy, but replace surrogates before handing bytes to the Rust tokenizer.
Add text coverage for DOMParser and innerHTML string parsing, including
leading BOMs, text and attributes, lone high and low surrogates, and a
valid surrogate pair.
Do not build content blocker cosmetic style sheets for decoded SVG
image documents. These documents are resource documents created for
image painting rather than ordinary navigable documents, and other
engines keep extension cosmetic CSS out of them.
Add text coverage that verifies a generic cosmetic rule still applies
to the embedding HTML document while a matching element inside an SVG
loaded through <img> keeps rendering.
Refresh content blocker styles when connected elements gain or change
class or id tokens that can affect generic cosmetic selectors. Cache the
class and id tokens covered by each document's content blocker
stylesheet, then ask the adblock engine whether newly-added tokens can
unlock selectors before invalidating user style for the whole page.
This keeps dynamic cosmetic hiding correct without refreshing blocker
CSS for unrelated class and id mutations.
Add text coverage for irrelevant class/id mutations that should preserve
author style invalidation without refreshing blocker CSS. Also prove
matching tokens still hide elements.
Replace PseudoClassInvalidator's subtree scan with targeted
invalidation for elements whose pseudo-class state changes. This scopes
state changes to affected selectors instead of rechecking a whole
common-ancestor subtree.
Use the ancestor chain that matches each pseudo-class. Hover walks the
shadow-including chain. :focus-within walks the flat-tree chain, so
slotted content invalidates its assigned slot and relevant shadow-tree
descendants. Focus, FocusVisible, and Target invalidate just the state
node.
Route each affected element through Element::invalidate_style with the
pseudo-class property. This uses the same invalidation-plan machinery as
Disabled, Checked, and other pseudo-class state changes.
Interaction state pseudo classes are not tracked in :has() metadata, so
schedule :has() ancestor invalidation explicitly when the state flips.
The callers no longer need cross-scope branching. The chain walk handles
shadow boundaries, and property invalidation already visits every
observer style scope.
Build the user stylesheet only for document style scopes, since user
rules are already considered relevant across shadow boundaries during
rule matching. This avoids regenerating and reparsing the same cosmetic
content blocker stylesheet for every shadow root in the document.
Keep the generated cosmetic stylesheet cached on the Document and clear
it whenever user style is invalidated, so content blocker changes still
produce fresh CSS for the next style update.
The base URL change handler checked whether any style scope contained
a `:local-link` rule before walking the document's links, this forced
a rule cache rebuild, which is generally slower than the link walk we
were trying to avoid.
On Speedometer2 the duplicated rule-cache and invalidation-set
construction accounted for roughly 4% of total samples. Removing the
gate lets the URL-unchanged early-exit handle the no-op case and runs
the link walk only when the URL actually changes, which the profile
showed to be inexpensive on its own.
Represent WebIDL C++ types with a single CppType model that tracks
nullability, optional presence, and contained storage.
GC-like values now use GC::Ref/GC::Ptr directly, while containers choose
"plain", "Root", or "Conservative" container types depending on what
they contain. For example, sequence<Element> becomes a RootVector of
GC::Ref values, while sequence<SomeDictionary> becomes a
ConservativeVector only when the dictionary contains GC-like values.
This moves the generated bindings away from wrapping GC values in
GC::Root by default.
This has broad fallout as the types passed to interfaces for GC
objects changes almost fully across the board.
Keep animated ImageStyleValue frame advancement owned by the
style value. The current frame and loop state live there, so a
separate document scheduler would duplicate ownership of that state.
Start the ImageStyleValue timer only while it has layout clients.
Stop it when the last client unregisters, or when a finite animation
completes. Expose a document-scoped active timer count through
internals for focused regression tests.
Clear image observers when layout nodes detach. Use current-node
cleanup for per-DOM-node clearing, and explicit subtree cleanup for
tree replacement, full tree teardown, and synthetic pseudo-elements.
This keeps large document clearing linear.
Unregister generated-content image providers during layout detach
instead of waiting for GC to finalize the provider.
Cover hidden animated background images, generated content images,
layout node replacement, full layout tree teardown, and document
scoping for the internals counter.
Previously, the fully active callback could fire when the document was
never actually deactivated, which could cause a verification failure in
HTMLMediaElement due to its assumption that the callbacks only fire
when a document's fully active state genuinely changed.
Add a targeted update_style_for_element() mode that resolves one
flat-tree inheritance chain. Normal callers still get computed style in
display:none subtrees. Focusability stops when that chain resolves to
display:none.
The targeted path falls back to normal document style traversal for
document invalidation, full rebuilds, and selector work. That keeps
global dirty state consumed atomically. Local recomputation preserves
layout, display-list, slot, visual-context, and stacking-context
invalidation. It marks children dirty when a recomputed element can
affect descendant style.
Use StopAtDisplayNone for focusable-area rendering checks so incidental
is_focusable() queries do not repeatedly force unrelated document style
work. Rebaseline style invalidation counters for the reduced
getComputedStyle() recomputation scope.
Factor the element-level and document-level side effects from style
recomputation into helpers used by normal document style traversal. This
keeps existing behavior unchanged while letting the later targeted style
update path reuse the same invalidation bookkeeping.
Follow the spec reuse of the initial same-origin about:blank window for
a browsing context's first real navigation. This fixes a crash in
promise-job-entry-different-function-realm.html by preserving the
correct iframe realm.
However, reusing the initial about:blank Window means
create-and-initialize can associate that Window with the pending
Document before session history activation has made the Document active.
Treating a browsing context's active document as its active Window's
associated Document therefore exposes the pending Document too early.
To fix this, add an explicit active document slot to BrowsingContext and
update it when a Document is made active.
A similar fix was attempted in 7fc7263a4d,
but that version still queued navigation tasks through the reused active
Window, tagging them with the pending Document before it was active.
This caused parser-created iframe loads to hang in encoding WPTs. This
commit instead queues those navigation-internal tasks against the
navigable's currently active Document.
The newly added iframe-initial-load-chunked-body.html mimics the same
type of failure seen by the WPT regressions mentioned above.
The spec doesn't say what time to use here but in other places where we
schedule animation events it says to use "the result of applying the
procedure to convert timeline time to origin-relative time to the
current time of the timeline with which animation is associated", so we
do that here as well.
This time is stable per animation frame per timeline so we now correctly
fall back to composite ordering of animation/transition events where we
previously wouldn't (since the scheduled time was so precise that it was
always unique), which causes the imported test to no longer be flakey.
Problem: An iframe whose content changes while it (or an ancestor)
has visibility:hidden isn’t painted once it becomes visible again.
The stale previous frame stays on screen until an unrelated
repaint (e.g., window resize) happens to occur.
Cause: set_needs_repaint() returns early for any document inside an
iframe with a visibility:hidden ancestor — discarding the request
entirely. The navigable’s needs_repaint flag is never set. Nothing
sets it again when the iframe becomes visible — so the rendering
loop keeps skipping it — and its display list stays stale.
Fix: Stop discarding the request in set_needs_repaint(). Instead,
skip painting hidden navigables in the rendering loop — while
leaving needs_repaint set. Once an ancestor iframe becomes
visible, the still-set flag makes the rendering loop paint the
navigable on the next frame.
Fixes https://github.com/LadybirdBrowser/ladybird/issues/9305
Track explicit inherit of non-inherited properties only on the direct
parent shadow root. A deeper descendant with margin-left: inherit still
inherits from its own parent, so a host margin change does not require
marking every ancestor as possibly affected.
Extend the shadow-root inherited style test to cover both the direct
child case that must still update and the deeper descendant case that
must not trigger broad inherited-style recomputation.
Make style updates reach a fixed point when slot invalidation dirties
assigned nodes after their traversal point. During inherited-style
cascades, only the topmost changed element scans for descendant slots.
Animation inherited-style updates now include the target slot and walk
shadow-including descendants, so host animations propagate inherited
values through shadow trees and assigned slottables. Animated inherited
longhands also carry the same inherited-style invalidation signal as
regular style changes.
Mark custom elements dirty when their :defined state flips, so upgraded
elements do not keep stale :not(:defined) computed style. Add coverage
for slotted menu invalidation, descendant-slot scan counts, target slot
animations, host shadow-tree animations, and explicit inherit from an
animated non-inherited longhand.
Track when style recomputation may require inherited-style work in a
shadow tree, and use that signal when crossing from a shadow host into
its shadow root. Shadow descendants can explicitly inherit normally
non-inherited host properties, so any host style change may need
inherited-style recomputation there.
Use the CSS property definition to tell whether changed longhands need
to propagate to shadow descendants. Do the same after recomputing
inheritance-dependent values, such as host font-size: 2em after a parent
font-size change.
The shadow DOM tests cover inline and class-driven inherited host style
changes, explicit inherit for non-inherited host properties, relative
units on hosts, and nested slotted inheritance updates.
Install the inherited about base URL before setting the document URL so
fallback-base URL consumers see the correct source during URL-dependent
style and content blocker work.