Commit graph

1739 commits

Author SHA1 Message Date
Shannon Booth
91e7218c22 LibWeb/HTML: Enforce CORS-mode fetch when fetching Worker script
At some point, the FIXME mentioned has been fixed.
2026-04-05 09:52:25 +02:00
Timothy Flynn
b11f30b32e LibWeb: Implement Navigator.getBattery more to spec & mark experimental
We should not throw exception types that are not dictated by the spec.
This is observable. This was preventing login on strava.com from
working.

Let's mark this feature as experimental as well, since it is just a stub
and was only added for a WPT score increase.
2026-04-04 17:54:18 +02:00
Aliaksandr Kalenik
54757e3586 LibWeb: Don't force replace history handling for iframe src changes
The spec's "not completely loaded" check in navigate_an_iframe_or_frame
was applied to all navigations, including attribute-driven src changes.
This caused navigations triggered before the previous page's load event
(e.g. via postMessage during parsing) to replace the history entry
instead of pushing a new one.

Restrict the check to initial insertion only. For subsequent src
attribute changes, always use "auto" so the navigate algorithm's own
logic (navigation_must_be_a_replace) decides the history handling.
2026-04-04 11:30:55 +02:00
Glenn Skrzypczak
e5dab9e1c7 LibWeb: Support WASM modules
This adds support for importing WASM modules in JavaScript and vice
versa.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
7392d2a2f4 LibWeb: Support JSON modules
This adds support for importing JSON objects from JSON files in
javascript.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
f1d3244b22 LibWeb: Support CSS modules
This adds support for importing CSS stylesheets from CSS files in
javascript.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
8053c2a0f1 LibWeb: Update fetch single module script steps
This updates the steps for fetching single module scripts and related
functions.
2026-04-03 21:21:09 +02:00
Aliaksandr Kalenik
610ffffe81 LibWeb: Replace ad-hoc target step recomputation with verification
Previously, we had to recompute targetStep in the middle of history
step application because our session history traversal queue (SHTQ)
implementation was broken and didn't provide actual task serialization.
This meant the step could change while we were waiting for tasks to
complete.

Now that the SHTQ correctly serializes tasks, the step should no longer
change mid-application. Replace the recomputation with a VERIFY() assert
to enforce this invariant.
2026-04-03 18:41:55 +02:00
Shannon Booth
379461e047 LibWeb: Make global prototype chains immutable
Per https://webidl.spec.whatwg.org/#interface-prototype-object any
global platform object should reject prototype changes (besides
from ShadowRealmGlobalScope), and interface prototype objects on
global prototype chains must be immutable.

We already handled parts of this on the globals themselves, but not
the full chain.

Also align some spec comments to the latest WebIDL spec.
2026-04-03 18:33:45 +02:00
Andreas Kling
51c7afdf5f LibWeb: Round offsetWidth and offsetHeight
Blink, WebKit, and Gecko round the border-box geometry that feeds
offsetWidth and offsetHeight instead of truncating it. Do the same
in HTMLElement so these CSSOM View APIs match interop behavior for
fractional sizes.

This also updates the two local text expectations that changed
because they observe the rounded values.
2026-04-03 14:29:44 +02:00
Aliaksandr Kalenik
e875f2b18b LibWeb: Make SessionHistoryEntry and DocumentState ref-counted
WebContent process keeps session history entries for pages we have
navigated away from. Before this change, those entries could prevent GC
objects (e.g. PolicyContainer and its CSP PolicyList) from being
collected, since the GC-allocated SHE/DocumentState held live GC::Ref
pointers into the heap.

By making both classes RefCounted and storing SerializedPolicyContainer
instead of a live PolicyContainer, history entries no longer keep alive
any GC objects. This eliminates the leak and is also a step toward
moving the session history entry tree to the UI process.
2026-04-03 14:20:09 +02:00
Aliaksandr Kalenik
41e7468ddc LibWeb: Remove unused members from SessionHistoryEntry
Remove m_original_source_browsing_context, m_browsing_context_name, and
m_policy_container along with their getters and setters, as they have no
callers outside the class itself.

