Commit graph

75527 commits

Author SHA1 Message Date
Tim Ledbetter
f05bc7c0cd LibWeb: Implement dominant-baseline for SVG text
This property determines the default baseline used to align content
within the given box.
2026-02-26 09:23:23 +01:00
Jelle Raaijmakers
90a211bf47 LibWeb: Use device-pixel coordinates in display list and AVC
Stop converting between CSS and device pixels as part of rendering - the
display list should be as simple as possible, so convert to DevicePixels
once when constructing the display list.
2026-02-26 07:43:00 +01:00
Shannon Booth
8d099b9cec LibWeb: Add non const global object getter to EnvironmentSettingsObject
And sneak in a as_if tidyup too.
2026-02-26 07:22:50 +01:00
Shannon Booth
9e7aa878bc LibWeb: Properly determine if running in SecureContext for Workers
Fixes the included imported test. Note that this required a minor
edit of the WPT import to work with our test harness setup to
try and create a non secure context setup as both file:// and
localhost are considered secure contexts.
2026-02-26 07:22:50 +01:00
Shannon Booth
457b83313e LibWeb/HTML: Add representation to WorkerGlobalScope to track owner set
Note that this is done using the serialized versions of these objects
as this is always used across different processes and the javascript
realm should never be relevant for owner set.
2026-02-26 07:22:50 +01:00
Shannon Booth
025ddd385b LibWeb/HTML: Track secure context as part of Serialized{Document,Worker}
This is somewhat awkward as the spec refers to 'is secure context'
with respect to these objects 'relevant settings object'. A natural
way of implementing this could be storing a pointer to the relevant
settings object like the JS representations of these objects do
(and then changing is_secure_context to accept this representation
too), but for now it seems much simpler to just store a boolean for
this purpose and sidestep both problems above.
2026-02-26 07:22:50 +01:00
Timothy Flynn
cb6a4683ce LibJS: Return UTF16String's ASCII storage when applicable
If we have a UTF-16 string with ASCII storage, we don't need to convert
the string to UTF-8 to get a StringView. This fast-path is hit over 76k
times during test-js and over 31 million times during test262.
2026-02-26 00:02:17 +01:00
Andreas Kling
00ffc340bc LibJS: Wrap CompiledRegex in Rc to allow AST cloning
CompiledRegex held an FFI handle with unique ownership and panicked
on clone. This caused a crash when a class field initializer contained
a regex literal, since the codegen wraps field initializers in a
synthetic function body by cloning the expression.

Wrapping CompiledRegex in Rc makes the clone a cheap refcount bump.
The take() semantics are preserved: the first codegen path to call
take() gets the handle, and Drop frees it if nobody took it.
2026-02-25 21:54:30 +01:00
Jonathan Gamble
472d6d4805 LibWeb+test-web: Add --fail-fast option
Offer to attach debugger if it's a timeout.
2026-02-25 12:33:35 -06:00
Jonathan Gamble
4cafb9b8bc LibWeb+test-web: Add --debug-timeouts option to capture backtraces 2026-02-25 12:33:35 -06:00
Jonathan Gamble
5911e8a527 LibWeb+test-web: Add --repeat flag
If provided, test-web batches & results will be partitioned in
multiple runs. Each run will execute the same set of tests, and
non-pass results will be stored in run1, run2, run6, etc directories.
2026-02-25 12:33:35 -06:00
Jonathan Gamble
e239ac88d9 LibWeb+test-web: Strip terminal escape codes from captured stderr 2026-02-25 12:33:35 -06:00
Jonathan Gamble
6e03c2168c LibWeb: Reduce navigation test's workload so it doesn't timeout on CI
In high concurrency, sometimes 400+ blob urls and iframe loads take
longer than 30 seconds, especially on sanitizer runs when memory is
tight. Reduce the number of urls and iframes to 84.
2026-02-25 12:33:35 -06:00
Jonathan Gamble
34cecb4643 LibWeb+test-web: Allow identical echo registrations in http-test-server
The http-test-server.py change allows repeated fixed /echo route
registration by Text/input/navigation/iframe-referrer-policy.html.
Before this change, the second registration of the same method+path+def
returned 409, causing include.js to throw and fail the test.

