Commit Graph

1469 Commits

Author SHA1 Message Date
Praise-Garfield
4a5746db10 LibWeb: Correct body null check in navigation params fetch
Step 8 of "create navigation params by fetching" says "if
request's body is null, then set entry's document state's
resource to null." The condition is inverted: it checks
!body().has<Empty>(), entering the block when the body is
non-null instead of null. For GET navigations this is mostly
a no-op since resource is typically already Empty, but for
POST navigations the inverted check incorrectly clears the
POSTResource from the document state, breaking session history
entries that rely on it for form re-submission.
2026-02-13 15:26:54 -05:00
Praise-Garfield
ebdb9c34bd LibWeb: Check for NavigationParams in finalize_session_history_entry
Step 7.3 of finalize_session_history_entry checks whether
navigationParams "is a navigation params (i.e., neither null
nor a non-fetch scheme navigation params)." The condition
checks has<NonFetchSchemeNavigationParams>() instead of
has<NavigationParams>(), matching the wrong variant type.
The block body already accesses the variant as NavigationParams,
so if the condition ever matched it would VERIFY-crash. The
identical spec clause five lines above (step 7.2.3.1) is
implemented correctly as has<NavigationParams>().

The spec assertion "navigationParams's request is not null"
does not hold for srcdoc navigations, which create
NavigationParams with a null request. The condition guards
on request being non-null instead, with an NB comment
explaining the divergence.
2026-02-13 15:25:52 -05:00
Andreas Kling
97986f9739 LibWeb: Stream animated image frames on demand
Add AnimatedDecodedImageData which implements DecodedImageData with
an 8-slot buffer pool instead of storing all frames in memory.
Frames are requested on demand from the ImageDecoder service as
the animation progresses.

For a 344-frame animated image at 1920x1080, this reduces
WebContent memory from ~1.3 GB to ~66 MB.

The streaming class owns frame progression and synchronizes
multiple callers (HTMLImageElement and ImageStyleValue) through
notify_frame_advanced() returning the authoritative frame index.
When a frame isn't in the pool, the last displayed frame is shown
as a fallback (brief freeze rather than blank).

Rename the old AnimatedBitmapDecodedImageData (which now only
handles static/single-frame images) to BitmapDecodedImageData.
2026-02-13 18:34:24 +01:00
Niccolo Antonelli Dziri
bed56c676d LibWeb: Use enum instead of bool for CanUseCrossOriginIsolatedAPIs
Change the parameters types of the functions `coarsen_time` and
`coarsened_shared_current_time` from `bool` to
`CanUseCrossOriginIsolatedAPIs` for more coherence with the surrounding
code.
2026-02-13 16:47:42 +00:00
Niccolo Antonelli Dziri
bd76078f97 LibWeb: Add constructor for Notification and getter methods
The full constructor for NotificationsAPI::Notification is implemented
along with the getter methods.
It is now possible to call the elements of Notification in JS without
getting undefined but the default values (or the ones passed in
options).

The method `current_wall_time` is added in EnvironmentSettingsObject.

This passes a least a few more tests because of the getter methods
that are created.

https://wpt.live/notifications/constructor-basic.https.html

https://wpt.live/notifications/idlharness.https.any.html
2026-02-13 16:47:42 +00:00
Praise-Garfield
49d24f1867 LibWeb: Fix off-by-one in Navigation::can_go_forward()
The getter compares the current entry index against the entry
list's size, but valid indices are in the range [0, size - 1].
An index equal to size is a past-the-end state that never occurs
in practice, so the function always returns true for any valid
index. This means it reports forward navigation is possible even
when the current entry is the last one in the list, where
forward() immediately throws an InvalidStateError.

The symmetric can_go_back() correctly checks against index 0,
and forward() correctly checks against size - 1. This brings
can_go_forward() in line with both.
2026-02-13 09:38:36 -05:00
Chase Knowlden
b8f31179b2 LibWeb: Use dimension image source for images
Fixes tiny images on Wikipedia
2026-02-13 10:42:38 +00:00
Tim Ledbetter
db35fa5f6a LibWeb: Don't crash in Storage::broadcast() if document has no navigable 2026-02-12 15:33:13 +00:00
Sam Atkins
873680a504 LibWeb: Delay the load event until critical style subresources load
Previously, `<link rel=stylesheet>` would delay the load event until its
style sheet loaded, but not care about its subresources. `<style>`
would not delay the load event at all. Instead, each `@import` would
delay the load event.

