Commit graph

79545 commits

Author SHA1 Message Date
Andreas Kling
78851f69f0 Meta: Bump curl to 8.20.0#2
This brings in support for Apple SecTrust on macOS, which means curl
uses the system's certificate verification mechanism.
2026-06-19 12:22:11 +02:00
Andreas Kling
ea08f5b1a2 Meta: Bump vcpkg baseline 2026-06-19 12:22:11 +02:00
Jelle Raaijmakers
fe33a2f66e CI: Update actions/cache to @v5 2026-06-19 10:40:43 +02:00
Jelle Raaijmakers
e2e2806d00 CI: Make dependabot scan our custom actions as well
By default, dependabot only looks at `.github/workflows`.
2026-06-19 10:40:43 +02:00
sideshowbarker
9d64cd8c9b LibGfx: Reject the Invalid bitmap format from IPC decoders
Problem: A borked process sending a Gfx::Bitmap (inside BitmapSequence)
or a Gfx::ShareableBitmap over IPC could set BitmapFormat::Invalid as
the format field. The receiving process then aborted while decoding the
message — an IPC-reachable crash.

Cause: The helper that both decoders use for validating the format read
off the wire accepts BitmapFormat::Invalid. The decoders go on to build
a bitmap with that format. But that triggers an assert — because
minimum_pitch only knows the four real pixel formats.

Fix: Drop BitmapFormat::Invalid from is_valid_bitmap_format. It’s an
indicator of an absent/unknown format, never one a real bitmap can have.
And any real bitmap is never encoded with it. So, both BitmapSequence
and ShareableBitmap decode now return a clean decode error for it.
2026-06-19 10:33:36 +02:00
Callum Law
fdca036ff3 LibWeb: Implement CSS progress() math function
`no-clamp` tests are added in-tree since there aren't any in WPT yet.
2026-06-19 09:33:06 +01:00
dependabot[bot]
043adecb13 CI: Bump actions/checkout from 6.0.3 to 7.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6.0.3...v7.0.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-19 09:52:09 +02:00
Tim Ledbetter
abe6d2c045 CI: Add a PR CI step to check new and modified tests for flakiness 2026-06-19 09:47:55 +02:00
Tim Ledbetter
6ebf9c54de Meta: Add a script to test the flakiness of newly-added tests
This script first identifies newly-added and newly-unskipped tests in
the working tree vs. a given base ref. It then runs each of these tests
individually using `test-web` at each of the given concurrency levels.
2026-06-19 09:47:55 +02:00
Tim Ledbetter
a9261b9daf test-web: Don't include skipped tests in --dry-run output 2026-06-19 09:47:55 +02:00
Luke Wilde
8dc8835b64 LibWeb+LibWebView+WebContent: Allow muted media to autoplay by default
The autoplay setting was binary and its default blocked all media,
including muted video, leaving sites that rely on muted autoplay
visibly broken. Replace it with a tri-state user-agent autoplay
policy (allow audio and video, block audio, or block audio and video)
defaulting to allowing only inaudible media to autoplay.

This is enforced through the media element's "allowed to play" check,
so unmuting a muted autoplay or calling `play()` cannot slip audio
past the policy; audible playback is permitted once the document has
been activated by the user. The policy lives in a dedicated
AutoplaySettings consulted from HTMLMediaElement instead of the
Permissions Policy "allowed to use feature" check it was previously
conflated with.
2026-06-19 09:41:32 +02:00
Andreas Kling
ca87f977e6 LibWeb: Reject child selectors with a parent hash filter
For selectors whose rightmost relation is an immediate child combinator,
collect hashes that must be present on the subject parent and reject the
rule early when the current parent cannot satisfy them. This avoids full
selector matching for common child-combinator tails.
2026-06-19 09:36:53 +02:00
Andreas Kling
14fc971035 LibWeb: Bucket :host selectors by subject pseudo-class
Only shadow hosts can match :host selectors, so route them through the
subject pseudo-class bucket instead of the generic other bucket. Full
selector matching still validates the shadow-root context and any
arguments.
2026-06-19 09:36:53 +02:00
Andreas Kling
8e473cb703 LibWeb: Bucket pseudo :is() rules by originating element
Split pseudo-element rules whose originating compound contains :is() or
:where() across the cheap buckets from their selector-list alternatives
when the rule would otherwise land in the pseudo-element other bucket.