Make /echo registration idempotent for identical definitions and return
success, but keep 409 for conflicting redefinitions of an existing
method+path.
2026-02-25 12:33:35 -06:00
Tim Ledbetter
245eb7d91d LibWeb: Use margin box for vertical overlap checks in float placement
Previously, a float with `padding-top` would overlap a preceding float
instead of being placed beside it. The vertical overlap check was
comparing the new float's content box Y,which includes the padding
offset, against preceding floats' margin box rects, causing the check
to incorrectly conclude the floats do not overlap.
2026-02-25 12:03:31 +01:00
Andreas Kling
7b0d818f8e LibWeb: Update layout before accessing paintables in viewport scroll
perform_a_scroll_of_the_viewport() accesses paintable_box() without
ensuring layout is up to date. This can lead to a null dereference
if the paintable tree was torn down (e.g. by adding a dialog to the top
layer via showModal()) between the last layout update and the scroll.

One concrete path: Window::scroll() has an optimization that skips
update_layout when scrolling to (0, 0), but still calls
perform_a_scroll_of_the_viewport if the viewport is at a non-zero
position.

Fix by adding an update_layout call at the top of
perform_a_scroll_of_the_viewport.
2026-02-25 10:18:08 +01:00
InvalidUsernameException
8c57fa780f CI: Remove redundant set -e calls
Shell scripts running in GitHub Actions workflows have `set -e` enabled
by default:
https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsshell

To avoid confusion, remove the redundant calls present in some of the
workflow script steps.
2026-02-25 10:08:23 +01:00
InvalidUsernameException
0c5684f7ff CI: Do not run multiple note-pushing workflow runs in parallel
In 1d03944a9c failures from pushing notes were ignored entirely due to
the command failing sporadically. Looking at the original commit message
this was almost certainly due to the fact that multiple runs of the
workflow could happend simulaneously if PRs were merged in quick
succession:

1. PR 1 gets merged.
2. Workflow run 1 gets triggered for newly pushed `master` commit from
   PR 1 and fetches notes ref at `aaaaaaa`.
3. PR 2 gets merged.
4. Workflow run 2 gets triggered for newly pushed `master` commit from
   PR 2 and fetches notes ref at `aaaaaaa` as well.
5. Workflow run 1 finishes its work and pushes `bbbbbbb` to the notes
   ref.
6. Workflow run 2 finishes as well, tries to push `ccccccc` to the notes
   ref, but gets rejected. This is because its changes are based on
   `aaaaaaa` and cannot be fast-forwarded due to workflow run 1 having
   pushed different notes in the meantime.

This sequence of events could also be observed after bbad346add got
merged, which caused the first couple workflow runs after to be very
slow as they were processing a large backlog of missing notes.

Instead of silencing the error when it happens and relying on the fact
that the next run will correct it, let's just prevent the conflict from
happening in the first place by disallowing parallel runs of the
workflow. This avoids unnecessary workflow runs and allows detection of
other, unexpected errors happening when pushing.
2026-02-25 10:08:23 +01:00
InvalidUsernameException
5f70d40feb CI: Make failure to fetch git-gloss a fatal error
bbad346add corrected a URL that broke several weeks ago. This problem
went unnoticed for a while partially because the workflow runs were all
still passing. A failure of a command in an &&-list is only considered
an error if it occurred in the last command of the list, even with `set
-e` being active (set automatically in GitHub actions).

From the Bash Reference Manual, 4.3.1 The Set Builtin:

> The shell does not exit if the command that fails is [...] part of any
> command executed in a && or || list except the command following the
> final && or ||.

Let's make download failures easier to disover by failing the workflow.
Every master-push getting marked with a red x-sign would probably have
been caught earlier.
2026-02-25 10:08:23 +01:00
Aliaksandr Kalenik
9231b54d49 LibWeb: Pre-populate viewport in SVG subtree relayout
During SVG subtree relayout, position:fixed elements inside
<foreignObject> use the viewport as their containing block. Since the
viewport is outside the SVG subtree, it was not pre-populated in the
LayoutState, causing a VERIFY failure in ensure_used_values_for().

