Commit graph

209 commits

Author SHA1 Message Date
Tim Ledbetter
d625deaccf LibWeb: Invalidate style when form control validity changes 2026-06-08 19:28:37 +02:00
Tim Ledbetter
de0b733bed LibWeb: Implement suffering from bad input for input elements
Email field support is left unimplemented because we don't have a way
to convert email addresses to punycode.
2026-06-08 19:28:37 +02:00
Andreas Kling
9340d2d1a3 LibWeb: Make layout nodes refcounted
Move the layout tree from GC allocation to refcounted ownership so
removed layout and paint subtrees are destroyed synchronously instead
of waiting for the next GC sweep. This dramatically reduces GC memory
usage peaks after layout tree churn and makes it easier for memory use
to fall back after large document updates.

Update layout factories, tree traversal, SVG layout node creation,
paintable back-pointers, and pseudo-element layout links to use RefPtr
ownership.

Make display: contents follow the same shape as Blink and WebKit: the
element itself does not create a layout node, and its children are
flattened into the nearest layout parent. Wrap direct non-whitespace
text in an anonymous inline node when the boxless element contributes
inherited style to that text.

Use an internal inline wrapper for display: contents pseudo-elements
so generated content can still participate in layout, painting, hit
testing, and pseudo-element queries. Keep CSSOM reporting the computed
display value from the pseudo style, not the internal wrapper.

Remove the retained out-of-tree layout node list and its testing hook,
since the flattened model does not need a side owner for boxless
elements. Add coverage for inherited text style, dynamic insertion
order, pseudo-element hit testing, and computed style queries.
2026-06-07 20:52:49 +02:00
Andreas Kling
7c06c3fd14 LibWeb: Make computed style data refcounted
Move ComputedProperties and CascadedProperties out of the GC. They no
longer contain strong references to GC-managed data.

Keep computed styles alive from DOM elements and animation updates with
RefPtr. Pass style into layout constructors by reference, since layout
only copies the values it needs while building nodes.

Use GC::Weak for cascade source links, so entries no longer keep the
style declaration or shadow root alive.
2026-06-06 23:29:48 +02:00
Zaggy1024
0ce19a19ea LibWeb: Leave input elements' text node contents unchanged while typing
Replacing the text node's contents with the normalized value after each
keystroke made it impossible to type some inputs. For example, `1e`
would cause the text node to be emptied, making it impossible to type
`1e2`. Also, `time`, `date`, and other time-related input types had no
intermediate valid values, so it was genuinely impossible to type in
them.

Additionally, typed numbers weren't being parsed as floats before
normalization, so even just typing `1.` would clear the text node, so
it was impossible to type a fractional number.
2026-06-05 12:49:24 +02:00
Zaggy1024
e6664213ac LibWeb: Fall back to TextInputBox for unsupported input types
This isn't strictly correct as it stands currently, since the size
attribute isn't supposed to affect type="time" and others, but those
types currently end up with zero width instead.

Size could probably be applied through shadow DOM style, and the input
layout box would simply allow content sizing.
2026-06-05 12:49:24 +02:00
Callum Law
f28e7120ea LibWeb: Ensure that shadow roots have hosts before appending children
This change gives each shadow root its host before appending its
children, and asserts that a root has no children when it's assigned to
a host. This ensures the children inherit the correct connectedness.

Otherwise, without this change, the user-agent shadow trees for color
and file inputs append their children before the shadow root is given
a host which, if the input element has already been inserted, means the
children stay marked disconnected despite being present in the rendered
tree. Disconnected nodes then skip layout invalidations they should
trigger.

Fixes a crash when submitting a prompt on https://chatgpt.com
2026-06-05 18:08:21 +09:00
Andreas Kling
164ed80244 Meta: Enable exit-time destructor warnings for libraries
Enable -Wexit-time-destructors for all in-tree library targets and
update process-lifetime library statics so they no longer register
exit-time destructors. Long-lived caches, lookup tables, singleton
registries, and generated constants now use NeverDestroyed or leaked
references where the data is intended to live until process exit.

