Commit Graph

4997 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
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
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
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
Timothy Flynn
432be813ce Tests/LibWeb: Disable a couple tests 2026-02-24 21:46:25 -05: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
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
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
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
4ea87db0a8 LibWeb/CSS: Load all fonts through FontFace::load()
The spec requires us to follow the steps in FontFace::load() whenever a
font is loaded. The simplest way to do so, is to make that the only way
we load fonts. :^)

To support this, FontFace::load() uses its connected CSSFontFaceRule's
ParsedFontFace if it's available.

The 1 regression in generic-family-keywords-003.html seems to be a false
positive: we don't support the system-ui font keyword.
2026-02-24 15:44:32 +00:00
Aliaksandr Kalenik
efbefb3b59 LibWeb: Skip display list commands under zero-area clips
Add a pre-computed `has_empty_effective_clip` flag on
AccumulatedVisualContext that propagates from parent to child. When a
clip rect or clip path has zero area, all descendant commands are
skipped at display list recording time in `DisplayList::append()`,
so they are never stored or executed.

This allows skipping ~10% of display list commands in the Discord app.
2026-02-24 16:41:20 +01:00
Aliaksandr Kalenik
beb7971762 Tests: Add display list test for zero-area clip commands 2026-02-24 16:41:20 +01:00
Tim Ledbetter
91b7525e18 LibWeb: Ensure favicon URL is valid before fetching it
Previously, we would crash when attempting to fetch the favicon if
the `<base>` element had an invalid URL.
2026-02-24 15:05:31 +01:00
Aliaksandr Kalenik
1fc4c69ad8 LibWeb: Expand PaintNestedDisplayList in internals.dumpDisplayList()
Previously, PaintNestedDisplayList was treated as an opaque command,
printing only its name and rect without showing the nested display
list's contents. This made it impossible to debug painting issues
involving SVG masks/clips, CSS background-clip: text, and iframe
content through display list dumps.

Refactor the command dump loop into a recursive lambda that expands
nested display lists inline with increased indentation.
2026-02-24 14:37:29 +01:00
Aliaksandr Kalenik
0c570dc6ed LibWeb: Only rebaseline screenshot tests when actual output differs
Previously, --rebaseline would unconditionally overwrite expected PNGs
before comparing, causing every screenshot test expectation to be
regenerated even when the actual screenshot already matched. Restructure
to load and compare first, only writing the new expectation on mismatch
or when the expected file doesn't exist yet.
2026-02-24 13:57:54 +01:00
Aliaksandr Kalenik
d7a8db671b LibWeb: Skip overflow clip generation for SVG inner elements
Per the CSS Overflow spec, overflow properties apply only to block
containers, flex containers, and grid containers — not SVG graphics
elements. Add an `is<SVGPaintable>` check in
`overflow_property_applies()` to return false for SVG inner elements
like `<g>`, `<rect>`, `<path>`.

This doesn't affect `<svg>` elements (which use `SVGSVGPaintable`, a
direct `PaintableBox` subclass) or `<foreignObject>` (which uses
`SVGForeignObjectPaintable`, a `PaintableWithLines` subclass) — both
correctly keep their overflow clips.
2026-02-24 12:28:55 +01:00
Aliaksandr Kalenik
5a073fdbf1 Tests: Add display list test for overflow on SVG inner elements
This test captures the current (incorrect) behavior where setting
`overflow: hidden` on an SVG `<g>` element produces a clip in the
display list. Per the CSS Overflow spec, overflow properties only apply
to block containers, flex containers, and grid containers — not SVG
graphics elements.
2026-02-24 12:28:55 +01:00
Tim Ledbetter
6b3d3468a1 LibWeb: Account for <col> span attribute during table grid formation
Previously, the column count was always incremented by 1. This led to a
mismatch with `compute_outer_content_sizes()`, which did use the `span`
attribute to advance the column index. This mismatch caused an
out-of-bounds access when the column index was greater than the
expected number of columns.
2026-02-24 12:14:54 +01:00
Sam Atkins
f657a4b71b LibWeb/CSS: Parse @font-face { font-weight } with two values
WPT has coverage for matching but not parsing, so the test is homemade.
2026-02-24 10:05:09 +00:00
Aliaksandr Kalenik
d2528dd5ce LibWeb: Compare Screenshot tests directly against expected PNGs
Instead of rendering a reference HTML page that wraps an <img> tag
pointing to a PNG, Screenshot tests now load the expected PNG directly
from disk and compare it against the rendered screenshot. This
eliminates the indirection of loading and rendering a second page just
to display a static image.