This also adds a missing include for JS::call in WebDriver/JSON.cpp,
which was previously provided transitively through the removed headers.
2026-04-03 14:20:09 +02:00
Psychpsyo
6ae9f21845 LibWeb: Implement makeXRCompatible() enough to work 2026-04-03 13:14:33 +02:00
Timothy Flynn
80b612b789 LibWeb: Move the WindowOrWorkerGlobalScope caches attribute
Let's copy-paste the partial interface from the spec.
2026-04-03 11:04:12 +02:00
Timothy Flynn
fb821ead7d LibWeb: Use CacheStorage as a forward declaration
This nearly eliminates the build overhead of changing CacheStorage.h
(where it was previously 2000+ targets rebuilt).
2026-04-03 11:04:12 +02:00
Psychpsyo
44ef574902 LibWeb: Properly set visibility state for nested documents
This cannot happen inside the Make Active algorithm, since that gets
called during document creation, which commonly happens before the
document's navigable is created.

Aligns us with a recent spec change and rids us of some AD_HOC
behavior.
2026-04-01 17:26:46 +02:00
Aliaksandr Kalenik
4985dabf3d LibWeb: Replace cached navigable with Navigable-maintained back-pointer
Now that Navigable directly owns its active document (m_active_document)
we can have Navigable maintain a back-pointer on Document instead of
using the old cache-with-validation pattern that fell back to a linear
scan of all navigables via navigable_with_active_document().
2026-04-01 11:51:43 +02:00
Aliaksandr Kalenik
2645695fdd LibWeb: Make Navigable directly own its active document
Previously, the active document's lifecycle was bound to
SessionHistoryEntry via DocumentState. The ownership chain was:
  Navigable → SessionHistoryEntry → DocumentState → Document

This made it impossible to move SessionHistoryEntry to the UI process
(which cannot own DOM::Document). This commit decouples the two by
giving Navigable a direct m_active_document field that serves as the
authoritative source for active_document().

- Navigable owns m_active_document directly; active_document() reads
  from it instead of going through the active session history entry.

- DocumentState no longer holds a Document pointer. Instead, it stores
  a document_id for "same document?" checks. Same-document navigations
  share a DocumentState and thus the same document_id, while
  cross-document navigations create a new DocumentState with a new ID.

- A pending_document parameter is threaded through
  finalize_a_cross_document_navigation → apply_the_push_or_replace →
  apply_the_history_step so the newly created document reaches
  activation without being stored on DocumentState.

- For traversal, the population output delivers the document.
  A resolved_document is computed per continuation from either the
  pending document, the population output, or the current active
  document (for same-document traversals).
2026-04-01 11:51:43 +02:00
Zaggy1024
1467127d35 LibMedia+LibWeb: Disable audio output in headless mode
Audio output on macOS was consuming Core Audio resources until the
PlaybackStream creation took well over the timeout for some tests.
This was observed in media-source-buffered.html, where it would time
out due to the long-running callback on the main thread to create the
PlaybackStream for AudioMixingSink.

However, the AudioUnit init should definitely not be blocking the main
thread, so I've added a FIXME there.
2026-04-01 02:54:22 -05:00
Zaggy1024
94be6c7611 LibWeb: Prevent a crash when triggering media load in the error handler
If we fire the error event synchronously within the on_error callback,
then we'll end up destroying the PlaybackManager inside its own
callback and crash. Instead, queue a task to execute the error steps.

This could happen with or without MSE, but I observed it occurring on
YouTube with MSE when we hit a decoding error, since they immediately
try another source when an error is reported.
2026-04-01 02:54:22 -05:00
Zaggy1024
51c3f7c41e LibWeb: Implement appending and demuxing WebM MSE segments
The segments are parsed for the SourceBufferProcessor by the
WebMByteStreamParser. It parses the initialization segment to update
its internal set of tracks, then SourceBufferProcessor/SourceBuffer set
them up for playback. When a media segment is received, it also parses
as much of it as is available, returning all the coded frames found so
far. SourceBufferProcessor then tells TrackBufferDemuxer to remove any
overlapping frames and insert the new ones.

