Commit graph

1973 commits

Author SHA1 Message Date
Andreas Kling
ca97f68cb7 LibWeb: Normalize decoded HTML string parsing
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.
2026-05-24 10:14:17 +02:00
Andreas Kling
289fe72aa0 LibWeb: Keep transferred ImageBitmap data stable
Keep decoded ImageBitmap transfer bytes in a stable heap object before
handing their pixel pointer to Gfx::Bitmap. GCC can evaluate the lambda
capture that moves the ByteBuffer before the data() argument. That can
leave the bitmap backed by moved-from storage.

Taking the pointer from heap-owned storage avoids that dependency. This
does not copy pixel data. The existing crash test covers the offscreen
canvas path.
2026-05-24 10:13:23 +02:00
Aliaksandr Kalenik
6c162d8b5d LibWeb+LibWebView+WebContent: Recover after Compositor process crashes
The browser previously treated the out-of-process Compositor as fatal.

Restart the shared Compositor from the browser process, reconnect
process-backed WebContent clients, recreate compositor contexts, restore
viewport state, and ask WebContent to repaint and republish canvas and
media resources. WebContent now marks its compositor connection lost,
returns conservative values for synchronous compositor queries while
reconnecting, and drops outgoing updates until the replacement transport
arrives.

Synchronous input queries through the compositor control connection now
use fallible IPC. If the Compositor exits after the open check or before
the sync reply arrives, scroll and mouse handling report that the
Compositor did not handle the event and let the normal WebContent
fallback run.

Mouse events queued while the Compositor is unavailable now fall back to
direct WebContent dispatch. This keeps input completion in step with the
pending-event queue.

Recovery is capped at three automatic restarts. If the restart limit is
exceeded, if restart, reconnect, or context recreation fails, or if the
replacement Compositor exits during active recovery, the browser crashes
instead of switching process-backed views to a fallback path.
2026-05-24 03:35:07 +01:00
Aliaksandr Kalenik
579de06b78 LibWeb: Rename m_rendering_thread_display_list_* to m_compositor_*
"Rendering thread" is the old name for what is now called the
compositor. Rename these Navigable members to reflect the current
terminology:
2026-05-23 18:13:29 +01:00
Andreas Kling
4c03a6f5fc LibWeb: Honor transparent copy compositing in canvas
Do not skip fully transparent canvas fill and stroke styles when the
current compositing operator can still affect the destination bitmap.
TradingView uses transparent copy fills while repainting its chart
canvases, and skipping those draws left old translucent chart pixels in
place so later source-over draws accumulated on top.

Add text coverage for transparent copy replacing an existing translucent
pixel before another translucent draw.
2026-05-23 19:11:01 +02:00
Shannon Booth
637fd51595 LibWeb: Unify WebIDL C++ type generation
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.
2026-05-23 18:26:12 +02:00
Martin Chrástek
cd3c72dfda LibWeb: Implement chardetng-based encoding detection for HTML parsing 2026-05-23 11:57:33 +02:00
Andreas Kling
56da8f01d7 LibWeb: Reject stale image decode promises
When an image source changes before a queued decode() job can attach
fetch callbacks, the current request can still be unavailable and have
no shared resource request. Treat that as the spec's current request
changed case instead of asserting while adding callbacks.

Add text coverage for changing an image source immediately after
calling decode(), matching the WPT image-decode-path-changes crash.
2026-05-23 11:36:45 +02:00
Andreas Kling
15714bade3 LibWeb: Avoid running scripts adopted during fetch
Follow the script execution model by checking the preparation-time
document before waiting for scripts to run in the node document. An
async script can be adopted into a freshly-created document while its
fetch is still pending, and that script must return without executing
when the fetch completes.

Also unblock render-blocking elements when removal disconnects them
from their browsing context, matching the render-blocking mechanism.
Add a crash test for an adopted async script whose fetch completes
after adoption.
2026-05-23 11:36:45 +02:00
Andreas Kling
7786b29882 LibWeb: Avoid unwrapping invalid computed-style pseudos
Leave the resolved object null when parsing the pseudo-element argument
fails, as required by CSSOM. The view-transition update hook ran
after that step and still unwrapped the parse result, crashing on
unsupported pseudos such as ::scroll-marker-group.

Only run the view-transition hook once parsing succeeds. Add a crash
test covering unsupported scroll pseudo-elements passed to
getComputedStyle().
2026-05-23 11:36:45 +02:00
Zaggy1024
a59804c9d4 LibWeb: Ensure that media fetches only begin after document is active
This ensures that we're only beginning a remote fetch when the document
is active, which the observer callbacks already assume. Combined with
the next commit, this will help ensure that the fix preventing the
VERIFY in the document_became_active callback from being hit works.
2026-05-23 09:14:13 +02:00
Aliaksandr Kalenik
4742a02975 LibWeb+WebContent: Split compositor context id allocation from creation
Once the compositor lives in another process, the helper has to know a
context's id before any per-context message about it can be dispatched.
Today the id is minted inside CompositorHost::create_context and
returned to the caller, so it cannot be named ahead of time.