This also means --rebaseline now works for Screenshot tests, generating
the expected PNG automatically instead of requiring manual screenshot
capture and placement.

Changes:
- Add TestMode::Screenshot with its own collector and runner
- Move PNGs from Screenshot/images/ to Screenshot/expected/ with
  normalized names matching input filenames
- Remove all 92 reference HTML wrapper files and the images/
  directory
- Remove <link rel="match"> from all 94 Screenshot input HTML
  files
- Update add_libweb_test.py Screenshot boilerplate accordingly
- Add Screenshot mode to results viewer image comparison tabs
2026-02-24 09:55:14 +01:00
Aliaksandr Kalenik
86bc379119 Tests: Move true ref tests from Screenshot/ to Ref/
Move them to Ref/ where they belong, before converting the remaining
Screenshot tests to direct PNG comparison.
2026-02-24 09:55:14 +01:00
Aliaksandr Kalenik
5ef132ba1a LibWeb: Replace AddMask/clipShader with saveLayer+DstIn compositing
This applies the same pattern used for background-clip: text (commit
f2e6f70fbb).

Results in visible performance improvement in Discord app where
previously, according to profiles, we spent lots of time allocating
surfaces for masks.
2026-02-24 07:14:16 +01:00
Aliaksandr Kalenik
533228f8ad LibWeb: Invalidate stacking context tree after partial SVG relayout
relayout_svg_root() clears individual stacking contexts via
reset_for_relayout() but didn't call invalidate_stacking_context_tree().
The viewport's stacking context remained non-null, so
build_stacking_context_tree_if_needed() skipped the rebuild. This caused
foreignObject to lose its stacking context after relayout, breaking SVG
mask application.
2026-02-24 06:15:07 +01:00
Aliaksandr Kalenik
19d3ca90b2 Tests: Add display list test for SVG foreignObject mask after relayout
This test verifies that SVG mask application on foreignObject is
preserved after partial SVG relayout. Currently the mask is not applied
to the foreignObject content after relayout because the stacking context
tree is not rebuilt.
2026-02-24 06:15:07 +01:00
Luke Wilde
8017f8a7ed Tests/LibWeb: Import Fullscreen WPT tests 2026-02-23 18:44:26 +00:00
Luke Wilde
6491c6bb90 test-web: Reset viewport size after each test 2026-02-23 18:44:26 +00:00
Luke Wilde
66d5bff914 test-web: Skip invalid test names in Ref tests 2026-02-23 18:44:26 +00:00
Simon Farre
bc17805b2b LibWeb: Implement requestFullscreen algorithm
The required functionality to exit fullscreen will be in a followup
commit.
2026-02-23 18:44:26 +00:00
Jelle Raaijmakers
1cc29c669a WebContent: Combine viewport size and DPR into a single IPC message
The set_viewport_size and set_device_pixel_ratio IPC messages were sent
separately, potentially causing a race condition when the DPR changes
(e.g. moving a window between screens): the DPR message would arrive
and use a stale viewport size, computing a temporarily wrong CSS
viewport. Combine both into a single set_viewport IPC that updates the
device viewport size and DPR together.
2026-02-23 15:22:12 +01:00
Jelle Raaijmakers
15e784cc4f Tests/LibWeb: Generate proper diff image instead of blending images
If the difference between the expected and actual test images was small,
our in-browser diff tool would often fail to highlight differing pixels.

