Header Gradient Blobs

This Month in Ladybird
February 2025

It’s been a short but productive month for the Ladybird project! We’ve merged 281 PRs from 35 contributors. Let’s take a look at some of the highlights!

Welcoming new sponsors

Ladybird is fully funded through the generous support of companies and individuals who believe in the open web. This month, we’re excited to welcome the following new sponsors:

We are incredibly grateful for their support! If you’re interested in sponsoring, contact us.

Web Platform Tests (WPT)

We’ve continued making improvements in WPT compliance: 9,836 more passing subtests than last month! This brings our total to 1,773,799 .

The low-hanging fruit is exhausted at this point, but the upward grind must continue!

Here’s the last month’s progress for all browsers:

Let’s also zoom out and take a look at overall WPT progress since we started tracking it back in August of 2024:

The dashed green line is Apple’s required 90% pass rate for eligibility as an alternative browser engine on iOS. That’s our next target. After that, the 3 major engines await…

Waiting for CSS to download before rendering

We now delay the initial rendering of pages until we’ve loaded all the CSS referenced by <link> elements. This is an important part of preventing FOUC (flash of unstyled content).

Pictured below are 3 stages of loading our GitHub repo in Ladybird while CSS is downloading. Before, we would render the first two stages. With these new changes, we hold off until we have enough to show you the final stage directly.

OpenSSL adoption

The work on moving off of our own home-grown cryptography library and onto the battle-tested OpenSSL goes on. This month, we’ve ported the following features to OpenSSL and removed our own implementations:

  • TLS 1.2
  • HKDF
  • PBKDF2
  • Curve25519
  • Ed25519
  • Ed448
  • X25519
  • X448

curl adoption

We’ve also continued migrating our networking stack to curl. The latest piece of functionality to move onto curl is our WebSockets implementation.

Note that there are some features that curl’s WebSocket backend doesn’t support, such as per-message compression and WebSockets over HTTP/2.

Firefox DevTools protocol support

We’re working on making it possible to use Firefox’s DevTools suite with Ladybird.

DevTools are not only vital to web development, but also crucial for browser developers to investigate websites that don’t yet work correctly.

Ladybird already had its own home-grown debug tooling, but by adding support for Firefox’s DevTools protocol, we gain access to sophisticated tools very quickly.

We’ve only just begun this work, but we can already inspect a page’s layout and style, and interact with the document from the DevTools console!

CSS image cursors

We now support custom images in the CSS cursor property, a rarely used but pretty fun feature!

New CSS pseudo-classes

We added a couple of new pseudo-classes this month:

  • :valid
  • :invalid
  • :user-valid
  • :user-invalid

These all apply to input elements that have valid or invalid values. They are commonly used to highlight form elements that need correcting.

Furthermore, :open now matches any input element that has a picker open. This is currently relevant for <input type="color"> and <input type="file">.

Text decorations for errors

We added support for text-decoration: spelling-error and text-decoration: grammar-error, which mimic the underlines you see in typical word processors.

TextEncoderStream

We’ve implemented the streaming version of TextEncoder, which converts the input to UTF-8 bytes. This is used by the server-side rendering mode of React Router, which is used by ChatGPT:

Resource Timing

We’ve implemented the Resource Timing API, which allows a website to get timing information about the network resources it requests. This was implemented as part of an initiative to support Cloudflare Turnstile, an anti-bot solution.

Resource Timing is also used by monitoring tools such as Sentry:

Constraint validation API

We’ve started to implement the Constraint Validation API. This prevents a form from being submitted if it contains invalid data.

Currently, we have implemented the required attribute, which checks that the element has a value, and the pattern attribute, which checks that the element’s value matches the given regular expression.

The inert attribute

We now support the inert attribute, which can be added to any element to make it non-interactive, non-focusable, and non-findable. This is useful for modals, popups, and other content that should not be interacted with.

Style invalidation optimizations

We’ve made several incremental optimizations to reduce unnecessary style recalculations.

The most significant change is that the presence of :has() selectors no longer triggers a full-page recalculation. Instead, only the relevant ancestor elements are updated, making the process much more efficient in the worst case.

aarch64 Linux continuous integration

We’ve been using GitHub Actions for PR testing for a long time, but we only had x86_64 Linux and aarch64 macOS runners.

This month, we took advantage of GitHub’s new public aarch64 Linux runners to add a nightly aarch64 Linux job. Adding the job required fixing some rough edges in aarch64 Linux support.

Credits

We’d like to thank everyone who contributed code this month:

Aliaksandr Kalenik, Alice Lee, Andreas Kling, Andrew Kaster, aplefull, AppleFlavored, David Hewitt, devgianlu, Felipe Muñoz Mazur, Francesco Gazzetta, Gingeh, Glenn Skrzypczak, InvalidUsernameException, Jaycadox, Jelle Raaijmakers, Jess, jg99, Kenneth Myhra, Lucas CHOLLET, Luke Warlow, Luke Wilde, Mehran Kamal, mikiubo, Piotr, Psychpsyo, R-Goc, rmg-x, Sam Atkins, Shannon Booth, sideshowbarker, stasoid, Tim Ledbetter, Timothy Flynn, Undefine, zoupingshi