Fix this by unconditionally pre-populating the viewport node from its
paintable in relayout_svg_root().
2026-02-25 09:05:10 +01:00
Jonathan Gamble
410e17ab29 LibMedia: Fix signed PCM to float sample normalization 2026-02-25 01:50:00 -06:00
dependabot[bot]
e803c381a9 CI: Bump dawidd6/action-download-artifact from 14 to 15
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 14 to 15.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/v14...v15)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-version: '15'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-24 21:47:10 -05:00
dependabot[bot]
37454ec9e9 CI: Bump actions/stale from 10.1.1 to 10.2.0
Bumps [actions/stale](https://github.com/actions/stale) from 10.1.1 to 10.2.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](997185467f...b5d41d4e1d)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: 10.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-24 21:46:55 -05:00
Timothy Flynn
432be813ce Tests/LibWeb: Disable a couple tests 2026-02-24 21:46:25 -05:00
Zaggy1024
1453add361 Tests: Use the proper stream close() method in TestFFmpegDemuxer
The test was outdated and needed to be updated before being merged. :^(
2026-02-24 17:51:03 -06:00
Andreas Kling
4b47245e99 LibJS: Cache ASCII-to-UTF-16 source conversion for Rust compilation
The Rust FFI requires UTF-16 source data, so ASCII-stored source code
must be widened to UTF-16. Previously, this conversion was done into a
temporary buffer on every call to compile_function, meaning the entire
source file was converted for each lazily-compiled function. For large
modules with many functions, this caused heavy spinning.

Move the conversion into SourceCode::utf16_data() which lazily converts
and caches the result once per source file. Subsequent compilations of
functions from the same file reuse the cached data.
2026-02-25 00:00:52 +01:00
Andreas Kling
a7d1c4baa6 LibJS: Defer GC during Rust-pipeline module and builtin compilation
The Rust bytecode pipeline stores SharedFunctionInstanceData pointers
as raw void pointers invisible to the GC. If garbage collection runs
during compilation (triggered by heap allocation of a new SFD), it
can collect previously created SFDs, leaving stale pointers that
crash during the next GC marking phase.

Every other Rust compilation entry point (compile_script, compile_eval,
compile_shadow_realm_eval, compile_dynamic_function, compile_function)
already uses GC::DeferGC to prevent this. Add the missing DeferGC to
compile_module and compile_builtin_file.
2026-02-25 00:00:52 +01:00
Zaggy1024
3a7f1f0b75 Tests: Add a test to read FFmpegDemuxer to EOF after aborting a read 2026-02-24 16:55:40 -06:00
Zaggy1024
4778c6a53b LibMedia: Deal with aborts in FFmpegDemuxer instead of the IO context
libavcodec apparently holds onto any error that is not AVERROR_EOF when
a read fails. This means that reading until EOF after an aborted read
results in us receiving an AVERROR_EXIT in FFmpegDemuxer instead of
AVERROR_EOF, which causes the playback system to enter an error state
without decoding all frames in the file.

Instead, just always return AVERROR_EOF, and check if the read was
aborted in FFmpegDemuxer instead to return the correct error category
from there.
2026-02-24 16:55:40 -06:00
Zaggy1024
6859c708c1 LibMedia: Add a formatter for DecoderErrorCategory
...and use it in the DecoderError formatter, as the category is often
more relevant than the error message.
2026-02-24 16:55:40 -06:00
Zaggy1024
dc95107eb6 test-web: Use the output StringBuilder to measure the counter length
Formatting the counter into a separate string is an unnecessary
allocation.
2026-02-24 16:00:25 -06:00
Andreas Kling
eda33abdbb LibGC: Remove hash() from Traits<GC::Weak<T>>
Make HashTable<GC::Weak<T>> a compile error to prevent future misuse.
All existing uses have been migrated to GC::WeakHashSet<T> which
provides its own internal hash traits.
2026-02-24 22:35:03 +01:00
Andreas Kling
f1573dfc63 LibWeb: Use GC::WeakHashSet for StyleScope's pending :has() nodes
Replace the unsafe HashTable<GC::Weak<DOM::Node>> with
GC::WeakHashSet<DOM::Node>. The null check in the iteration loop is
no longer needed since WeakHashSet's iterator skips dead entries.
2026-02-24 22:35:03 +01:00
Andreas Kling
73b0ecd89d LibWeb: Use GC::WeakHashSet for AnimationTimeline associated animations
Replace the unsafe HashTable<GC::Weak<Animation>> with
GC::WeakHashSet<Animation>, and update all callers to use reference
syntax instead of pointer syntax since the iterator now yields T&.
2026-02-24 22:35:03 +01:00
Andreas Kling
323e7dd79d LibGC: Add GC::WeakHashSet<T> for safe weak pointer hash sets
HashTable<GC::Weak<T>> is unsafe because GC::Weak's hash depends on
ptr() which becomes nullptr when the object is collected. This corrupts
the hash table: entries shift to wrong buckets, probe chains break
during delete_bucket(), and rehash scatters dead entries incorrectly.

WeakHashSet wraps HashTable with private internal traits that own the
hash function, prunes dead entries before every mutation, and provides
an iterator that skips dead entries and yields T& directly.
2026-02-24 22:35:03 +01:00
Zaggy1024
e195d4e33e LibWeb: Move canvas and media element iteration methods out of line
This reduces the number of rebuilt files when modifying
HTMLMediaElement.h and HTMLCanvasElement.h significantly.
2026-02-24 21:09:27 +01:00
Zaggy1024
2e4ef086f3 LibWeb: Include Requests.h in SharedResourceRequest.cpp
This is only transitively included through Page.h ->
HTMLMediaElement.h.
2026-02-24 21:09:27 +01:00
Timothy Flynn
5224eb8db6 CI: Switch back to Linux for code linting
We switched to macOS since it was easier to install swift-format in CI.
With that removed, let's switch back to Linux, as macOS runners tend to
have higher contention.

To do so, this makes more use of the setup action. This way, the setup
action is the only place that needs to know how to install the apt repos
we need (LLVM in particular).
2026-02-24 14:33:22 -05:00
Luke Wilde
21713377e2 LibWeb: Paint SVG-in-img with a nested display list
This makes SVG-in-img appear sharp no matter the current
(pinch-to-)zoom level.
2026-02-24 19:13:23 +01:00
Aliaksandr Kalenik
abb392bd65 LibWeb: Remove redundant flush() in DisplayListPlayer::execute_impl()
The flush() call at the end of execute_impl() was accidentally left
behind in 2d2af9cd3b. That commit moved flushing into execute(), but
didn't remove the old call from execute_impl(). This caused every
nested display list to trigger a redundant GPU flush.

On an M4 MacBook, this improves Discord from ~65 FPS to 120 FPS.
2026-02-24 18:50:02 +01:00
Andreas Kling
f19d00ca9e LibJS: Memoize failed arrow function attempts in Rust parser
Cache failed arrow function attempts by token offset. Once we
determine that '(' at offset N is not the start of an arrow
function, skip re-attempting at the same offset.

Without memoization, nested expressions like (a=(b=(c=(d=0))))
cause exponential work: each failed arrow attempt at an outer '('
re-parses all inner '(' positions during grouping expression
re-parse, and each inner position triggers its own arrow
attempts. With n nesting levels, the innermost position is
processed O(2^n) times.

The C++ parser already has this optimization (via the
try_parse_arrow_function_expression_failed_at_position()
memoization cache).
2026-02-24 18:42:13 +01:00
Tim Ledbetter
84043cd82d LibWeb: Track deleted state on IndexedDb Index and ObjectStore
An `InvalidStateError` is now thrown when an attempt is made to
interact with an index or object store that has been deleted.
2026-02-24 17:37:04 +01:00
Luke Wilde
f06732d180 LibWeb: Mark CacheStorage as Experimental
CacheStorage is currently a stub that breaks anything that uses it.
2026-02-24 17:08:48 +01:00
Luke Wilde
09e00677eb IDLGenerators: Support Experimental extended attribute on IDL attributes 2026-02-24 17:08:48 +01:00
Sam Atkins
afdc0df70b Tests: Re-enable some tests which rely on font loading
These should no longer be flaky, now that we wait for fonts to load.
2026-02-24 15:44:32 +00:00
Sam Atkins
000f902522 Tests: Import WPT test for document.fonts.ready 2026-02-24 15:44:32 +00:00
Sam Atkins
1ac3ede046 LibWeb/CSS: Make @font-face a critical style subresource
This causes `@font-face`'s loading state to propagate to its style sheet
and upwards.
2026-02-24 15:44:32 +00:00
Sam Atkins
5e3f4d71cc LibWeb/CSS: Remove number_of_css_font_faces_with_loading_in_progress()
This is now unused as of the previous commit.
2026-02-24 15:44:32 +00:00
Sam Atkins
d9f12da712 LibWeb: Implement missing code for FontFace/FontFaceSet loading
As FontFaces are added or removed from a FontFaceSet, and as they load
or fail, the FontFaceSet moves them between a few different lists, and
updates its loading/loaded status. In the spec, this is how the
FontFaceSet.[[ReadyPromise]] gets fulfilled: When the document has
finished loading and FontFaceSet.[[LoadingFonts]] is empty, it resolves
the promise.

To support this, FontFace now keeps a set of FontFaceSets that it is
contained in.

This lets us remove the non-spec resolve_ready_promise() call in
EventLoop which was sometimes triggering before any fonts had attempted
to load.

As noted, there's a spec issue with the ready promise: If nothing
modifies the document's fonts, then it would never resolve. My ad-hoc
fix is to also switch the FontFaceSet to the loaded state if it is
empty, which appears to solve the issues but is not ideal.
2026-02-24 15:44:32 +00:00
Sam Atkins
bca6f3e4b5 LibWeb/DOM: Always give Document a FontFaceSet
In practice, the event loop queries Document::fonts(), so we don't gain
anything by delaying the allocation, apart from making it unclear when
it happens.
2026-02-24 15:44:32 +00:00