Update LibWeb, LibLine, and the binding generators so regenerated
sources follow the same rule instead of reintroducing destructed
statics.
2026-06-04 19:20:49 +02:00
Zaggy1024
effb3fad3c LibWeb: Stop rounding to the nearest integer when dragging range inputs
set_value_as_number() already snaps the value to the nearest step, the
round and FIXME here were unnecessary.
2026-06-03 21:26:53 -05:00
Zaggy1024
10ba2ddbb7 LibWeb: Access range inputs' mouse events' clientX by casting
This is a bit more legible, and should be a bit more efficient than a
property lookup by name as well.
2026-06-03 21:26:53 -05:00
Tim Ledbetter
709c10f8ec LibWeb: Let range inputs stretch in grid containers
Previously, the UA stylesheet gave range inputs a definite
`width: 20ch`. This prevented range inputs from filling their grid
track. We now source the default width and height from a new
`RangeInputBox` type. This approach matches the implementation of other
input types.
2026-05-30 12:17:58 +01:00
Pavel Shliak
b542552f1e LibWeb: Map embedded content align to vertical-align 2026-05-26 09:35:16 +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
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
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
Shannon Booth
5adfd1c43a LibWeb/Bindings: Generate struct definitions from IDL dictionaries
Previously we were inconsistent by generating code for enum definitions
but not generating code for dictionaries. With future changes to the
IDL generator to expose helpers to convert to and from IDL values
this produced circular depdendencies. To solve this problem, also
generate the dictionary definitions in bindings headers.
2026-05-09 10:49:49 +02:00
Aliaksandr Kalenik
f8640d813a LibGfx+LibWeb: Make DecodedImageFrame a value type
DecodedImageFrame only wraps a ref-counted Bitmap and color-space
metadata. The frame object itself does not provide shared mutable
state or lifetime ownership beyond those members, so ref-counting it
adds an unnecessary layer of indirection.
2026-05-07 16:08:13 +02:00
Aliaksandr Kalenik
568b7ce7ea LibWeb: Make Paintable tree ref-counted
The Paintable tree and its supplemental painting data structures were
GC allocated because that was the easiest way to manage it and avoid
leaks introduced by ref cycles. This included the Paintable subclasses
themselves plus StackingContext, ChromeWidget, Scrollbar, ResizeHandle,
and scroll-frame state.

We are now trying to reduce GC allocation churn on layout and painting
updates, so keeping this short-lived rendering tree outside the JS heap
is a better fit. Move Paintable to RefCountedTreeNode, make painting
helpers ref-counted or weakly reference Paintables, and update the
layout and event-handler call sites to use RefPtr/WeakPtr ownership.
2026-05-07 15:03:44 +02:00
Aliaksandr Kalenik
76c79ee522 LibGfx: Remove ImmutableBitmap
DecodedImageFrame now owns decoded bitmap pixels directly, so the
separate ImmutableBitmap wrapper no longer carries useful semantics.
Remove the class and pass decoded image frames or bitmaps at the
boundaries where pixels are actually required.

The Skia image cache now keys off DecodedImageFrame, matching the
display-list commands that paint decoded images. Video frames stay
owned by LibMedia, with the explicit YUV-to-bitmap conversion living
at HTMLVideoElement's decoded-frame entry point for canvas and WebGL
callers.
2026-05-05 14:39:17 -05:00
Aliaksandr Kalenik
40f2abb7fe LibGfx+LibWeb: Add DecodedImageFrame
Decoded image data should not continue to traffic in ImmutableBitmap now
that the bitmap wrapper is being retired. Introduce DecodedImageFrame as
the paintable decoded-image unit and store a Bitmap plus ColorSpace in
it directly.

Thread the new frame type through decoded image data, display-list
image commands, filters, canvas drawImage, patterns, WebGL texture
upload, and CSS/SVG image consumers. ImmutableBitmap remains only at
the legacy boundaries that still need it, such as HTML video snapshots
and callers that explicitly ask for a bitmap snapshot.

This keeps color-space ownership with the decoded frame while making
the expensive or legacy ImmutableBitmap path explicit at the few call
sites that still need it.
2026-05-05 14:39:17 -05:00
Tim Ledbetter
d1fc4b4234 LibWeb: Route presentational hints through the CSS cascade
Previously, presentational hints bypassed the regular cascade pipeline
and wrote directly into `CascadedProperties` under
`CascadeOrigin::Author`. That meant `var()` substitution and the
invalid-at-computed-value-time fallback had to be duplicated in a
separate per-element pass, which in practice missed the IACVT step and
could leave a `GuaranteedInvalidStyleValue` in the cascaded
properties. This caused a crash in downstream code that assumed the
value had been resolved.

This introduces an `AuthorPresentationalHint` cascade origin and feeds
them through the cascade as normal declarations. This means that
`var()` resolution now happens in only one place.
2026-04-30 19:50:28 +01:00
Andreas Kling
83dfed14ad LibWeb: Move input open style invalidation into the helper
HTMLInputElement still mapped its picker open-state change directly to a
style invalidation reason. Move that mapping into
CSS::Invalidation::ElementStateInvalidator alongside the matching select
open-state helper.