TrackBufferDemuxer implements the Demuxer interface in terms of the
coded frame store maintained by the SourceBufferProcessor. It returns
the frames in decode order when requested by a data provider. When a
is needed, it finds the keyframe prior to the target timestamp, and
checks that there are no gaps in data up to the target timestamp. If
there are any gaps, it blocks until the gaps are gone.
2026-04-01 02:54:22 -05:00
Zaggy1024
d960c1eaf5 LibWeb: Implement assignment of MediaSource to HTMLMediaElement src
Also, support the srcObject attribute, and fire the sourceopen event
at the MediaSource.
2026-04-01 02:54:22 -05:00
Zaggy1024
6dcfe20f1e LibWeb: Rename HTMLMediaElement::FetchData -> RemoteFetchData
This struct is only used for remote resources, so let's make that
clearer before adding local resource support in the form of
MediaSources.
2026-04-01 02:54:22 -05:00
Zaggy1024
a41e1ad080 LibWeb: Include a comment for media src attribute and match spec
We're apparently not supposed to load anything when the attribute is
removed.
2026-04-01 02:54:22 -05:00
Zaggy1024
6034a93c83 LibWeb: Expose PlaybackManager's buffered range on the media element 2026-04-01 02:54:22 -05:00
Zaggy1024
f3832c0b36 LibWeb: Use MSE steps to update the media element's ready state
These steps are the best definition we have for how the ready state
should be set, and it seems to be reasonable to apply to plain file
playback as well.

Since our file demuxers are hardcoded to return the entire duration as
buffered, the ready state immediately progresses to HAVE_CURRENT_DATA.
This will probably change once we can check the demuxers for buffered
data.
2026-04-01 02:54:22 -05:00
Zaggy1024
29db875b7f LibWeb: Don't remove video displays on media element finalization
Removing a display risks triggering callbacks on the playback manager
that may cause a recursive GC. This wasn't having any effect since the
playback manager became an OwnPtr.
2026-04-01 02:54:22 -05:00
Zaggy1024
b4db8f11c5 LibMedia+LibWeb: Align Media::Track more to the web spec
...giving tracks a kind attribute, and renaming name to label.

Demuxers will need to determine the kind attribute, since the spec for
sourcing tracks requires us to select based on info we don't expose.
2026-04-01 02:54:22 -05:00
Zaggy1024
9664c11c15 LibMedia+LibWeb: Remove an unnecessary parameter from on_track_added
The TrackType parameter is redundant, since the actual Track object
already contains it.
2026-04-01 02:54:22 -05:00
Aliaksandr Kalenik
f3ea882d6e LibWeb: Remove "signal to continue SHTQ" from document loading
This promise was previously used to signal the session history traversal
queue that it could continue processing, but is no longer needed.
2026-04-01 06:47:59 +02:00
Shannon Booth
e20fd9ba74 LibWeb: Simplify iframe sandbox attribute lookup
Fold the has_attribute and attribute call into an if statement
initializer.
2026-04-01 04:41:11 +02:00
Shannon Booth
0086a7899d LibWeb: Remove some uneeded navigation error propogation
We should not have any errors to propogate down these paths.
2026-04-01 04:41:11 +02:00
Aliaksandr Kalenik
5a7ef7d494 LibWeb: Handle null active document in content_document()
The Crash/HTML/image-load-after-iframe-navigated.html test was
crashing on CI with a null pointer dereference at
NavigableContainer.cpp:178. The crash occurs because content_document()
dereferences the return value of active_document() without checking for
null.

When an iframe is navigated, Document::destroy() sets the old
document state's document to null via set_document(nullptr), but
the navigable (m_content_navigable) remains non-null since it is
reused for the new navigation. During the window between the old
document being destroyed and the new document being set,
active_document() returns null. If JS code accesses
iframe.contentDocument during this window (e.g. via a timer
callback), content_document() would dereference the null pointer.
2026-03-31 18:31:53 +02:00
Callum Law
75ecdaca41 LibWeb: Use document LRC in normalize_source_densities 2026-03-31 10:06:18 +02:00
Aliaksandr Kalenik
baecba0d08 LibWeb: Remove unused spin_processing_tasks_with_source_until()
This function is no longer used after apply_the_history_step was
converted to use an event-driven state machine.
2026-03-31 09:47:59 +02:00
Aliaksandr Kalenik
2a69fd4c52 LibWeb: Replace spin_until in apply_the_history_step with state machine
Replace the blocking spin_processing_tasks_with_source_until calls
in apply_the_history_step_after_unload_check() with an event-driven
ApplyHistoryStepState GC cell that tracks 5 phases, following the
same pattern used by CheckUnloadingCanceledState.

Key changes:
- Introduce ApplyHistoryStepState with phases:
  WaitingForDocumentPopulation, ProcessingContinuations,
  WaitingForChangeJobCompletion, WaitingForNonChangingJobs and Completed
