Commit graph

1944 commits

Author SHA1 Message Date
Sam Atkins
9996403e73 LibWeb/CSS: Extract base class from MediaFeature
`<media-feature>` and the upcoming `<size-feature>` from `@container`,
share the same syntax and almost all of their behaviour. To avoid a lot
of duplication, pull as much as possible into a FeatureQuery template
class that they will both inherit from.

MediaFeatureValue is renamed FeatureValue as it's also shared by both.

No behaviour change.
2026-05-20 13:00:50 +01:00
Sam Atkins
34382a2aca LibWeb/HTML: Add missing include for KeywordStyleValue 2026-05-20 13:00:50 +01:00
Tim Ledbetter
b67d73a661 LibWeb: Apply ::first-letter pseudo-element styles
We now apply first letter styles by splitting text with a first-letter
style applied into 2 `TextSliceNode` objects.  The
`DOM::Text` layout  node always points at the non first-letter slice
and the first-letter slice is  reachable via
`TextSliceNode::first_letter_slice()`.

First letter splitting works by `TreeBuilder` walking a block
container's inline descendants to find the first typographic letter
unit per the pattern given in  css-pseudo level 4, which is then
wrapped in an anonymous inline box styled with the `::first-letter`
computed properties.

Consumers that map between DOM offsets and layout geometry
are updated to visit all slices of a `DOM::Text` through
`TextOffsetMapping`.
2026-05-20 12:09:19 +01:00
Andreas Kling
5fedacb7de LibWeb: Move textarea Home and End by line
Make unmodified Home and End in textarea use the current line
boundary instead of the whole control. Keep modified Home and End on
the existing whole-control path so Ctrl+Home and Ctrl+End still jump
across the textarea.

Update the textarea keyboard navigation test to cover the fixed line
movement and the preserved modified-key behavior.
2026-05-20 12:26:20 +02:00
Andreas Kling
f7411a36a1 LibWeb: Notify clients when reload starts
Emit the existing page_did_start_loading notification when a
top-level reload starts repopulating the document. Normal navigation
already sends this notification earlier in the algorithm, but reload
enters through the session history path and skipped the UI signal.

This lets browser chrome show its loading indicator for reloads without
frontend-specific reload button hooks.
2026-05-20 09:37:33 +02:00
Tim Ledbetter
ee55344997 LibWeb: Stop completed image fetches from retaining the prior document
When an image fetch finished or failed, the cached request object
released its fetch controller before releasing its load-event delayer.
Releasing the delayer decrements the document's load-event delay count,
which can re-enter the HTML parser end check and fire the document load
event. If anything triggers a same-URL image fetch during that
re-entry,  the cached request gets a fresh fetch controller and the
request get's kept alive, which also keeps the assocaited window and
document objects alive.
2026-05-20 01:47:14 +02:00
Zaggy1024
8cc00c09fa LibWeb: Only update the media controls' timeline while playing 2026-05-19 16:37:59 -05:00
Aliaksandr Kalenik
6063650261 LibWeb: Stop using VideoFrameSource for video frame updates
Future compositor-process work needs to push video frame updates without
going through VideoFrameSource. That object cannot be shared through
IPC, so video display-list resources now use stable VideoFrameResourceId
values and the current frame is sent through explicit resource/update
commands.
2026-05-19 22:11:15 +02:00
Aliaksandr Kalenik
262a2796b2 LibWeb: Paint iframe surfaces through compositor queue order
Represent main-thread presents as compositor commands so iframe presents
remain ordered before later parent display-list and present work. Nested
painting now enqueues the child present without blocking the main
thread.

When a nested present publishes to a compositor surface owned by another
context on the same page thread, update that target context directly
inside the compositor loop. This keeps the iframe surface available
before the queued parent present replays its display list.
2026-05-18 20:11:31 +02:00
Aliaksandr Kalenik
81b5b343d9 LibWeb: Share WebContent compositor thread across pages
Move compositor-thread ownership to WebContent's PageHost so every Page
object in one WebContent process registers its navigables on the same
compositor thread. This covers auxiliary pages created by window.open(),
while worker and SVG helper pages continue to skip compositor thread
creation.