Use per-collection generation stamps to suppress duplicate candidates
when more than one alternative bucket applies to the same originating
element. Add text coverage for class, attribute, and complex combinator
arguments reaching generated pseudo-element style.
2026-06-19 09:36:53 +02:00
Andreas Kling
093a24d3f9 LibWeb: Bucket heading pseudo-class rules
Treat :heading as a subject pseudo-class bucket so heading rules are
only enumerated for h1 through h6 elements. The selector matcher still
checks functional :heading() levels, so the bucket only narrows rule
collection before normal matching.
2026-06-19 09:36:53 +02:00
Andreas Kling
f45bf0e770 LibWeb: Bucket ancestor-filtered rules by ancestor hash
Add a late rule-cache bucket for selectors that do not expose a
current-element bucket but do expose ancestor-filter metadata. These
rules previously stayed in the global other bucket and relied on the
ancestor filter after broad enumeration.

Visit the new buckets only when the current ancestor bloom filter may
contain the bucket hash. Keep pseudo-class invalidation caches opted
out because those caches answer targeted invalidation questions rather
than normal style collection.

On the GitHub profile, other-bucket candidates fell from about 5.50k
to about 1.07k per 1k rule collection calls.
2026-06-19 09:36:53 +02:00
Andreas Kling
f39890bdc8 LibWeb: Bucket subject pseudo-class rules
Put rules whose rightmost compound has no id, class, tag, or
attribute bucket into a subject pseudo-class bucket when they have a
required cheap element-state pseudo-class such as :hover, :focus, or
:checked.

Also let :is() and :where() selector lists use a regular bucket when
every alternative exposes the same mandatory bucket key. Pseudo-class
invalidation rule caches keep using broad buckets because they must
consider rules while the matching state is changing.
2026-06-19 09:36:53 +02:00
sideshowbarker
b6bd191531 CI: Use the image-provided wasm-tools on the Linux jobs
Bump the workflow image pin to the 2026.06.14 tag that bakes in
wasm-tools. And keep the wasm-tools download/caching steps for the macOS
and Windows jobs — but skip those steps on Linux. So, the Linux jobs use
the wasm-tools copy the image installs.

Follow-up to https://github.com/LadybirdBrowser/ladybird/pull/9972
2026-06-19 09:02:57 +02:00
sideshowbarker
c96dec10e3 Meta: Update ICU to 78.3 by bumping the vcpkg baseline
Bump the pinned ICU version from 78.2 to 78.3 — the current release — so
the build works on systems that already ship 78.3. And bump our vcpkg
baseline — because 78.3 is newer than our existing baseline. And pin
freetype to 2.13.3 — because the baseline update otherwise pulls in
2.14.3, which has font-rendering changes that break our layout tests.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/10145
2026-06-19 08:59:16 +02:00
Aliaksandr Kalenik
48874609f4 LibIPC: Inline small Mach IPC message bodies
The Mach transport always sent the serialized IPC bytes as an
out-of-line descriptor. That asks Mach to transfer the payload through a
VM region even when the message is only a small control message.

Use a second data message ID for inline bodies whose full Mach message
fits within 4 KiB. Inline messages carry the unpadded payload length
before the serialized bytes so the receiver can ignore Mach message-size
padding, while larger messages keep using the existing out-of-line
descriptor path.
2026-06-19 02:44:35 +02:00
Andreas Kling
bfcb51cfc3 LibWeb: Collect ancestor hashes from subject selector lists
When :is() or :where() appears in the subject compound, collect hashes
from ancestor compounds inside its argument selectors. Keep only hashes
shared by every alternative, and do not treat the argument selector
subject as an ancestor.
2026-06-19 01:40:49 +02:00
Andreas Kling
0b2a5ac143 LibWeb: Salt ancestor filter hashes by selector component
Separate ancestor filter hashes for tag names, ids, classes, and
attributes. This avoids false positives where identical strings in
different selector component kinds satisfy each other, while keeping the
filter conservative.
2026-06-19 01:40:49 +02:00
Andreas Kling
bc5d153e60 LibWeb: Improve ancestor hashes for selector-list pseudo-classes
Collect hashes from :is() and :where() selector lists by keeping only
hashes present in every alternative. This lets the ancestor filter
reject more selectors without changing matching semantics.
2026-06-19 01:40:49 +02:00
Andreas Kling
8d85a17527 LibWeb: Extract ancestor hashes from :is() and :where()
Look through single-argument :is() and :where() pseudo-classes when
collecting ancestor-filter hashes. Reuse hashes from the rightmost
compound of the argument selector, including nested wrappers, because
that compound matches the same ancestor element.