Untangle allocation from creation so Browser can mint the id and hand it
down through the call chain into both the local host and the future
remote host with no special case. The id helpers also move into a public
header so LibWeb, WebContent, and the upcoming service share one
encoding for the page-presenting bit. Behavior is preserved; the
in-process compositor still owns rendering.
2026-05-22 19:50:42 +01:00
Shannon Booth
2ae54d77e0 LibWeb: Reuse initial about:blank window for first same-origin load
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.
2026-05-22 18:17:58 +02:00
Andreas Kling
56e1f1ca22 LibWeb: Avoid relayout for definite-size image updates
When image data becomes available, intrinsic dimensions can change, but
that does not require relayout for image elements whose computed width,
height, and min/max constraints are independent of intrinsic sizing. In
that case, invalidate paint and intrinsic-size caches instead of marking
layout dirty.

Keep the conservative relayout path for auto, percentage,
calc-percentage, and intrinsic sizing constraints, since decoded image
dimensions can affect used size in indefinite contexts. Query image
availability while painting so an existing paintable can switch from alt
text to image content without relayout.

Add text coverage that waits for image load events and checks auto,
percentage, calc-percentage, intrinsic keyword, min/max percentage, and
fixed-size cases without relying on timeouts.
2026-05-22 15:09:29 +02:00
Andreas Kling
75375e8cef LibWeb: Update hover after async scrolling stops
Remember the last mouse or wheel position seen by the event handler.
Schedule a hover refresh once async scrolling goes idle.
This lets hover state and boundary events follow content under a
stationary pointer after scrolling has stopped.

Add a text test that keeps hover on the old target while scrolling is
active. It then checks that hover moves after the idle update without
extra mousemove or pointermove events.
2026-05-22 14:33:39 +02:00
sideshowbarker
c1f38f92fe LibWeb: Keep repaints pending inside visibility:hidden iframes
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
2026-05-22 09:58:10 +01:00
Andreas Kling
55aad9ee38 LibWeb: Install fresh JS bytecode cache blobs locally
After generating a bytecode cache blob, map it as ImmutableBytes and ask
the owning JS record to install it. This lets a cold-cache load move to
mapped cache backing without waiting for a later page load.
2026-05-22 10:54:44 +02:00
Andreas Kling
43b8a8b099 LibWeb: Thread request context into ContentBlocker
Carry the initiating URL, fetch destination, initiator type, and request
mode from Fetch into LoadRequest and pass them to ContentBlocker. The
existing substring matcher still matches only the request URL, but the
blocker API now receives the context needed by source-aware backends.

Preserve that metadata for CORS preflights and connection hints, and add
coverage for resource-type mapping and blob source URL normalization.
2026-05-21 21:16:56 +02:00
Callum Law
199e82fc73 LibWeb: Forward non-synthetic pseudo-elt accesses to relevant element
This adds a new class `ElementReferencePseudoElement` which forwards
any accesses to the referenced element for "element-reference" pseudo
elements.

This allows us to, for instance:
 - Access the underlying `ComputedProperties` in getComputedStyle, which
   includes inline style.
 - Store and access `CustomPropertyData`
 - Access the layout node for "resolved value" computation
 - Apply animations from `update_animated_style_if_needed`

We register these with the originating element when calling
`set_associated_shadow_host_pseudo_element`, this requires us to append
the element to the tree beforehand since we need to be able to get the
shadow host.
2026-05-21 14:26:22 +01:00
Callum Law
977c054e77 LibWeb: Rename use_pseudo_element
`associated_shadow_host_pseudo_element` is clearer on what this is.
2026-05-21 14:26:22 +01:00
Aliaksandr Kalenik
6b912038d3 LibWeb+WebContent: Route compositor through in-process IPC
LibWeb still exposed the concrete CompositorThread to Page,
Navigable, and EventHandler, so compositor IPC would have leaked the
thread implementation into callers. The old thread APIs also bundled
page presentation callbacks and main-thread wakeups into the same
object, which made it awkward for WebContent to put an actor boundary
in between.

Introduce CompositorHost and context handles as the caller-facing API,
and move shared compositor protocol values out of CompositorThread. Add
WebContentCompositor IPC endpoints and route PageHost through a paired
in-process transport. The actor owns CompositorThread with explicit
main-thread and UI presentation clients, while screenshot completion is
serialized on the WebContent event loop using request IDs.