Keep page presentation keyed by page id. Each presenting context records
the page id it presents for, and static compositor entry points route
ready-to-paint, async scrolling, and viewport scrollbar events to that
page's presenting context on the shared thread.
2026-05-18 20:11:31 +02:00
Martin Chrástek
437c8b1d19 LibWeb: Implement legacy-clone of session storage shed on window.open
When a new window is opened via window.open() with an opener
(non-null), the session storage must be cloned from the opener's
storage shed into the new window's storage shed. This implements
the legacy-clone a traversable storage shed algorithm from the
Storage spec.
2026-05-18 16:38:15 +02:00
Aliaksandr Kalenik
93bbdf1f55 LibWeb: Use compositor surface IDs for embedded content
Display lists kept canvas and nested navigable content alive through
ExternalContentSource objects. That made the resource graph depend on
process-local object identity instead of a stable surface handle, which
blocks compositor process isolation and made teardown-sensitive embedded
content harder to reason about.

Allocate CompositorSurfaceId values for canvases and child navigables,
publish their backing stores to the owning compositor, and paint them
with DrawCompositorSurface. Child navigables now publish to parent
compositors by CompositorContextId instead of raw object pointers, so
the in-process path uses the same stable addressing model required by a
remote compositor.

Clear and skip stale child surfaces during teardown, preserve Skia
canvas state while drawing compositor surfaces, and add display-list
coverage for canvas and iframe compositor surfaces. The nested navigable
async-scrolling baseline now expects DrawCompositorSurface.
2026-05-18 15:27:59 +02:00
InvalidUsernameException
46e91c7ba6 LibWeb: Invalidate img-element when loaded from list of available images
When loading an image, there are two success paths: Either the image is
loaded through fetch, or it is part of the list of available images
already and doesn't need to be downloaded anymore.

Only the fetch code path was invalidating style and layout, meaning that
an image loaded from the list of available images was not visible until
something else caused an invalidation.

To fix this, perform the same invalidation in both code paths.

