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:
- Shopify (renewed sponsorship)
- Proton, with $50,000 (raised with the help of their community and a matching donation from Proton VPN)
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