The intention for introducing IPC here is to prepare for moving the
compositor thread into a separate process.
2026-05-21 11:45:06 +01:00
Andreas Kling
30aae77901 LibWeb: Delegate focus from shadow hosts
Handle the delegatesFocus branch of get-the-focusable-area before
rejecting non-focusable focus targets. This lets host.focus() move focus
to the first focusable delegate in the shadow tree, or preserve an
already-focused descendant.

Treat delegatesFocus shadow hosts as focus delegates even when tabindex
would otherwise make the host focusable. Skip inert delegate candidates,
and reject inert shadow hosts before looking for a delegate. Check focus
inertness through shadow-host ancestry so direct focus cannot enter
inert shadow subtrees.

Rebaseline the disabled delegatesFocus WPT now that this behavior
passes. Cover delegated focus, hidden and inert delegate candidates,
tabindex hosts, inert hosts and direct delegates inside inert hosts, and
hosts without any focusable delegate.
2026-05-21 08:56:05 +02:00
Andreas Kling
94302775bf LibWeb: Map document element focus to the viewport
Apply the focusing steps' get-the-focusable-area mapping before
rejecting a non-focusable target. This preserves documentElement.focus()
by mapping the non-focusable document element to the Document viewport.

Also map rendered navigable containers with content navigables to their
active document, while leaving hidden containers unfocused. Preserve
Window focus events for child document viewports reached through iframe
focus, while still suppressing the top-level viewport surrogate events.

Treat rendered object elements as focusable through their default
non-null tabindex, even when they show fallback or image content instead
of a child navigable.

Keep the spec focus-chain common-tail handling intact for viewport
focus. The Document object is only our surrogate for the viewport, so
designate viewport focus from the new focus target without dispatching
Window focus/focusin events for that top-level surrogate.

Pass that viewport surrogate as the fallback target for fragment
scrolling and NavigateEvent focus reset, so unfocusable body or fragment
targets still clear stale element focus.

Cover documentElement.focus() in both the activeElement and focus-chain
tests, including a tabindex document element that remains focused as an
element. Cover object focus with and without a child navigable, hidden
object focus attempts, iframe focus events, hidden iframe focus, and
blurring a focused iframe after it becomes hidden. Also cover viewport
fallback for intercepted navigation focus reset and fragment scrolling
to an unfocusable target.
2026-05-21 08:56:05 +02:00
Andreas Kling
99b1780d57 LibWeb: Reject non-rendered elements as focus targets
Do not let elements inside display:none subtrees become focus targets.
The HTML focusable-area model only allows elements to be focusable when
they are rendered, delegate rendering to their children, or are relevant
canvas fallback content.

Preserve blur for the current focused area after script hides it, since
the unfocusing steps operate on the old focus target. Check display:none
through the flat-tree style parent chain, so slotted controls inside
hidden slot subtrees cannot become focused.

Cover hidden ancestors with materialized computed style, display:none
controls, display:contents, hidden focused controls, and slotted cases
inside hidden and visible shadow-tree subtrees.
2026-05-21 08:56:05 +02:00
Tim Ledbetter
11379e7c67 LibWeb: Clear selection when no find in page matches are found
Previously, if the find in page query was updated and no matches were
found we would keep the old selection instead of clearing it.

`window.find` behaves differently from the find in page UI and
preserves the old behavior.
2026-05-20 21:32:00 +02:00
Timothy Flynn
f0d7e28f55 LibWeb+LibWebView+UI: Move SelectedFile factory to LibWebView
This factory is only used by the UI. An upcoming commit will make it
depend on LibFileSystem. LibWeb currently does not link LibFileSystem,
and doing so would push LibWeb in the wrong direction (we should be
doing less file IO in LibWeb, not more).
2026-05-20 21:09:22 +02:00
Shannon Booth
de6aec04e8 LibGC: Default-construct ConservativeVector from the global heap 2026-05-20 20:37:55 +02:00
Shannon Booth
387cd6e2e2 LibGC: Default-construct RootVector from the global heap
Similar to GC::Root<T>, make GC::RootVector<T> constructible without
explicitly passing a Heap.

This is implemented by having RootVectorBase use GC::Heap::the() for
heap-free construction.
2026-05-20 20:37:55 +02:00
Andreas Kling
8eb74bf747 LibWeb+LibWebView: Preserve crashed page URLs on crash
Load the browser-generated crash page as a synthetic response for the
URL that was active when WebContent exited. This keeps the session
history entry, response URL, and created Document aligned with the same
navigation URL, so reload targets the original page without creating a
local document for an HTTP(S) history entry.

Suppress history metadata updates from the generated page and declare
an inert rel=icon. Fallback favicon loading now follows the HTML
condition that no link with the icon keyword exists, which avoids the
credentialed /favicon.ico request from the crashed origin.
2026-05-20 20:17:45 +02:00
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