- Add on_complete callbacks to apply_the_push_or_replace_history_step,
  finalize_a_same_document_navigation,
  finalize_a_cross_document_navigation, and
  update_for_navigable_creation_or_destruction
- Remove spin_until from Document::open()
- Use null-document tasks for non-changing navigable updates and
  document unload/destroy to avoid stuck tasks when documents become
  non-fully-active
- Defer completely_finish_loading when document has no navigable yet,
  and re-trigger post-load steps in activate_history_entry for documents
  that completed loading before activation

Co-Authored-By: Shannon Booth <shannon@serenityos.org>
2026-03-31 09:47:59 +02:00
Dylan Hart
c710ff5afa LibWeb: Fire textarea input events immediately instead of debouncing
The 100ms debounce timer on textarea input events causes character
loss when JavaScript restores a previously captured value via
requestAnimationFrame. The text node mutation happens immediately
during input processing, but the input DOM event is delayed,
creating a window where stale rAF callbacks overwrite new input.

Remove the debounce timer and fire the input event immediately
via queue_an_element_task, matching HTMLInputElement behavior.
The spec notes this delay is optional ("User agents may wait").

Fixes #7793.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 13:17:47 -04:00
Adam Colvin
f79c3a4bfe LibWeb: Implement exportparts forwarding in part element map
Implement the forwarded part names step of the CSS Shadow Parts
spec in ShadowRoot::calculate_part_element_map(). When a shadow
host has an exportparts attribute, the inner shadow root's part
element map is consulted and matching parts are added to the
outer shadow root's map under the exported name.

This supports both shorthand same-name forwarding (exportparts=
"foo") and renamed forwarding (exportparts="foo: bar"), and
chains transitively through nested shadow boundaries via
recursive part_element_map() calls.

Fixes 4 WPT tests: simple-forward, simple-forward-shorthand,
double-forward, and precedence-part-vs-part.
2026-03-30 16:47:34 +01:00
Callum Law
0219eb2ef9 LibWeb: Remove FooOrCalculated classes
These are unused since we now store values as `StyleValue`s before
used-value time, and as their resolved type (e.g. CSSPixels) after
2026-03-30 14:05:10 +01:00
Callum Law
f2a8099d13 LibWeb: Parse sizes attribute as StyleValue
Gets us a step closer to removing the `FooOrCalculated` classes
2026-03-30 14:05:10 +01:00
Guilherme Mendes
2064bde5f9 LibWeb: Add case when <br> has display other than 'none'
When <br> element style display is not 'none', it must be an inline box.
Add a condition to ensure <br> is treated as an inline element
instead of a table, flex, or grid in that case,
preventing program from crashing.
Fixes #5568
2026-03-30 12:34:46 +01:00
Dylan Hart
9be298e39c LibWeb: Use document resolution context in canvas set_font
When a canvas belongs to a detached document (e.g. one created via
document.implementation.createHTMLDocument()), document->window()
returns null, causing a null pointer crash in set_font.

Use Length::ResolutionContext::for_document() instead of for_window(),
which handles the no-navigable case gracefully and is already the
recommended pattern (per existing FIXME in Length.h). This also fixes
the same crash path via fillText, strokeText, and measureText which
trigger lazy font initialization through set_font.

Fixes #8515.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:24:29 +02:00
Tim Ledbetter
f601c0cd4b LibWeb: Disable Navigation API after document.open() on about:blank
This matches the behavior of other engines.
2026-03-29 16:39:03 +02:00
InvalidUsernameException
7002c47ce1 LibJS+LibWeb: Pass constants into execution context constructor
The additional data being passed will be used in an upcoming commit.
Allows splitting the churn of modified function signatures from the
logically meaningful code change.

No behavior change.
2026-03-29 13:44:06 +02:00
Jenn Barosa
8808a54f37 LibWeb: Fix session history replacement for superseded navigations 2026-03-29 03:11:14 +02:00
Aliaksandr Kalenik
76d9cc4baf LibWeb: Replace spin_until in execute_script with deferred parser start
HTMLScriptElement::execute_script() and SVGScriptElement had spin_until
calls waiting for ready_to_run_scripts to become true. The race exists
because load_html_document() resolves the session history signal and
starts the parser in the same deferred_invoke — so the parser can hit a
<script> before update_for_history_step_application() sets the flag.