Keep selector lists with multiple alternatives conservative, since no
single hash is mandatory for every branch.
2026-06-19 01:40:49 +02:00
Andreas Kling
bc201e3257 LibWeb: Bucket more :is() and :where() rules
Look through single-argument :is() and :where() selectors when
selecting a rule-cache bucket. Use mandatory ids, classes, tag names
or attributes from the rightmost compound of the argument selector,
including nested :is() and :where() wrappers.

Leave multi-argument lists in the broad bucket, since a single key
would not be mandatory for every alternative.
2026-06-19 01:40:49 +02:00
Andreas Kling
b7a290cbe2 LibWeb: Keep pseudo-element rules in pseudo buckets
Keep pseudo-element style rules out of the normal element rule buckets
while preserving the same id, class, tag, attribute and root buckets
inside each known pseudo-element type. This avoids collecting pseudo
rules for normal element style, without broadening pseudo style
collection to every rule targeting the queried pseudo-element.

Update the has invalidator to walk both the normal rule buckets and
the pseudo-element bucket maps when deciding whether pending :has()
mutations may affect style.
2026-06-19 01:40:49 +02:00
Aliaksandr Kalenik
a08734ecbc LibGfx+LibWeb+Compositor+WebContent: Commit 2D canvas flushes atomically
2D canvas contexts started publishing partial frames after canvas
rasterization moved into the Compositor. WebContent still splits large
recorded command lists after 64 commands, but every split batch was sent
through the same compositor path as the end-of-frame flush. The
compositor replayed each batch into the DrawCanvas source surface,
so a pending present could sample a canvas after clear and before the
rest of the next frame had been drawn. Canvas-heavy pages such as
slither.com then flickered between partial and complete frames.

Carry an explicit commit bit with 2D canvas command updates. Non-commit
batches now update a hidden working canvas in the Compositor, while the
display-list-visible surface keeps the last committed canvas contents.
The end-of-frame canvas preparation sends the commit boundary, including
the empty-commit case needed when the auto-flush consumed all recorded
commands before prepare_for_compositing() runs.
2026-06-19 00:01:26 +02:00
Sam Atkins
cb88229c3f LibDevTools: Handle fragmented protocol packets
Firefox can split a DevTools protocol packet across multiple TCP
reads. The previous reader only checked that some data was available,
then tried to synchronously read the whole length-prefixed packet from
the readiness callback. Once the socket was nonblocking this could make
startup flaky when Firefox opened the inspector.

Buffer incoming bytes instead, and only dispatch messages once a full
length-prefixed JSON payload has arrived. Add a protocol test that sends
a request in two fragments through the real DevTools server.
2026-06-18 22:53:30 +02:00
Andreas Kling
2ca74acc3d LibWeb: Store small invalidation sets inline
Most invalidation sets carry at most one selector feature. Storing
every set in a HashTable pays allocation and hashing costs while
constructing style invalidation data, even in the common case.

Store the first property inline and upgrade to HashTable only when a
second distinct property is inserted. Keep hash and equality checks
direct over the backing so those hot paths do not route through the
public callback iterator.
2026-06-18 22:53:13 +02:00
sideshowbarker
13b609133d CI: Add wasm-tools to the build image
wasm-tools is needed at build time to generate the WebAssembly spec
tests (INCLUDE_WASM_SPEC_TESTS), and the setup action downloads it from
the bytecodealliance releases CDN for every build job. That CDN
intermittently returns 504, which fails otherwise-green CI runs.

Bake the pinned wasm-tools 1.243.0 into the ladybird-ci image so the
Linux container jobs, which are the bulk of the build matrix, get it
from the image instead of fetching it per run.

