Commit Graph

1817 Commits

Author SHA1 Message Date
Aliaksandr Kalenik
4f54b16315 LibWeb: Preserve non-ASCII characters in canvas text preparation
The whitespace-normalization loop in prepare_text() called
StringBuilder::append() on each code point, which resolves to the
`char` overload and truncates non-ASCII characters. measureText("ó")
therefore returned a width of 0, despite fillText painting the glyph.

Use append_code_point() instead, and add a regression test for both
precomposed and decomposed accented text.
2026-04-25 14:54:18 +02:00
Andreas Kling
792a8c3a9c LibWeb: Accept image/avif as a supported image MIME type
The list previously omitted AVIF even though we ship a working
AVIFImageDecoderPlugin, which meant <picture><source type="image/avif">
candidates and image-set(... type("image/avif")) candidates were
unconditionally skipped.
2026-04-25 14:54:10 +02:00
Andreas Kling
30f37d691c LibWeb: Share supported image MIME type list
Extract the file-local is_supported_image_type() helper from
HTMLImageElement into a small standalone translation unit so other
parts of the engine can ask the same question. The next commit reuses
it for the image-set() type() filter.

The list is still hard-coded; deriving it from the registered image
decoders remains a FIXME.
2026-04-25 14:54:10 +02:00
Shannon Booth
cc6e048bd6 LibWeb+LibIDL: Remove support for #import directives during parsing
These no longer serve any purpose now that we run the IDLGenerator
on all of these files at once.
2026-04-24 20:08:29 +02:00
Aliaksandr Kalenik
1193409f64 LibWeb: Wait for CompletelyAvailable state before resolving img.decode()
HTMLImageElement's update-the-image-data step 16 queues its state
transition and load event dispatch via a 1 ms BatchingDispatcher, so
the current request does not become CompletelyAvailable synchronously
when the fetch finishes. decode()'s on_finish callback, however, was
queuing its resolve task directly on the event loop, bypassing the
batch. That race meant decode() could resolve while the image request
was still in Unavailable state, so any .then() handler inspecting
img.width / img.height (or anything derived from the bitmap) would see
zeros.

Google Maps hits this on its .9.png road shield icons: after awaiting
img.decode() it reads a.width / a.height and calls
ctx.getImageData(0, 0, 0, 0), which throws IndexSizeError and aborts
the tile rendering pipeline.

Route decode()'s on_finish through the same BatchingDispatcher so both
are processed in the same batch, with the decode resolution queued
after step 16's element task.
2026-04-24 19:27:26 +02:00
Andreas Kling
9a6f5f8640 LibWeb: Avoid realm lookup when rejected promises list is empty
notify_about_rejected_promises() is called for every related environment
settings object at the end of every microtask checkpoint. It was
unconditionally reading the realm up front, which showed up at 3.0% self
time in a YouTube playback profile.

This patch moves the realm lookup into the queued task callback, which
happens way less often.
2026-04-24 18:58:48 +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
Andreas Kling
3cf24872c4 LibWeb: Fix crash removing link stylesheet nested in a shadow tree
HTMLLinkElement::removed_from() used `old_root` to find the
StyleSheetList to remove the link's stylesheet from. That's wrong
when the link element lives inside a shadow tree that is itself
nested within a larger removed subtree: Node::remove() hands every
shadow-including descendant the outer subtree's root as `old_root`,
not the descendant's own containing root. So we'd look in the
document's list while the sheet was actually in the shadow root's
list, failing the did_remove VERIFY in StyleSheetList::remove_sheet.

Fix by using the sheet's own owning-root tracking. A link-owned sheet
always has exactly one owning document or shadow root (only constructed
stylesheets can be adopted, and link sheets are never constructed), so
we can just read that entry.

Also make owning_documents_or_shadow_roots() return by const reference
instead of copying the HashTable on every call, which benefits existing
iterating callers too.

Fixes a crash on https://nytimes.com/.
2026-04-23 22:37:06 +02:00
Shannon Booth
5a97dba495 LibWeb: Model Function as a callback type
Import WebIDL/Function.idl where TimerHandler uses Function, and let the
bindings generator handle it through the normal callback-function path.