Instead of spinning, defer parser->run() until the document is ready.
Document gains a m_deferred_parser_start callback that is invoked when
set_ready_to_run_scripts() is called. The callback is cleared before
invocation to avoid reentrancy issues (parser->run() can synchronously
execute scripts). All three document loading paths (HTML, XML, text)
now check ready_to_run_scripts before starting the parser and defer if
needed.

create_document_for_inline_content() (used for error pages) now calls
set_ready_to_run_scripts() before mutating the document, ensuring the
invariant holds for all parser paths.

The spin_until calls are replaced with VERIFY assertions.
2026-03-29 01:05:35 +01:00
Aliaksandr Kalenik
df96b69e7a LibWeb: Replace spin_until in HTMLParser::the_end() with state machine
HTMLParser::the_end() had three spin_until calls that blocked the event
loop: step 5 (deferred scripts), step 7 (ASAP scripts), and step 8
(load event delay). This replaces them with an HTMLParserEndState state
machine that progresses asynchronously via callbacks.

The state machine has three phases matching the three spin_until calls:
- WaitingForDeferredScripts: loops executing ready deferred scripts
- WaitingForASAPScripts: waits for ASAP script lists to empty
- WaitingForLoadEventDelay: waits for nothing to delay the load event

Notification triggers re-evaluate the state machine when conditions
change: HTMLScriptElement::mark_as_ready, stylesheet unblocking in
StyleElementBase/HTMLLinkElement, did_stop_being_active_document, and
DocumentLoadEventDelayer decrements. NavigableContainer state changes
(session history readiness, content navigable cleared, lazy load flag)
also trigger re-evaluation of the load event delay check.

Key design decisions and why:

1. Microtask checkpoint in schedule_progress_check(): The old spin_until
   called perform_a_microtask_checkpoint() before checking conditions.
   This is critical because HTMLImageElement::update_the_image_data step
   8 queues a microtask that creates the DocumentLoadEventDelayer.
   Without the checkpoint, check_progress() would see zero delayers and
   complete before images start delaying the load event.

2. deferred_invoke in schedule_progress_check():
   I tried Core::Timer (0ms), queue_global_task, and synchronous calls.
   Timers caused non-deterministic ordering with the HTML event loop's
   task processing timer, leading to image layout tests failing (wrong
   subtest pass/fail patterns). Synchronous calls fired too early during
   image load processing before dimensions were set, causing 0-height
   images in layout tests. queue_global_task had task ordering issues
   with the session history traversal queue. deferred_invoke runs after
   the current callback returns but within the same event loop pump,
   giving the right balance.

3. Navigation load event guard (m_navigation_load_event_guard): During
   cross-document navigation, finalize_a_cross_document_navigation step
   2 calls set_delaying_load_events(false) before the session history
   traversal activates the new document. This creates a transient state
   where the parent's load event delay check sees the about:blank (which
   has ready_for_post_load_tasks=true) as the active document and
   completes prematurely.
2026-03-28 23:14:55 +01:00
Aliaksandr Kalenik
200c72ae5c LibWeb: Remove spin_until from check_if_unloading_is_canceled()
Replace the two spin_processing_tasks_with_source_until() calls in
TraversableNavigable::check_if_unloading_is_canceled() with a
callback-based GC cell (CheckUnloadingCanceledState) that tracks
completion across both phases (traverse navigate event + per-document
beforeunload handlers) and invokes a callback when done.

This required making check_if_unloading_is_canceled() async
(callback-based), splitting apply_the_history_step() into pre-check
and continuation parts, and updating all callers to move session
history traversal queue promise resolution into callbacks.

The trusted-event test is rebaselined because beforeunload now fires
as a queued NavigationAndTraversal task rather than being processed
inline by spin_until. This allows the unhandledrejection microtask
to run before the beforeunload task, swapping their order.
2026-03-28 04:17:21 +01:00
Sam Atkins
ed6a5f25a0 LibWeb: Implement scoped custom element registries 2026-03-27 19:49:55 +00:00
Sam Atkins
71626ac58c LibWeb: Update "look up a custom element definition" algorithm
This now takes a registry directly. As a temporary stop-gap, the old
method on Document is still here and calls the new one.

We do get a test regression:

"Creating an element in a cloned document and inserting into the
document must not enqueue a custom element upgrade reaction" in
"custom-elements/upgrading.html".

Possibly a spec bug?
2026-03-27 19:49:55 +00:00