Replace this by generating a new diff PNG that is layered as follows:

  1. 50%/50% blend of the actual and expected images
  2. 80% blend with white / rgb(255, 255, 255)
  3. Differing pixels are highlighted in red / rgb(255, 0, 0)
2026-02-23 14:21:59 +01:00
Jelle Raaijmakers
a5be2d247b Tests/LibWeb: Report fuzzy matching errors in test-web's results HTML 2026-02-23 14:21:59 +01:00
Jelle Raaijmakers
73658137b6 Documentation+Tests: Optimize PNGs using optipng
The wide gamut test file went unused, so it was deleted.
2026-02-23 13:45:04 +01:00
Callum Law
8d4084261a LibWeb: Resolve list item marker using registered counter styles 2026-02-23 11:21:09 +00:00
Callum Law
ca54cc6c79 LibWeb: Resolve <counter> functions using registered counter styles
Previously we only supported a subset of the predefined counter styles,
we now respect counter styles defined by `@counter-style` rules when
resolving the value of `counter()` and `counters()` functions
2026-02-23 11:21:09 +00:00
Jonathan Gamble
34742681de LibWeb: Avoid spin_until in HTMLImageElement::decode_image
Improve performance of overlapping decodes. Reject on src changes
during the operation.
2026-02-23 10:11:04 +01:00
Callum Law
49eb9d7a7a LibWeb: Support composition of mixed values
This exposes an existing issue with interpolation where it is not clear
in what situations zero-valued dimensions should be excluded from the
interpolated value of a dimension-percentage mix (e.g. `calc(50% + 0px)`
vs `50%`) - but this is just a serialization issue as both
representations are resolved to the same used value
2026-02-23 09:01:19 +00:00
Tim Ledbetter
81f077adfd LibWeb: Ensure mspace presentation hint is valid before setting it
The height and depth attributes are parsed individually and then
combined into a `calc()` expression. Bare zero is valid as a standalone
CSS length but inside `calc()` it is typed as a number, so
`calc(0 + 0)` fails to parse as a length. We now check the parsed value
is valid to avoid a crash.
2026-02-23 09:57:32 +01:00
Zaggy1024
470248e00d LibMedia+LibWeb: Stop ref counting PlaybackManager
PlaybackManager's ref counting was only used to keep it alive in a few
callbacks. Instead, the callbacks can use weak references that can only
be used from the thread that the PlaybackManager was created on, to
ensure that the PlaybackManager can't be destroyed while being
accessed.

This ensures that:
- The PlaybackManager is destroyed immediately when it is reassigned
  by HTMLMediaElement
- No callbacks are invoked after that point

This fixes the crash initially being addressed by #8081. The test from
that PR has been included as a regression test.
2026-02-23 08:49:13 +00:00
Zaggy1024
21019c2fa9 LibWeb: Use UA shadow DOM for media elements' controls
Instead of using a custom paintable to draw the controls for video and
audio elements, we build them out of plain old HTML elements within a
shadow root.

This required a few hacks in the previous commits in order to allow a
replaced element to host children within a shadow root, but it's
fairly self-contained.

A big benefit is that we can drive all the UI updates off of plain old
DOM events (except the play button overlay on videos, which uses the
video element representation), so we can test our media and input event
handling more thoroughly. :^)

The control bar visibility is now more similar to how other browsers
handle it. It will show upon hovering over the element, but if the
cursor is kept still for more than a second, it will hide again. While
dragging, the controls remain visible, and will then hide after the
mouse button is released.

The icons have been redesigned from scratch, and the mute icon now
visualizes the volume level along with indicating the mute state.
2026-02-23 07:27:31 +01:00
Zaggy1024
bc60768cb0 LibWeb: Rewrite audio elements without controls to display:none
This is part of the rendering spec, but we had neglected to do this
before. It causes one WPT check to fail, but other browsers get the
same result on that check, so I guess we can call that a win. :^)
2026-02-23 07:27:31 +01:00
devgianlu
3d7b02333f LibWeb: Import some CredentialsContainer WPT tests 2026-02-22 14:55:30 -05:00