This removes the special C++ mapping for Function and makes TimerHandler
use GC::Root<CallbackType>, matching the generated binding type when IDL
files are parsed together.
2026-04-23 07:07:49 +02:00
Pavel Shliak
0e98fdccd5 LibWeb/HTML: Fix ruby parse error check for rp/rt 2026-04-22 15:30:41 +01:00
Tim Ledbetter
da5e002db1 LibWeb: Keep select button text in sync with the selected option
Previously, the select button's text was only refreshed inside the
two non-trivial branches of the selectedness setting algorithm.
Paths that left the select with exactly one selected option hit a
no-op branch and skipped the refresh.

Fix this by implementing the "clone selected option into select
button" algorithm and invoking it whenever the set of selected options
may have changed.
2026-04-22 09:15:29 -04:00
Sam Atkins
f434ddc01f LibWeb/HTML: Implement HTMLOptionElement moving steps 2026-04-22 14:05:49 +01:00
Sam Atkins
6d02296eb5 LibWeb: Pass better information to node moving/removing steps
Corresponds to:
73de9e5e1b
097be9feaa
2026-04-22 14:05:49 +01:00
Jelle Raaijmakers
a5e1c33743 LibWeb: Parse srcdoc documents synchronously during activation
Bypass the async body-reading pipeline for about:srcdoc iframes whose
body bytes are already in memory. Set up a deferred parser at document
load time and run the post-activation update synchronously, so the body
element exists before parent script can observe the new document via
contentDocument. This matches Chrome and Firefox behavior for srcdoc
iframes and fixes the flaky test
`set-innerHTML-inside-iframe-srcdoc-document.html` that relied on body
being non-null.

Co-authored-by: Tim Ledbetter <tim.ledbetter@ladybird.org>
2026-04-22 13:27:45 +01:00
Shannon Booth
25254d5a20 LibWeb/Bindings: Move parsed IDL entities into Context
Start making IDL::Context represent the shared IDL world used during
code generation.

Move globally visible parsed IDL such as dictionaries, enums,
typedefs, callbacks, mixins, and partial declarations out of individual
Interface objects and into Context.

The main goal of this change is a step towards invoking the IDL
generator on every IDL file at once, rather than per interface.

In the meantime as standalone improvements, this lets code generation
resolve imported IDL types through the shared Context without copying
imported declarations onto each Interface. It also makes duplicate
local declarations unnecessary for imported shared types, since an
interface can reference an enum or dictionary owned by another
parsed IDL module without re-emitting it itself.
2026-04-22 13:26:01 +02:00
Zaggy1024
04cc5bced9 LibWeb: Update video elements' natural dimensions during playback
This tightens the implementation of video element sizing to the spec by
implementing two spec concepts:
- The media resource's natural width and height, and
- The video element's natural width and height.
The element's natural dimensions change based on the representation,
which has many inputs, so update checks are triggered from many
locations.

The resize event is fired when the media resource's natural dimensions
change, and the layout is invalidated if the element's natural
dimensions change.

Tests for a few important resize triggers have been added.
2026-04-21 19:11:24 -05:00
Zaggy1024
938c254d6f LibWeb: Remove VideoTrack's list reference when it is removed from it 2026-04-21 19:11:24 -05:00
Zaggy1024
2420e87be9 LibWeb: Simplify video element's first poster representation condition
The HAVE_METADATA check was redundant.
2026-04-21 19:11:24 -05:00
Zaggy1024
f3d3c1f421 LibWeb: Don't clear video posters before the fetch and decode complete
Also, make all the callbacks capture the element weakly. No reason to
keep it alive here.
2026-04-21 19:11:24 -05:00
Zaggy1024
08faa83340 LibMedia+LibWeb: Add an initial Starting state to PlaybackManager
This state will indicate to the media element that it's not guaranteed
to have a frame yet, for the purposes of determining the ready state.
JavaScript should be sure that video elements with a ready state of
HAVE_CURRENT_DATA or greater represent the current video frame already.

To allow the state to be exited if audio is disabled, audio tracks are
now only added to the buffering set on enable if the audio sink exists,
since without the sink starting the data provider, it will never be
removed.