This keeps another element-state invalidation decision out of the HTML
implementation without changing the invalidation behavior.
2026-04-29 15:47:23 +02:00
Andreas Kling
7c401b051b LibWeb: Move checked-state invalidation into a helper
HTMLInputElement had two call sites spelling out the same checked and
unchecked pseudo-class invalidation set. Move that selector policy into
FormControlInvalidator.

This keeps the input element responsible for detecting state changes,
while CSS::Invalidation owns the affected selector features.
2026-04-29 15:47:23 +02:00
Andreas Kling
5da72570b8 LibWeb: Harden UA event handlers on range and number inputs
These handlers crashed on several kinds of JS-dispatched input:
zero-width range (divide by zero in the slider mouse handler),
step="any" (MUST(step_up) throws InvalidStateError), plain Event
without clientX/deltaY/key (unchecked as_foo() asserts on
undefined), min > max (trips clamp()'s VERIFY), and input.type
changes leaving the range listeners attached to dereference empty
Optionals from the range-only min()/max() accessors.

Gate each handler on its expected type_state() and on
allowed_value_step() having a value, validate event property types
before converting, and bail out on zero-width rects or min > max.
Six crash tests cover the new paths.

Hit on a Cloudflare challenge page.
2026-04-24 07:58:34 +02:00
Shannon Booth
fd44da6829 LibWeb/Bindings: Emit one bindings header and cpp per IDL
Previously, the LibWeb bindings generator would output multiple per
interface files like Prototype/Constructor/Namespace/GlobalMixin
depending on the contents of that IDL file.

This complicates the build system as it means that it does not know
what files will be generated without knowledge of the contents of that
IDL file.

Instead, for each IDL file only generate a single Bindings/<IDLFile>.h
and Bindings/<IDLFile>.cpp.
2026-04-21 07:36:13 +02:00
Shannon Booth
482e5e770f LibWeb: Let flexbox stretch auto-width text inputs
Don't rewrite text input 'width: auto' to 'size()ch' in
'HTMLInputElement::adjust_computed_style()'. That turns the control into
a definite-width flex item and prevents 'align-items: stretch' from
expanding it across the flex container.

Fixes the layout of the input element on the element matrix login page.
2026-04-13 09:57:01 +02:00
Tim Ledbetter
6534a58b3c LibWeb: Maintain precision for large valueAsNumber time inputs 2026-04-11 18:28:56 +02:00
Tim Ledbetter
e2e401d0e0 LibJS+LibWeb: Avoid out of range time values in <input> value strings 2026-04-11 18:28:56 +02:00
Andreas Kling
34d954e2d7 LibRegex: Add ECMAScriptRegex and migrate callers
Add `ECMAScriptRegex`, LibRegex's C++ facade for ECMAScript regexes.

The facade owns compilation, execution, captures, named groups, and
error translation for the Rust backend, which lets callers stop
depending on the legacy parser and matcher types directly. Use it in the
remaining non-LibJS callers: URLPattern, HTML input pattern handling,
and the places in LibHTTP that only needed token validation.

Where a full regex engine was unnecessary, replace those call sites with
direct character checks. Also update focused LibURL, LibHTTP, and WPT
coverage for the migrated callers and corrected surrogate handling.
2026-03-27 17:32:19 +01:00
Zaggy1024
44ed698d4f LibWeb: Separate the active element and the element being activated
We were conflating elements being the active element and elements being
activated. The :active pseudo class is supposed to be based on whether
an element will have its activation behavior run upon a button being
released.

Store whether an element is being activated as a flag that is set/reset
by EventHandler.

Doing this allows label elements to visually activate their control
without doing a weird paintable hack, so the Labelable classes have
been yeeted.
2026-03-17 04:01:29 -05:00
Tim Ledbetter
a4f6ce3662 LibWeb: Use unsafe_layout_node() when handling alt attribute changes
The layout node is only accessed to clear the cached alt value, so the
layout tree doesn't need to be up to date in this case.
2026-03-17 09:07:10 +01:00
Jelle Raaijmakers
2e42421553 LibWeb: Invalidate paint cache for input/textarea on focus change
The invalidate_style() calls on text nodes in did_receive_focus() and
did_lose_focus() were no-ops since Node::invalidate_style() returns
early for character data nodes. Replace them with set_needs_repaint()
which properly invalidates the containing PaintableWithLines' paint
cache, ensuring selection highlights are cleared and the caret is
repainted when switching focus between text controls.

Fixes #8363
2026-03-11 16:44:19 +00:00
Aliaksandr Kalenik
8f7bb7dd2e LibWeb: Skip layout update for disconnected elements querying metrics
Introduce Document::update_layout_if_needed_for_node() which only calls
update_layout() when the node is connected. Use it at all call sites
that query layout metrics (offsets, client dimensions, image size, SVG
bounding box, etc.) so disconnected elements no longer trigger an
unnecessary layout.
2026-03-05 14:17:20 +01:00
Aliaksandr Kalenik
eae94a8a46 LibWeb: Route repaint requests through paintables, not Document
Rename Document::set_needs_display() to set_needs_repaint() and make it
private. External callers must now go through Node/Paintable which
route the request to the document internally.

Fix one existing misuse in AnimationEffect that was calling
document-level set_needs_display() instead of routing through the
target element's paintable.

This is preparation for per-paintable display list command caching:
repaint requests must go through specific paintables so their cached
command lists can be invalidated.
2026-03-04 19:35:45 +01:00
MichielN19
98f1813f5d LibWeb: Fix input field placeholder vertical alignment
Input elements with a placeholder were positioned lower than inputs
without a placeholder or inputs with text. This was caused by the
placeholder element missing height height and overflow properties that
the inner text element had.

This fix makes sure both the placeholder and inner text elements let
show the same position of the input field.
2026-03-02 13:24:20 +01:00
Andreas Kling
a146225331 LibWeb: Use unsafe layout/paintable accessors where appropriate
Add unsafe_layout_node(), unsafe_paintable(), and unsafe_paintable_box()
accessors that skip layout-staleness verification. These are for use in
contexts where accessing layout/paintable data is legitimate despite
layout not being up to date: tree construction, style recalculation,
painting, animation interpolation, DOM mutation, and invalidation
propagation.

Also add wrapper APIs on Node to centralize common patterns:
- set_needs_display() wraps if (unsafe_paintable()) ...set_needs_display
- set_needs_paint_only_properties_update() wraps similar
- set_needs_layout_update() wraps if (unsafe_layout_node()) ...

And add Document::layout_is_up_to_date() which checks whether layout
tree update flags are all clear.
2026-02-26 21:09:08 +01:00
Callum Law
b8f2989ccb LibWeb: Reduce recompilation from editing CascadedProperties.h
This reduces the recompilation of editing `Properties.json` from ~1429
to ~158
2026-02-19 11:27:06 +00:00
Praise-Garfield
36d8191a3d LibWeb: Chain all accept attribute checks in parse_accept_attribute()
The wildcard checks for audio/* and video/* are standalone if
statements, while the MIME-type and extension branches are
else-if chained only to the image/* check. When a token like
"audio/*" arrives, it matches the first if (adding
FileType::Audio) and then falls through to the MIME-type
else-if. MimeType::parse() accepts the wildcard because * is a
valid HTTP token code point, so a second MimeType{"audio/*"}
entry is added. FileFilter::add_filter() deduplicates within
variant types but cannot catch this cross-type duplication.

This chains all five conditions into a single if/else-if,
matching the spec's mutually exclusive "one of the following"
wording.
2026-02-13 15:32:36 -05: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
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
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
Psychpsyo
b8b0522cdc LibWeb: Apply base presentational hints across the board 2026-02-04 20:21:36 +01: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
Tim Ledbetter
73fcbb0666 LibWeb: Add a flag for UA internal shadow roots 2026-02-02 12:28:05 +00:00
Tim Ledbetter
b8bad97e76 LibWeb: Populate the data property for input events 2026-01-31 13:30:33 +01:00
Jelle Raaijmakers
e05503dbcb LibWeb: Send InputEvent with right .inputType on insert and delete
Applies to `<input>` and `<textarea>`. Editing commands in
`contenteditable` already sent the right events and input types.

Fixes #7668
2026-01-29 15:08:06 +01:00
Shannon Booth
354cca350a LibWeb/HTML: Invalidate :checked style on <input> type attribute change
The :checked (and :unchecked) psuedo classes depend on both the
checked state of input elements as well as what the type of that
input element is.
2026-01-27 09:45:40 +01:00
Jonathan Gamble
7385569a02 LibWeb: Selection toString focused text control delegation
Allows selected text in form controls to be copied to clipboard.
2026-01-02 18:40:05 +01:00
Jonathan Gamble
f6f4d7f497 LibWeb: Move <input> handle_return_key logic to HTMLInputElement 2025-12-29 19:59:42 +01:00