Now, both `<style>` and `<link>` delay the load event until their style
sheet and its critical subresources have loaded or failed. This means
that CSSImportRules no longer need to delay the load event themselves,
because they do so implicitly as a critical subresource of their parent
style sheet.

This doesn't directly affect behavior, but means that any other critical
style resources we add will automatically delay the load event.

One wrinkle here is that the spec for the `<link>` element requires that
we wait for the style sheet's critical subresources *before* we create
a CSSStyleSheet, which means we don't yet know what those are.
https://html.spec.whatwg.org/multipage/semantics.html#fetching-and-processing-a-resource-from-a-link-element:critical-subresources
For now we simply ignore this, as we did before. That means we continue
to not delay the `<link>`'s load event.
2026-02-12 16:23:12 +01:00
Sam Atkins
44cbdc34fa LibWeb: Make StyleElementUtils into a base class, StyleElementBase
This will allow us to cast an Element to a StyleElementBase without
having to know whether it's an HTML or SVG style element.
2026-02-12 16:23:12 +01:00
Callum Law
8a82d116d6 LibWeb: Always parse <counter-style> as such
Previously we parsed it as `<custom-ident>` in `<counter>` and as a
keyword in `list-style-type`.

The practical effect of this is:
 - Spec defined counter style names in `<counter>` are ASCII lowercased
   on parse.
 - Non spec defined counter style names are allowed in `list-style-type.

We are still to parse the `symbols()` function but this gives us a
better base for that.
2026-02-12 10:33:09 +00:00
Tim Ledbetter
910a8c78ec LibWeb: Preserve event properties in label activation behavior
Previously, the label called `HTMLElement::click()` which dispatched a
synthetic event with all properties set to their default values. We now
preserve the properties of the original mouse event.
2026-02-12 10:06:39 +00:00
mikiubo
88ac590e9d LibWeb: Present canvas before snapshotting in drawImage()
When a WebGL canvas is used as a CanvasImageSource, the underlying
PaintingSurface may not yet reflect the most recent GL commands.
This caused drawImage() to capture stale or empty content unless
gl.flush() was called manually from JS.

Call HTMLCanvasElement::present() before creating the snapshot so
that WebGL content is properly synchronized with the surface prior
to readback.

Fix #7901
2026-02-12 00:28:36 +01:00
Aliaksandr Kalenik
30e4779acb AK+LibWeb: Reduce recompilation impact of DOM/Node.h
Remove includes from Node.h that are only needed for forward
declarations (AccessibilityTreeNode.h, XMLSerializer.h,
JsonObjectSerializer.h). Extract StyleInvalidationReason and
FragmentSerializationMode enums into standalone lightweight
headers so downstream headers (CSSStyleSheet.h, CSSStyleProperties.h,
HTMLParser.h) can include just the enum they need instead of all of
Node.h. Replace Node.h with forward declarations in headers that only
use Node by pointer/reference.

This breaks the circular dependency between Node.h and
AccessibilityTreeNode.h, reducing AccessibilityTreeNode.h's
recompilation footprint from ~1399 to ~25 files.
2026-02-11 20:02:28 +01:00
Aliaksandr Kalenik
901cc28272 LibWeb: Reduce recompilation impact of DOM/Document.h
Remove 11 heavy includes from Document.h that were only needed for
pointer/reference types (already forward-declared in Forward.h), and
extract the nested ViewportClient interface to a standalone header.

This reduces Document.h's recompilation cascade from ~1228 files to
~717 files (42% reduction). Headers like BrowsingContext.h that were
previously transitively included see even larger improvements (from
~1228 down to ~73 dependents).
2026-02-11 20:02:28 +01:00
Tim Ledbetter
7577fd2a57 LibWeb: Implement timer nesting level throttling
This clamps the interval of repeating timers to 4ms after they have run
5 times. This prevents CPU spinning for `setInterval()` calls with low
timeouts.
2026-02-11 16:32:20 +00:00
Tim Ledbetter
24055b60ef LibWeb: Add Timer::set_interval()
This allows us to modify the interval of an existing timer.
2026-02-11 16:32:20 +00:00
Praise-Garfield
1b01fae0af LibWeb: Fix textarea placeholder visibility on attribute change
HTMLInputElement calls update_placeholder_visibility() when its
placeholder attribute changes, but HTMLTextAreaElement did not. This
meant dynamically changing the attribute would not toggle the display
of the placeholder and inner text shadow DOM elements.
2026-02-11 16:11:11 +01:00
Praise-Garfield
ebd312689e LibWeb: Support :placeholder-shown pseudo-class for textarea elements
Previously only input elements were matched. Add placeholder_value()
to HTMLTextAreaElement mirroring the HTMLInputElement API and update
both selector matching code paths to handle textarea.
2026-02-11 16:11:11 +01:00
Jelle Raaijmakers
b07a576c22 LibWeb: Select contents of <input> when tabbing through fields
Browsers seem to make it convenient to replace an <input>'s contents by
selecting all text on focusing, but only if you used keyboard
navigation. Programmatic focus and clicking on the field do not show
this behavior.
2026-02-11 11:17:27 +01:00
Jelle Raaijmakers
2d4728d353 LibWeb: Keep cursor in view for text controls
When editing or changing the selection inside an <input> or <textarea>,
we should scroll the container so the cursor is always visible. Note
that currently the cursor might still become invisible at the end of the
container since we do not reserve enough space for it to be made
visible.
2026-02-11 11:04:53 +01:00
Jelle Raaijmakers
c72de688cc LibWeb: Make HTMLInputElement's contents scrollable
If the input's contents exceeded the dimensions of the inner text, it
would simply get clipped. This allows the user to scroll the input
horizontally.
2026-02-11 11:04:53 +01:00
Andreas Kling
3240cd536c LibWeb: Prevent navigation on destroyed navigables
When an iframe is removed before its post-connection session history
steps finish processing, the queued steps still run and call
navigate() on the now-destroyed navigable. This calls
set_delaying_load_events(true), creating a DocumentLoadEventDelayer
on the parent document. Since the navigable is destroyed, no
finalize step ever runs to clear the delayer, permanently blocking
the parent document's load event.

Fix this by checking has_been_destroyed() at the start of
begin_navigation() and bailing out early.
2026-02-10 21:19:35 +01:00
Andreas Kling
bd83591a1c LibWeb: Clear load event delayer when destroying child navigable
When a child navigable starts loading, the navigate algorithm calls
set_delaying_load_events(true), creating a DocumentLoadEventDelayer
on the parent document. This delayer is normally cleared when the
navigation finalizes via set_delaying_load_events(false).

However, when an iframe is removed from the DOM, the child navigable
is destroyed. If the finalize step hasn't run yet, the delayer
lingers until GC collects the Navigable, which can block the parent
document's load event indefinitely.

Fix this by explicitly clearing the "is delaying load events" flag
in destroy_the_child_navigable() right after marking the navigable
as destroyed.
2026-02-10 21:19:35 +01:00
Andreas Kling
bacd946721 LibWeb: Bail out of image callbacks when document becomes inactive
HTMLImageElement's "update the image data" algorithm checks
is_fully_active() at the start, but its async continuations
(microtasks, element tasks, batching dispatcher callbacks) skip
this check. When an iframe is removed or navigated, these
callbacks fire on an inactive document, causing crashes.

Fix this with two changes:

1) Add is_fully_active() bail-out checks at all async callback
   entry points in HTMLImageElement. Each bail-out also clears
   the DocumentLoadEventDelayer to prevent blocking the parent
   document's load event forever.

2) Create the DocumentObserver eagerly in initialize() (like
   HTMLMediaElement) with a document_became_inactive callback
   that clears the load event delayer and stops the animation
   timer. Fire document_became_inactive from Document::destroy()
   in addition to did_stop_being_active_document_in_navigable(),
   since iframe removal takes a different path than navigation.
   A guard flag prevents duplicate firing.
2026-02-10 21:19:35 +01:00
Andreas Kling
0145e425db LibWeb: Skip destroyed navigables in apply_the_history_step
When queuing tasks for changing navigables in step 12 of
apply_the_history_step, skip navigables that have been destroyed and
increment completed_change_jobs directly. This is necessary because
Document::destroy() removes tasks associated with its document from the
task queue, so a task queued for a destroyed navigable's window may
never run, causing the subsequent spin_until to wait forever.
2026-02-10 21:19:35 +01:00
Andreas Kling
9b987baf0e LibWeb: Bail out of the_end() spin_untils for inactive documents
When a document is navigated away from while HTMLParser::the_end() is
spinning the event loop (steps 7 and 8), the spin_until stays on the
call stack indefinitely, causing all subsequent event processing on the
same event loop to happen within nested spin_until pumping. Add
is_fully_active() checks to bail out early in this case.
2026-02-10 21:19:35 +01:00
Timothy Flynn
8d97389038 LibHTTP+Everywhere: Move the cookie implementation to LibHTTP
This will allow parsing cookies outside of LibWeb.

LibHTTP is basically becoming the home of HTTP WG specs.
2026-02-10 12:21:20 +01:00
Andreas Kling
4fa4ecf31b LibJS: Inline ExecutionContextRareData fields into ExecutionContext
After removing the unwind context stack, ExecutionContextRareData only
held two GC::Ptr fields — both trivially destructible. The indirection
cost more than it saved: a GC cell allocation per EC, an extra pointer
chase on every source range lookup, and unnecessary complexity.

Replace the rare data cell with two inline fields on ExecutionContext:
cached_source_range and context_owner.
2026-02-09 16:35:39 +01:00
Aliaksandr Kalenik
1f0f427a3c LibWeb: Remove Document.h include from XMLDocumentBuilder.h
...and SVGDecodedImageData.h

These headers only use Document via forward-declarable references and
smart pointers. Add explicit Document.h includes to .cpp files that
were relying on the transitive include.
2026-02-08 18:51:13 +01:00
Aliaksandr Kalenik
2452680615 LibWeb: Remove Document.h include from DOMParser.h, DOMImplementation.h
...and WorkerEnvironmentSettingsObject.h

These headers only use Document via forward-declarable references and
smart pointers, so the full include is unnecessary.
2026-02-08 18:51:13 +01:00
Aliaksandr Kalenik
9140348cbd LibWeb: Remove unused Document.h includes from SerializeBitmap.h
...and XMLFragmentParser.h

Neither header uses anything from Document.h directly.
2026-02-08 18:51:13 +01:00
Aliaksandr Kalenik
edf42ec9f9 LibWeb: Remove Document.h include from SVGElement.h
This reduces the recompilation cascade when Document.h is modified,
cutting off the transitive path through ~30 SVG element headers.

Move the inline try_resolve_url_to() template body in
SVGGraphicsElement.h to a non-template helper in the .cpp file to
avoid needing Document.h and ShadowRoot.h in the header.

Add explicit includes to files that relied on the transitive dependency.
2026-02-08 18:51:13 +01:00
Jelle Raaijmakers
2a2f8ef90b LibWeb+UI: Support triple clicking and dragging paragraphs
When triple clicking on text, we should select the entire paragraph, or
entire line in <input>s and <textarea>s. If the mouse button is held
down and the user starts dragging, the selection expands with additional
paragraphs or lines.

This expands on the work of Kai Wildberger (PR #7681) but was adjusted
for the work that happened previously to support double click + drag
moves and includes triple click support for our Qt UI.

Co-authored-by: Kai Wildberger <kiawildberger@gmail.com>
2026-02-06 14:18:10 +00:00
Sam Atkins
108ef5e088 LibWeb/HTML: Actually use charset encoding for linked style sheets
This code that used `charset` created a second `environment_encoding`
variable which shadowed the outer one, making it a no-op. Now we
actually use its value.
2026-02-06 15:04:44 +01:00
Andreas Kling
5b26777904 LibWeb: Don't WEB_SET_PROTOTYPE_FOR_INTERFACE for ShadowRealm global
We weren't doing this before either, but through a slightly sneaky
mechanism: we had overridden Cell::initialize() in
ShadowRealmGlobalScope as a no-op.

Instead of that, do the same thing Window and Worker globals do and
make all of the globals that inherit UniversalGlobalScopeMixin opt
out of WEB_SET_PROTOTYPE_FOR_INTERFACE in EventTarget::initialize().
2026-02-06 13:50:54 +01:00
Andreas Kling
706eb0018c LibGC+LibWeb: Mark two GC::Cell functions as MUST_UPCALL
Let's make sure that subclasses always call their base class when
overriding these virtuals:

- void finalize()
- void visit_edges(Visitor&)
2026-02-06 13:50:54 +01:00
Adam Colvin
2df5a7bb31 LibJS: Add source locations to console.trace()
LibJS+DevTools: Implement console.trace() with source locations

- Add Console::TraceFrame struct with source location data
- Implement Console::trace() to gather stack information
- Add WebView::StackFrame and ConsoleTrace for IPC
- Implement DevToolsConsoleClient::printer() for traces
- Update FrameActor to format traces for DevTools
- Update WorkerDebugConsoleClient trace handling
- Update ReplConsoleClient to format trace output
2026-02-06 11:58:07 +00:00
Psychpsyo
864018b3dc LibWeb: Don't lie about browsing context being top-level
The VERIFY() this was triggering wasn't actually to spec, and by the
time it gets encountered, the browsing context isn't technically a top-
level context yet, because it has just been created and the definition
of a top-level browsing context requires the document to be the
navigables active document, which it only becomes once a history entry
has been created for it.

Therefore we cannot just verify a top-level browsing context actually
being a top-level browsing context when inserting it into the group,
because that happens to early in its life-cycle as a top-level context.

This makes it so that JS console commands from the devtools no longer
get sent to the last created nested frame in the tab, because nested
frames no longer pretend to have a top-level browsing context.
2026-02-06 10:52:31 +00:00
Jelle Raaijmakers
c56c933014 LibWeb+WebContent: Instantly update DPI for painting and media queries
If our UI informed the page of a DPI change, we would store the new
device pixel ratio and leave it at that. It would take a layout/style
update (e.g. by clicking the page) to actually render the page using the
new DPI. This is very visible on macOS when moving the Ladybird window
from a 1x resolution monitor to a HiDPI 2x monitor.

We now instantly update the backing stores and mark media queries for
reevaluation. Moving the Ladybird window on macOS now immediately
updates the page when dragging it to a HiDPI monitor.
2026-02-06 09:01:26 +01:00
Tim Ledbetter
d41f77be64 LibWeb: Reset line-height for select elements 2026-02-05 12:34:57 +01:00
Psychpsyo
9eb2b8da8e LibWeb: Fix spec step numbering in comment 2026-02-05 11:54:46 +01:00
Sam Atkins
db3a8caa7f LibWeb/HTML: Walk flat tree to compute heading offsets 2026-02-05 11:21:08 +01:00
Sam Atkins
2994a7532d LibWeb: Make shadow_including_first_ancestor_of_type() use the flat tree
Every user of this actually wants an ancestor in the flat tree - taking
things like `<slot>` into account. So rename it and adjust its behavior
to use that.
2026-02-05 11:21:08 +01:00
Shannon Booth
1da77d2796 LibWeb/HTML: Simplify checking if navigation ID is no longer the same 2026-02-05 08:38:33 +01:00
Psychpsyo
ed2018f301 LibWeb: Add presentational hints for clear attribute on BR elements 2026-02-04 20:24:28 +01:00
Psychpsyo
b8b0522cdc LibWeb: Apply base presentational hints across the board 2026-02-04 20:21:36 +01:00
Callum Law
11d524bda4 LibWeb: Support CSS font-optical-sizing property 2026-02-03 11:44:25 +00:00
Jonathan Gamble
d3cdeb3ac5 LibWeb: Implement auto_content_box_size for textarea and input
This allows default and attribute-based sizing when an axis is auto,
without overriding extrinsic sizing.
2026-02-02 14:36:49 +00:00
Callum Law
b55023fad3 LibGfx+LibWeb: Resolve font features per font rather than per element
Previously we would resolve font features
(https://drafts.csswg.org/css-fonts-4/#feature-variation-precedence)
per element, while this works for the current subset of the font feature
resolution algorithm that we support, some as yet unimplemented parts
require us to know whether we are resolving against a CSS @font-face
rule, and if so which one (e.g. applying descriptors from the @font-face
rule, deciding which @font-feature-values rules to apply, etc).

To achieve this we store the data required to resolve font features in a
struct and pass that to `FontComputer` which resolves the font features
and stores them with the computed `Font`.

We no longer need to invalidate the font shaping cache when features
change since the features are defined per font (and therefore won't ever
change).
2026-02-02 14:11:43 +00:00