This is a step towards making video ref tests.
2026-04-21 19:11:24 -05:00
Zaggy1024
e1e752cc28 LibMedia+LibWeb: Indicate playback states' available data with an enum
This allows us to differentiate between having no data available yet,
having current data, and having future data. The main purpose of this
is to allow a new starting state to explicitly force HAVE_METADATA
instead of >= HAVE_CURRENT_DATA.

Note that the SeekingStateHandler returns Current instead of None. This
is deliberate, since the buffered ranges from the demuxer(s) can be
used to inform whether the possibly-current data is actually available
at the seek target.
2026-04-21 19:11:24 -05:00
Zaggy1024
9494f4e8c5 LibWeb: Relayout video elements when setting the initial size
A while ago, we removed the relayout upon rendering a new frame. In
doing so, it became possible for the layout to remain stale after the
video metadata had loaded, leaving the video drawn in a 0x0 box.
2026-04-21 19:11:24 -05:00
Zaggy1024
29d9667511 LibWeb: Always close remote media resource streams on a request error
Otherwise, the PlaybackManager may get stuck waiting for enough data to
read the metadata and call on_metadata_parsed.

This is unfortunately difficult to test without direct control over the
fetching process, but it could cause flakes in tests that wait for
loadeddata.
2026-04-21 19:11:24 -05:00
Tim Ledbetter
e5d615cb11 LibWeb: Implement autofocus candidate processing
This change implements the algorithms necessary to focus elements with
the autofocus attribute on page load.
2026-04-21 23:47:05 +02:00
Jonathan Gamble
baefb51902 LibWeb: Add Media Capture and Stream APIs 2026-04-21 16:40:46 -05:00
Jelle Raaijmakers
6171cb7bbf LibWeb: Override HTMLFormElement::is_supported_property_name()
By implementing this method ourselves, we no longer go through
::supported_property_names() and skip both the vector allocation and
sorting, which we don't need to determine if a property name is present.
2026-04-21 14:02:54 +01:00
Jelle Raaijmakers
e63af74dda LibWeb: Use tree order in HTMLFormElement::supported_property_names()
Calling into ::compare_document_position() for each node comparison
inside quick_sort() is quite expensive - it calculates more than we need
and allocates. Replace it with TreeNode::is_before() which does not, and
gives us the required positional info.
2026-04-21 14:02:54 +01:00
Jelle Raaijmakers
bf414f5d8f LibWeb: Simplify result in HTMLFormElement::supported_property_names()
We were doing the exact same thing as HashTable::values(). No functional
changes.
2026-04-21 14:02:54 +01: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
706011bd9b LibWeb: Respect image response MIME type over .svg URL suffix
SharedResourceRequest was treating any URL ending in .svg as SVG, even
when the response Content-Type was some other format (like image/webp).
This could result in transformed CDN image URLs to fail decoding.

Only use the .svg URL suffix fallback when no MIME type was provided.
2026-04-19 15:57:47 +02:00
Jonathan Gamble
1c5907d87f LibWeb: Correct initiator origin logic for new top level traversables 2026-04-19 13:11:48 +02:00
Pavel Shliak
94b29821a1 LibWeb/HTML: Remove duplicate area tag in XMLSerializer 2026-04-19 10:38:32 +02:00
Andreas Kling
354a20217c LibWeb: Handle null active document in destroy_the_child_navigable
When an ancestor document is unloaded, its child documents are unloaded
(and destroyed) first, which leaves their navigable's active document
null. If the ancestor's pagehide handler then removes a subtree
containing one of those iframe containers, destroy_the_child_navigable
crashed dereferencing the null active document.

Treat the "destroy a document and its descendants" step as a no-op when
there is no document left to destroy, and still run the remaining
post-destruction cleanup.

This fixes a crash when closing a GMail tab.
2026-04-16 12:38:38 +02:00
Andreas Kling
e330d5b9ab LibWeb: Make Node::is_connected() O(1) via a cached flag
Previously this walked up the parent chain on every call, which shows
up as a 2.5% item in the profile while watching YouTube videos.

Cache an m_is_connected bit on Node instead, maintained by the DOM
insertion and removal steps.
2026-04-16 08:26:34 +02:00
Andreas Kling
8a9d5ee1a1 LibJS: Separate raw and capturing native functions
NativeFunction previously stored an AK::Function for every builtin,
even when the callable was just a plain C++ entry point. That mixed
together two different representations, made simple builtins carry
capture storage they did not need, and forced the GC to treat every
native function as if it might contain captured JS values.