A follow-up will drop the per-job download for the container platforms
once this image is published. The macOS and Windows jobs run on native
runners that do not use this image, so they keep downloading the same
pinned version.
2026-06-18 22:44:40 +02:00
sideshowbarker
1484686c70 CI: Add caching and retries to the wasm-tools download
Cache the wasm-tools binary rather than doing (trying) a re-fetch of it
on every build job. And when we ever do need to re-download it (after a
cache miss), then do it with some sensible retry-with-backoff-and-wait.

Otherwise, a single network hiccup when trying to download wasm-tools
was failing multiple CI jobs at once — before their builds even started.
2026-06-18 22:44:40 +02:00
Jelle Raaijmakers
d819152b4e LibGfx+LibWeb: Preserve text color for selections
Selecting text without custom ::selection styling changed the
foreground color of the selected content. This was especially visible
for links, where the text changed color but the underline did not.

The default selection style supplied both a selection background and a
foreground color from the palette or HighlightText system color. That
made ordinary selections behave as if the page had explicitly styled
::selection color.

Only provide a default selection background, so selected content keeps
its own foreground color unless CSS overrides it. Remove the now-unused
SelectionText palette role.
2026-06-18 22:43:26 +02:00
Tim Ledbetter
91d3d135eb LibWeb: Paint emoji glyph text-shadows in the shadow color 2026-06-18 22:42:29 +02:00
Andreas Kling
86e0e281a0 LibWeb: Avoid unnecessary pseudo-element style recomputation
Track the synthetic pseudo-elements that matched while computing an
originating element's normal style. Store the transient match set as a
bitfield, then copy those bits into ComputedProperties. Use them during
style invalidation to skip pseudo style recomputation when neither the
old nor new originating style matched pseudo rules and no pseudo style
already exists.

This shaves roughly 500 ms off loading the Ladybird GitHub repository.

Materialize synthetic pseudo styles on demand for CSSOM reads so
getComputedStyle(element, "::before") still computes skipped styles when
script asks for them. Add coverage for a universal pseudo selector, and
update style invalidation counter expectations for the reduced work.
2026-06-18 19:50:34 +02:00
Tim Ledbetter
340ef361d8 LibWeb: Support anchor() in calc() trees
Previously, `anchor()`  was only resolved when it appeared bare in an
inset property. We now allow it to appear anywhere inside a `calc()`
tree.
2026-06-18 17:36:56 +01:00
Tim Ledbetter
b62a099e91 LibWeb: Serialize a non-math function at the root of a calc() tree
Previously, math function serialization assumed the calculation tree
root was a numeric value or a calc-operator node, and otherwise emitted
the root's name followed by its comma-separated children.
A non-math function node such as `sibling-index()` or `anchor()` has no
children, so a `calc()` whose entire contents was such a function
serialized to an empty "calc()". We now serialize the function directly
instead.
2026-06-18 17:36:56 +01:00
Tim Ledbetter
e4a5957bc6 LibWeb: Only allow anchor() values in inset properties 2026-06-18 17:36:56 +01:00
Tim Ledbetter
c1100a7c73 LibWeb: Simplify property validity check in parse_anchor_size() 2026-06-18 17:36:56 +01:00
Tim Ledbetter
d9fac87e8a LibWeb: Use correct spec link for anchor() 2026-06-18 17:36:56 +01:00
Andreas Kling
849d528220 LibWeb: Build style invalidation data lazily
Split StyleCache's rule matching data from its invalidation metadata.
Allow callers to build either payload independently. Style invalidation
queries no longer force a full rule cache rebuild, and rule matching
no longer builds invalidation metadata as a side effect.

Previously, callers often treated an absent rule cache as proof that no
style invalidation metadata existed. That made some invalidation paths
do nothing until something else had populated the rule cache first.
Build invalidation data before reading it instead, so these paths use
the metadata whenever stylesheet rules require it.

Rebaseline style invalidation counter expectations for the new lazy
build points. Flush setup style work in the structural :has() feature
filter test before measuring each mutation, so the recomputation
counters describe the mutation itself instead of leftover setup work.
2026-06-18 15:45:12 +02:00
Jelle Raaijmakers
d8a55dad1c LibWeb: Target :active and :open invalidation
Changing :active or :open used the broad style invalidation path, so
large subtrees were recomputed even when only the target element and
selector-matched relatives could be affected.