This fixes that most of the images on https://bleepingcomputer.com/ were
not loading until hovered. They are using
[`bLazy.JS`](https://github.com/dinbror/blazy), which loads the files on
a disconnected `img` element and then swaps out `src` or `srcset` on the
actual `img` element once the load has completed.

The `requestAnimationFrame`-dance in the testcase is there to ensure
that the test fails reliably without this change applied.
2026-05-18 12:54:49 +02:00
Andreas Kling
3d3e6f4226 LibJS+LibWeb: Keep cached script source text lazy
Avoid decoding warm-cache script responses into full UTF-16 SourceCode
buffers when a bytecode cache sidecar is available. SourceCode now keeps
the original immutable source bytes and source encoding, then decodes
only when full source text or a Function.toString() range is requested.

Compute the bytecode cache source hash while streaming decoded code
points from the response bytes, so cache validation does not force an
intermediate UTF-8 string. Function and class source text metadata now
stores SourceCode ranges instead of views into a materialized buffer.
2026-05-18 09:18:35 +02:00
Andreas Kling
b849af70b8 AK+LibWeb: Reject impossible Variant visit overloads
Make Variant::visit reject typed visitor overloads that cannot be
called for any variant alternative. This catches stale visitors after a
variant payload type changes instead of falling through to a generic
overload.

Update fetch body consumers that still expected ByteBuffer after the
body payload moved to Core::ImmutableBytes.
2026-05-18 01:21:34 +02:00
Andreas Kling
318fb4f2d0 LibWeb: Preserve immutable consumed body bytes
Keep consumed response body bytes in Core::ImmutableBytes instead of
requiring a ByteBuffer. This lets responses that already arrived as
file-backed immutable data keep that representation through body
consumption, while streamed responses can still adopt their
accumulated ByteBuffer without another copy.

Update the body consumers that only inspect bytes to read from
immutable byte views. Font loading still copies at its existing
ownership boundary, where the off-thread preparation path takes a
ByteBuffer.
2026-05-18 01:21:34 +02:00
Andreas Kling
936bb9ca53 LibWeb: Use Rust preload scanner
Replace the C++ speculative HTML parser token walk with the Rust
preload scanner. Keep URL resolution, duplicate suppression, and fetch
issuance in C++ so the scanner only emits base href updates and fetch
candidates.

Use the scanner callback result to stop iteration when the speculative
parser has been stopped.

Update parser comments that still described speculative mock element
production.
2026-05-18 00:23:52 +02:00
Andreas Kling
411c6654e8 LibWeb: Add Rust preload scanner
Add a Rust scanner that walks pending HTML parser input and emits base
href updates or speculative fetch candidates. Keep URL parsing and fetch
issuance in C++ for now, where the Document and request objects live.

Allow the scan callback to stop iteration so the C++ speculative parser
can preserve its stop hook once it is wired up.

Expose a shared Attribute helper for resolving interned local names and
use it from the Rust parser and preload scanner instead of repeating the
same lookup pattern.

Cover link rel handling, preload destination filtering, crossorigin
mapping, and template/foreign-content skipping with Rust unit tests.
2026-05-18 00:23:52 +02:00
Andreas Kling
1c7519f9ef LibWeb: Treat fragment parser documents as disconnected
Keep the temporary document used by HTML fragment parsing from
running post-connection work while the parser is staging nodes there.
This lets scripts from Range.createContextualFragment() remain
unstarted until the returned fragment is inserted into the real
document, and removes the script-specific preparation guard.

Strengthen parser coverage so contextual fragment scripts must wait
until the fragment is applied before running.
2026-05-17 15:35:56 +02:00
Andreas Kling
ccf5a278ab LibWeb: Keep deferred document.close cleanup on its parser
document.close() can defer script-created parser cleanup while a
parser-blocking script is pending. If document.open() installs a new
parser before the old parser resumes, the deferred action must clean up
the parser that scheduled it instead of the document's current parser.

Capture that parser before installing the deferred action. This keeps
the parked cleanup from affecting a parser installed by a later
document.open() call.
2026-05-17 15:35:56 +02:00
Andreas Kling
29784ea397 LibWeb: Remove the C++ HTML tree builder
Delete the old C++ tree-construction implementation and helper classes
that became unused once the Rust parser is unconditional. Remove the C++
stack of open elements, active formatting elements, speculative mock
element, and tree-builder-only token storage.

Keep the C++ parser entry points that still own LibWeb DOM integration,
encoding detection, tokenizer bridging, incremental parsing, and the
speculative parser support used by resource discovery.
2026-05-17 15:35:56 +02:00
Andreas Kling
a7ece4b062 LibWeb: Make the Rust HTML parser unconditional
Remove the runtime selector between the old C++ tree builder and the new
Rust implementation. Always construct HTML documents and fragments with
the Rust parser now that it matches the existing tests.

Simplify dump-html-tree by dropping the backend option that only made
sense while both parser implementations were available.
2026-05-17 15:35:56 +02:00
Andreas Kling
f49335f210 LibWeb: Align declarative shadow root parsing
Teach the Rust parser to recognize declarative shadow root templates and
pass the parsed mode, slot assignment, clonable, serializable, and
focus-delegation flags to the C++ DOM host.

Expose shadowRootSlotAssignment reflection with the spec-defined named
missing and invalid value defaults, and extend the ShadowDOM text test
coverage for the reflected property and parser-created shadow roots.
2026-05-17 15:35:56 +02:00
Andreas Kling
54879bc916 LibWeb: Complete Rust HTML tree construction
Finish the Rust implementation of the spec tree-construction algorithms
needed by the LibWeb test suite. Add the remaining table modes, foster
parenting, scope helpers, adoption agency handling, ruby/list/form and
select cases, frameset state, foreign-content edge cases, and parser
host callbacks.

Preserve behavior that depends on the C++ DOM integration, including
parser-created custom element reactions, fragment quirks mode, arbitrary
fragment namespaces, template fragment mode, fragment form ownership,
MathML annotation-xml boundaries, contextual fragment scripts, parser
script source positions, document.close() parser state, void-element
insertion, and duplicate attribute tracking.

Add focused tests for the parser edge cases that are easy to regress at
the boundary between the Rust tree builder and the C++ DOM host.
2026-05-17 15:35:56 +02:00
Andreas Kling
de12062515 LibWeb: Wire Rust parser scripts and fragments
Preserve Rust parser state across tokenizer runs and stop cleanly when
a parser-blocking script has to execute. Thread the pending script back
through the existing C++ parser entry point so document.write(), input
insertion points, and script bookkeeping continue to use the normal
LibWeb machinery.

Add the fragment parser setup needed by innerHTML and contextual
fragment parsing, including context elements, form ownership, tokenizer
state selection, text coalescing, and foreign-content integration.
2026-05-17 15:35:56 +02:00
Andreas Kling
2e9875770e LibWeb: Add initial Rust HTML tree construction
Implement the first Rust tree builder pass around the tokenizer and the
LibWeb DOM host hooks. Cover the document setup, insertion-mode
dispatch, ordinary body insertion, basic table handling, active
formatting element reconstruction, and foreign-content routing.

Leave the C++ parser available at runtime so the new path can be tested
against the old implementation while the remaining tree-construction
algorithms are filled in.
2026-05-17 15:35:56 +02:00
Andreas Kling
09296315c2 LibWeb: Add Rust HTML parser host plumbing
Add the C++ and Rust scaffolding that lets the tree builder live in
Rust while the DOM remains owned by LibWeb. Keep the exported surface
small: Rust stores parser state, and C++ provides node creation,
insertion, script, template, and GC hooks.

Route dump-html-tree through the selectable parser backend so the new
implementation can be exercised beside the existing parser while it is
being brought up.
2026-05-17 15:35:56 +02:00
Andreas Kling
5b63cb5f37 LibWeb: Avoid unsafe tokenizer state conversion
Replace the FFI tokenizer state transmute with an explicit conversion
from the incoming numeric value. The old code range-checked against the
last state before transmuting, which matched today's contiguous enum but
left the conversion dependent on that layout detail.

Returning early for unknown values keeps the FFI boundary tolerant while
removing a source of possible invalid enum discriminants.
2026-05-17 15:35:56 +02:00
Andreas Kling
11e69d5e49 LibWeb: Support dump tools without resource loading
Allow parser dump utilities to run without installing a ResourceLoader.
Short-circuit resource fetch entry points used by links, stylesheets,
and shared resource requests when no loader is present.

Keep those failures local to headless utility use so dump-html-tree can
parse real pages without a full browser page loader or request service.
2026-05-17 15:35:56 +02:00
Andreas Kling
edf909f83d Utilities: Add dump-html-tree
Add a small parser utility for inspecting tree-construction output in
the same spirit as dump-html-tokens. Print an annotated DOM tree so
parser changes can be compared without launching the browser.

Keep a silent iteration mode for external benchmark tools, where the
parser still builds the DOM but the utility avoids serialization and
stdout work.
2026-05-17 15:35:56 +02:00
Andreas Kling
541828dbb1 LibWeb: Respect overflow axes for wheel scrolling
Keep the compositor scroll node max offset as the real scroll range,
even for axes that cannot be scrolled by wheel input. Track wheel
scrollability separately so hidden axes are skipped during async wheel
scrolling without clamping away an existing programmatic offset.

Use the viewport-propagated root and body overflow values when deciding
whether viewport axes accept wheel input. Apply wheel deltas only on
axes that can be wheel-scrolled in async metadata and main-thread wheel
default actions, while preserving CSSOM scroll offsets on hidden axes.

Add async scrolling coverage for hidden-axis wheel targeting, preserved
programmatic hidden-axis offsets, and body overflow-x: hidden blocking a
horizontal viewport wheel scroll despite pseudo-element overflow.
2026-05-17 14:19:36 +02:00
Andreas Kling
28e648714d LibWeb: Stop internal IDB databases retaining realms
The process-wide IndexedDB database registry stores internal database
objects in GC roots. Those objects do not need a JavaScript shape or
realm, but they inherited one from PlatformObject. This let an internal
database keep its creating realm, window, and script graph alive.

Make the internal database construct a plain GC cell instead. Callers
provide a heap when they need snapshots of associated connections. This
means the database no longer needs to remember its creating realm.

On x.com, the rooted internal database subgraph shrank from the whole
page graph, including 24k executables, to the database metadata itself.
2026-05-17 00:29:18 +02:00
Andreas Kling
f1c151a17f LibWeb: Release completed link element fetches
HTMLLinkElement only needs to retain its FetchController while a linked
resource fetch is in flight, so that a later attribute change can stop
the old request. Once the current stylesheet/icon/preload fetch has
produced its response, keeping the controller alive retains FetchParams,
the Request, and the request client unnecessarily.

Clear the in-flight controller as each current linked resource fetch
finishes. Stale callbacks from older generations still return without
touching a newer controller.
2026-05-17 00:29:18 +02:00
Andreas Kling
7696c9e26c LibWeb: Release completed shared image fetches
SharedResourceRequest kept its FetchController after the resource had
finished loading or failed. The controller owns FetchParams, which owns
the original Request and its client, so cached decoded images could keep
completed fetch machinery and old window/navigable state alive.

Clear the controller when the shared resource reaches a terminal state.
2026-05-17 00:29:18 +02:00
Andreas Kling
fe31d205a5 LibWeb: Bound per-document decoded image caches
Prune decoded image resources retained by active documents once they
grow beyond a recent working set. Route-heavy applications can load
many unique images through one Document, and the shared resource and
available-image caches would otherwise keep decoded image data alive
after the DOM stopped using those images.

Track cache touches and evict least recently used decoded images from
both caches. This keeps active documents from accumulating unbounded
decoded image resources while preserving a small hot cache for repeat
loads.
2026-05-17 00:29:18 +02:00
Aliaksandr Kalenik
8906011a6b LibWeb: Synchronize display list resources via transactions
Display lists used to own the resource storage needed to replay their
command bytes. That kept the compositor tied to in-process object
ownership: sending a display list update also meant sharing the same
resource container with the recording side.

Move resource storage out of DisplayList and make display list updates
carry a transaction of resources to add and remove. Navigable now tracks
the resources referenced by the current display list, sends only the
delta to the compositor, and trims its recording-side storage to the
active set. The compositor applies those transactions to its own storage
before replacing the cached display list.

This still carries in-process resource objects, but it puts the
ownership boundary in the right place. Command bytes and resource
lifetime are now synchronized explicitly, which is the shape needed
before the compositor can receive serializable resource updates across a
process boundary.
2026-05-16 19:35:24 +02:00
Aliaksandr Kalenik
fd823becd7 LibWeb: Move backing store management into compositor thread
BackingStoreManager was owned by Navigable and allocated on the GC heap,
which left backing-store sizing decisions on the main thread even though
the compositor thread was already responsible for allocating the actual
surfaces. That split ownership makes it harder to isolate the compositor
behind a process boundary.

Move the manager into LibWeb's compositor code and let CompositorThread
thread data own it. The main thread now reports viewport size changes
through a compositor command, and the compositor uses that message to
decide when to resize and publish backing stores. The delayed shrink
timer remains with the main-thread CompositorThread facade so it can use
the Core event loop, but it now only sends another viewport-size update.

This removes the GC edge from Navigable, drops stale WebContent includes
and keeps the existing resize padding and delayed shrink behavior.
2026-05-16 16:36:05 +02:00
Aliaksandr Kalenik
649296ec07 LibWeb: Defer stale main-thread frames during async scroll
While an async scroll present was pending, the main thread could still
record and submit a display list from a stale scroll state before the
compositor-presented frame had reached the UI process. That stale
snapshot could replace the compositor-side scroll state and cause
visible back-and-forth jumps.

Check the async-scroll present defer condition before recording the
frame. The existing post-record check remains in place for races that
become pending while recording is in progress.
2026-05-16 14:50:46 +02:00
Shannon Booth
951e2e1986 LibWeb: Avoid unhandled rejection when reporting module script errors
Report module script evaluation failures without replacing the returned
evaluation promise or rethrowing from the reporting reaction. This
avoids surfacing the same failure as both a script error and an
unhandled promise rejection.
2026-05-16 09:52:35 +02:00
Andreas Kling
881c1484fe LibWeb: Avoid widening ASCII source for bytecode cache hashes
Hash ASCII-backed script source as equivalent UTF-16 data in fixed-size
chunks instead of first forcing SourceCode to allocate a full widened
copy. Keep the existing bytecode cache key stable by preserving the same
byte sequence that the previous utf16_data() path hashed.
2026-05-16 09:10:00 +02:00
Andreas Kling
a646f9d0bf LibJS: Borrow mapped bytecode cache executable bytes
Keep executable bytecode payloads decoded from owner-backed bytecode
cache blobs as ranges into the original blob instead of copying them
into Rust Vec allocations. The mapped blob owner is held by decoded
executable records, including lazy nested function executables, so the
borrowed bytecode remains alive until materialization copies it into the
final C++ Executable.

Use the owner-backed decoder for HTTP bytecode cache hits and keep the
plain byte decoder for tests and in-memory callers. Add coverage for
materializing bytecode cache data from an ImmutableBytes mapped file.
2026-05-16 08:13:35 +02:00
Aliaksandr Kalenik
429b7fc809 LibWeb: Rebase pending async scrolls over main-thread state
Async scrolling kept only the compositor-visible absolute scroll offset
for pending scrolls. If script changed the same scrolling box before
the main thread adopted the pending offset, adoption could write the
stale absolute compositor offset back to the DOM and lose the script
update.

Track the unadopted compositor delta alongside the absolute offset
used for compositor presentation. When fresh scroll state reaches the
compositor, and when the main thread adopts pending async scrolls,
apply that delta on top of the current main-thread offset instead of
assigning the old absolute value.

Adoption can run during the event-loop scroll steps, before the later
rendering-update layout pass has made paintables safe to query. Keep
element adoption on the stored DOM scroll offset and apply viewport
deltas through the navigable, so a dirty layout tree does not trip the
paintable freshness invariant.

The async scrolling text test covers the script-scroll race and also
dirties layout before adoption. The old paintable-box adoption path
crashed in that case.
2026-05-15 21:13:18 +02:00
Andreas Kling
171e3adf01 LibWeb: Replace the HTML tokenizer with Rust
Replace the C++ HTML tokenizer with a Rust implementation behind the
existing HTMLTokenizer API.

Keep the parser-facing integration points for streaming input,
insertion points, document.write(), EOF insertion, parser aborts,
speculative parser input, and last start tag tracking. The generated
FFI handle stays an implementation detail of HTMLTokenizer, so callers
keep a single tokenizer class.

Preserve duplicate attributes through FFI so C++ token normalization can
record the duplicate-attribute signal used by CSP nonce checks. Keep
bulk tag-name and attribute scans capped at the active insertion point
so streamed parser input is spliced at the right offset.

Use generated DAFSA tables for named character references and intern
common tag and attribute names to reduce FFI marshalling overhead. This
also fixes attribute name source positions, nested old insertion points,
and aborted fast-path handling.

TestHTMLTokenizer covers duplicate attributes and insertion points in
fast tag-name, attribute-name, and quoted-value scans. A CSP text test
covers duplicate nonce attributes on parser-created script elements.
The tokenizer dump fixtures still match, TestHTMLTokenizer passes, and
the full release test-web run passes with 6981 tests and 226 skipped.
2026-05-15 21:01:40 +02:00
Shannon Booth
d595369ae4 LibWeb: Let document.write() reenter parser from parser-blocking scripts
When resuming after an async wait for a pending parser-blocking script,
clear the parser pause flag before executing the script. The spec has
unblocked the tokenizer by this point, and document.write() calls from
the script must be able to synchronously process inserted markup up to
the insertion point.

This fixes ordering for document.write()'d inserted scripts during
external parser-blocking script execution.
2026-05-15 19:49:45 +02:00
Aliaksandr Kalenik
f743263871 LibWeb: Let internals.wheel await async scroll adoption
Async scrolling tests used requestAnimationFrame() as a proxy for the
compositor thread to return pending scroll updates to the main thread.
That waited for a rendering opportunity, so tests could observe stale
DOM scroll offsets when the compositor update had not been adopted yet.

Make internals.wheel() return a promise that resolves after a tracked
async scroll operation has been applied by Navigable. Tracking is opt-in
from the internals test API, so regular page wheel input and compositor
IPC keep the boolean async-scroll path without allocating operation IDs.
Tracked test scrolls are the only operations that record completions.

Update async scrolling and wheel propagation tests to await the wheel
promise directly instead of relying on animation frame timing in tests.
2026-05-15 19:10:27 +02:00
Aliaksandr Kalenik
d51611b36f LibWeb: Publish dirty canvas content before painting
Canvas frame publishing was tied to CanvasPaintable::paint(), so cached
paint commands could replay DrawExternalContent without updating the
ExternalContentSource first. That made dynamic canvas content depend on
whether the display list was re-recorded for the frame.

Move canvas presentation to the rendering update step after animation
frame callbacks and layout, immediately before navigables paint. The
canvas paintable now only records the external-content draw command,
which keeps display-list replay from skipping the resource update.

Add a ref test that draws red, lets the display list cache, then draws
green on a later animation frame. The final rendering must come from the
updated external content source while reusing the cached draw command.
2026-05-15 15:08:43 +02:00
Tim Ledbetter
c24e00d279 LibWeb: Use fast_is and fast_as for FormAssociatedTextControlElement 2026-05-15 13:45:42 +02:00
Luke Wilde
de35994fc2 LibJS+LibWeb: Use the unified Visitor for Variant-holding members 2026-05-15 08:51:17 +02:00
Andreas Kling
e3841a7392 LibJS: Compact Shape property table to a sorted flat array
Replace the lazy per-shape OrderedHashMap cache for non-dictionary
shapes with a GC-allocated descriptor array. Store descriptors in hash
order for lookup while keeping an enum index so callers can still walk
properties in insertion order.

Keep dictionary shapes on the mutable OrderedHashMap path, and migrate
callers that enumerated Shape::property_table() to the new insertion
order iterator. Cap descriptor arrays to their compact u16 index range
and keep larger dictionary shapes on the mutable table path across
prototype transitions and prototype clones.

Add coverage for setting the prototype of a dictionary object with more
than 65536 named properties.
2026-05-14 19:59:40 +02:00
Aliaksandr Kalenik
d353954993 LibWeb: Adopt async scroll offsets for nested scroll nodes
Nested scroll nodes were present in the async scroll tree, but the
compositor rejected any non-viewport wheel target and tracked only one
pending viewport offset. That prevented element scrollports from being
scrolled asynchronously and made compositor-side offsets impossible to
adopt after the main thread rebuilt scroll state.

Let async wheel commands target any scroll node selected by the tree.
Store every offset produced by a compositor scroll and reapply pending
offsets by stable ID across display-list and scroll-state updates. The
main thread now adopts viewport, element and pseudo-element offsets
before rendering-update observers run, including scroll event
bookkeeping for element scrollers.

Carry the wheel hit-test rejection reason through the enqueue path while
doing this, so main-thread and blocking-wheel regions remain explicit
rather than being collapsed into a missing target. Existing nested
async-scrolling text tests cover the successful nested scroll path.
2026-05-14 19:41:32 +02:00