Introduce RawNativeFunction for plain NativeFunctionPointer callees
and keep AK::Function-backed callables on a CapturingNativeFunction
subclass. Update the straightforward native registrations in LibJS
and LibWeb to use the raw representation, while leaving exported
Wasm functions on the capturing path because they still capture
state.

Wrap UniversalGlobalScope's byte-length strategy lambda in
Function<...> explicitly so it keeps selecting the capturing
NativeFunction::create overload.
2026-04-15 15:57:48 +02:00
Shannon Booth
8642801889 LibWeb: Set fragment scripting mode from the context document
This corresponds with the editorial change to the HTML standard
introducing the parsing mode enum of:

https://github.com/whatwg/html/commit/01c45cede

And a follow up normative change of:

https://github.com/whatwg/html/commit/508706c80

Making fragment parsing derive its scripting mode from the context
document.
2026-04-14 23:01:36 +02:00
Shannon Booth
290db9d690 LibWeb: Set iframe sandbox flags before child navigable creation
The initial about:blank document inherits sandbox flags when the
child navigable is created. Parse the iframe sandbox attribute first
so the initial child document gets the correct sandbox state.

Fixed in the HTML spec with:

https://github.com/whatwg/html/commit/3fd7f35
2026-04-14 23:01:36 +02:00
Shannon Booth
04211d5a51 LibWeb: Propogate sandbox flags when creating a new browsing context 2026-04-14 23:01:36 +02:00
Shannon Booth
de14978046 LibWeb: Implement cross process BroadcastChannel delivery
Route BroadcastChannel messages over IPC so matching channels can
receive them across WebContent and WebWorker processes, rather than only
within a single process.

Each channel now serializes its payload, sends it upward over IPC, and
receiving processes deliver it locally after matching by storage key and
channel name.
2026-04-14 18:43:28 +02:00
Andreas Kling
88d4d1b1a6 LibWeb: Use VM helpers for execution context access
Inline JS-to-JS frames no longer live in the raw execution context
vector, so LibWeb callers that need to inspect or pop contexts now go
through VM helpers instead of peeking into that storage directly.

This keeps the execution context bookkeeping encapsulated while
preserving existing microtask and realm-entry checks.
2026-04-13 18:29:43 +02:00
Andreas Kling
2ca7dfa649 LibJS: Move bytecode interpreter state to VM
The bytecode interpreter only needed the running execution context,
but still threaded a separate Interpreter object through both the C++
and asm entry points. Move that state and the bytecode execution
helpers onto VM instead, and teach the asm generator and slow paths to
use VM directly.
2026-04-13 18:29:43 +02:00
Andreas Kling
ff5273084d LibWeb: Serialize external content surface clears
Lock the shared Skia backend context before clearing an external
content back store.

Nested navigables render through PublishToExternalContent, and that
clear ran outside the locking used by normal display list playback.
This allowed multiple renderer threads to enter the same Ganesh
context concurrently and trip Skia's SingleOwner checks during
painting.
2026-04-13 12:26:14 +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
Shannon Booth
9db0ebe145 LibWeb: Order connectedMoveCallback before adoptedCallback
Corresponds to https://github.com/whatwg/html/commit/f831ea031b42
2026-04-12 18:13:09 +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
Sam Atkins
e1e73d485a LibWeb: Left-align the video progress bar
Prevents ancestors of the `<video>` element from moving the bar around.
For example, `<center><video></center>` would cause the progress bar to
start in the center and expand outwards.
2026-04-11 09:38:29 -05:00
Zaggy1024
b7c8537336 LibWeb: Invert the order of sink toggling when selecting video tracks
This ensures that when we're switching from one video track to another,
we don't end up exiting buffering/seeking early due to no tracks being
enabled.
2026-04-10 15:21:07 -05:00
Zaggy1024
bece3c360d LibWeb: Update the ready state after enabling tracks
Otherwise, the buffered ranges used won't include the tracks that are
supposed to be enabled.
2026-04-10 15:21:07 -05:00
Zaggy1024
ac70eb601f LibWeb: Throttle media elements' time marches on ready state updates 2026-04-10 15:21:07 -05:00