Reuse the :has() feature collector to keep conservative fallback for
observable :has() cases, then use pseudo-class property invalidation
for the common targeted path.
2026-06-18 13:42:51 +02:00
sideshowbarker
4bbc5e0950 LibWeb: Fix crash from SVG resource boxes outliving removed element
Problem: Crash when removing a <mask>, <clipPath>, or <pattern> element
that’s referenced via url(#id), and then GC’ing it.

Cause: <mask>, <clipPath>, and <pattern> are laid out as resource boxes
attached to the referencing element's layout subtree, rather than their
own. So those survive cleanup of their DOM ancestor. Once a removed
<mask>/<clipPath>/<pattern> is collected, its resource box’s weak DOM
node pointer is null. And dereferencing that trips an assert — both
while painting and while tearing down the layout tree.

Fix: When a <mask>, <clipPath>, or <pattern> is removed, request a full
layout-tree update while the element’s still alive. That drops the stale
resource boxes (whose url(#id) references no longer resolve) before the
node gets collected.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/10127
2026-06-18 13:35:32 +02:00
Andreas Kling
66f313fe48 LibWeb: Preserve parsed user style sheets
Keep regular rule cache invalidation from discarding the parsed user
style sheet. User style and content blocker source changes now use an
explicit invalidation path that clears the parsed sheet before the rule
cache is rebuilt.

This avoids reparsing user CSS for unrelated style changes, which was
very annoying when browsing with cosmetic CSS from content blockers.
2026-06-18 13:27:39 +02:00
Andreas Kling
4daec8f6e0 LibWeb: Use Event storage for MouseEvent relatedTarget
Store MouseEvent's relatedTarget in the inherited Event field instead of
keeping a second slot on MouseEvent.

Event dispatch retargets and updates the inherited field while building
the event path. The second slot left JS listeners observing stale or
null relatedTarget values during mouse and pointer boundary events.

Add coverage for boundary events between sibling elements.
2026-06-18 12:40:37 +02:00
Callum Law
8ebdd6d41e LibWeb: Schedule rendering update on AVC only style change
b583fd skipped display list invalidation for AVC only style changes
which also meant that we no longer marked the navigable as needing a
repaint or requested the next frame.

This commit updates `set_needs_accumulated_visual_contexts_update` to do
so.

This makes the animation when hovering icons on
https://chrede88.github.io/L1nkr paint intermediate frames not just the
first and last.
2026-06-18 12:26:22 +02:00
Callum Law
64f866cae2 LibWeb: Support number/percentage interpolation for scale
Previously we didn't support interpolating component values of `scale`
from a number to a percentage (or vice versa). This also caused
interpolation from `none` to a percentage value to fail since the
fallback value is number based.

This makes the transition run when hovering buttons on
https://chrede88.github.io/L1nkr/ rather than being discrete.
2026-06-18 12:26:22 +02:00
Callum Law
2c6aa4d272 LibWeb: Apply null transform properties on style recomputation
When applying style in `Layout::Node::apply_style` we previously ignored
null `rotate`, `translate`, and `scale` values which left the old values
in place in the case of nonnull -> null changes.

Fixes #10125
2026-06-18 12:26:22 +02:00
Sam Atkins
147d4595c6 LibWebView: Restore RFC cookie storage behavior
In 11b053b154 I accidentally changed the
behaviour of CookieJar::set_cookie() to not match what the RFC
requires, particularly when dealing with too-long paths. This commit
restores the original behaviour, now that the validation required by
DevTools happens elsewhere, before set_cookie() is called.
2026-06-18 11:37:36 +02:00
Sam Atkins
953251351d LibHTTP: Validate direct cookie conversion
DevTools edits cookies as concrete fields rather than Set-Cookie
strings. Validate direct Cookie objects while converting them back to
ParsedCookie so invalid edits can be reported without making the RFC
storage algorithm stricter.
2026-06-18 11:37:36 +02:00
Sam Atkins
680dc78dac LibHTTP: Reuse cookie domain attribute parsing
The Cookie to ParsedCookie conversion stripped a leading dot and
lowercased the cookie domain itself. Use the existing Domain attribute
parser instead, so edited cookies follow the same ASCII validation and
normalization as Set-Cookie parsing.
2026-06-18 11:37:36 +02:00