This Month in Ladybird: October 2026
This Month in Ladybird: October 2026
Ladybird Newsletter · November 5, 2026
Did someone forward you this? Subscribe to this newsletter.
Hello friends! In October, we moved style and layout off the main thread, built a JavaScript JIT, replaced our WebAssembly engine, redesigned the browser UI, and passed Safari Technology Preview on Web Platform Tests. :^)
Sponsors
Ladybird is entirely funded by companies and individuals who believe in the open web. You can see everyone supporting the project on our sponsors page, and we're grateful to all of them. If you're interested in sponsoring, please contact us.
Style and layout no longer wait for JavaScript
Browsers normally run JavaScript, style, and layout on one main thread, one at a time. While a script runs, the page can't update. A few simple animations can keep going on the compositor, but everything else has to wait.
We moved style and layout to their own thread, and paint recording to another (#12377, #12400). They now run at the same time as JavaScript (#12396, #12432, #12460). If a script asks for layout information, like an element's size, it waits until pending layout work is finished, so it never gets stale data.
So two things now work during a long script:
- CSS animations keep running while JavaScript is busy. This includes animations that change layout, like width and font-size (#12433, #12447, #12451).
- :hover keeps working while JavaScript is busy. The render thread finds the element under the mouse, applies its hover styles, starts any transitions, updates the cursor, and draws a new frame. When the script ends, the main thread catches up and fires the hover events (#12530).
As far as we know, no other browser can do this today. Here's a text animation while JavaScript blocks the main thread in 1.5 second bursts, with Ladybird in the top left:
And here's :hover on a page running JavaScript for 250ms at a time, with Ladybird on the left and Chrome on the right:
A JavaScript JIT
On Linux and macOS, LibJS now compiles hot JavaScript to machine code, on both x86-64 and AArch64 (#12613).
We decided against a JIT in the past, and did what we could to push and tune the interpreter instead. It's already competitive, so making it twice as fast would be a huge effort, and that would only turn a 300ms hang into a 150ms hang, which you'd still notice. So we needed an optimizing JIT.
The design is deliberately boring: speculative optimization based on runtime type profiling, like other JavaScript engines. For now, we just want to go reasonably fast.
While code warms up, we record things like which types and object shapes it sees (#12588). The compiled code uses those recordings to make guesses, like "this value is always an integer", and inlines small functions (#12595, #12598).
To find bugs during development, we used a fuzzer that ran the same code in the JIT and the interpreter and compared the results (#12601).
A new WebAssembly engine
We replaced our C++ Wasm engine and Cranelift with a new engine that has its own interpreter and JIT (#12963). It supports newer parts of WebAssembly that the old engine didn't, like exception handling and GC. On the JetStream 3 Wasm workloads both engines can run, it scores about 7x higher.
In July, we built flap, a small language and compiler for writing LibJS's interpreter. The Wasm interpreter is written in flap too, so one source builds it for x86-64, AArch64, and Windows x64. Hot functions move from there to the JIT, even in the middle of a running loop.
We're making great progress on performance. JSLinux, an x86 PC emulator, now boots Alpine Linux to a shell in 1.8 seconds, while Chrome takes 1.5.
Benchmarks
Web Platform Tests (WPT)
On October 26, we passed Safari Technology Preview on WPT. :^) We ended the month at 2,184,722 subtests, a gain of 75,650.
Most of that gain came in five days, from about 2.12 million on October 22 to about 2.18 million on October 27. We pointed AI coding agents at WPT and asked them to fill in missing functionality. They made lots of small fixes, and those added up. Our biggest gains for the month were about 30,000 in /css and 10,000 in /editing.
A new browser UI
Until now, our UI had grown organically, with tinkering here and there. This was the first time we sat down and mapped out a complete design. We kept it modest and quiet, so the attention stays on the page.
It covers tabs, toolbars, menus, and our own about: pages on macOS and Linux, in light, dark, and a violet dark theme for private windows (#13271, #13169, #12815).
- Tabs: you can pin tabs, search all open tabs, and restore your windows on launch (#12757, #13271).
- Form controls got a new look, and date and time inputs got a picker (#13554).
- Scrolling: smooth mouse wheel scrolling (#12593), elastic overscroll on macOS (#12624), touchpad momentum on other platforms (#12345), and scrollbars that hide until used (#12997).
Sites that work better
- Google Slides: presentations open instead of showing an error (#12497).
- GitHub: Mermaid diagrams render (#12383).
- ChatGPT: the text box grows as you type (#13050).
- nytimes.com and reuters.com get past their bot checks (#12718, #12188).
- Instagram: videos show their first frame instead of staying blank (#12898).
- Gmail: reloading no longer keeps the old page in memory (#12689, #12660).
- x86CSS, an x86 emulator made of CSS, is now usable (#12911).
New browser features
- Screen readers: we've added first support for VoiceOver on macOS and Orca on Linux (#9156). There's still a lot of work to do here.
- Spell checking in text fields on macOS (#12638).
- Picture-in-Picture (#12542).
- Links to text: links can scroll to a piece of text and highlight it, and you can create them from the context menu (#11121, #12744).
- Permissions: sites can now ask for your location and microphone (#13336, #12604).
- DevTools: Inspect Element (#13348), console autocomplete (#13355), and expandable objects in the console (#13360).
- Smaller additions: Find in page can highlight all matches (#12434), ad blocking can be turned off per site from the toolbar (#12695), and we added Reload Without Cache (#13056).
More of the web platform
We rendered this page in Ladybird, using features that landed in October:
From the top left, that's multi-column (#13026), display: grid-lanes for masonry (#13236), MathML (#13062, #13141), corner-shape (#12942), CSS Motion Path (#13027), much more of anchor positioning (#13021, #13079, #13166), and text-wrap: balance (#13461).
We also added:
- CSS: calc-size(), which lets heights animate to and from auto (#13006), plus vertical writing modes (#13103), zoom (#13237), the stretch sizing keyword (#13006), shape() and border-shape (#12942), field-sizing (#13050), view progress timelines and animation-range (#12943), and the start of SVG animation (#12823, #13498).
- Web APIs and more: the HTML Sanitizer API (#13185), Touch Events (#13249), Cross-Origin-Opener-Policy (#12296), Paint Timing, Event Timing, Largest Contentful Paint (#13110), WebVTT cues (#12895), wide-gamut canvases (#13097), WebDriver BiDi (#13167), JavaScript's using and await using (#13102), and many execCommand and contenteditable fixes (#13186, #13038).
Security and process isolation
Web pages run in sandboxed renderer processes, so a malicious page that takes over its renderer should be stuck there.
We kept fixing security issues from many sources, including ways around that sandbox. For example, a compromised renderer could ask the browser process to open any file on your computer. Now only a renderer showing local files can read them (#12582, #12590). Renderers could also fake a user click to open popups or read the clipboard. The browser process no longer trusts them on this (#12597).
We also split the browser into more processes, so a compromised one can reach less:
- Cross-site iframes get their own renderer by default (#12647), and so do cross-site popups (#12296).
- Each top-level site gets its own network process, and the HTTP cache and third-party cookies are kept separate per site (#13144, #12424).
- Each renderer has its own audio process (#12604) and image decoder (#12437).
Media and Windows
On Windows, video now plays and YouTube works (#12646, #13195). Hardware video decoding moved to its own process and now works on Linux through Vulkan (#12868). We also read MP4 files ourselves now instead of using FFmpeg, which fixes problems with seeking and buffering (#12641).
More C++ moved to Rust
LibJS's runtime moved from C++ to Rust just before the JIT landed, so our JavaScript engine is now all Rust, apart from its flap interpreter and the garbage collector (#12492). The new Wasm engine is Rust as well. WebGL, 2D canvas, IndexedDB, Streams, and URL also moved over (#12699, #12935, #13287, #13083, #12998). We also deleted the C++ style computation, so style is now computed entirely in Rust (#12346).
Getting ready for alpha
Our first alpha is planned for later this year. This month we added:
- Release builds: macOS archives, Linux tarballs, .deb and .rpm packages, and Flatpak bundles (#13176, #13313, #13340).
- Crash reports: after a crash, you can review a report and choose to send it to us (#12298, #12342).
- A welcome page to pick your tab layout, search engine, and ad blocking (#12333).
- Reporting broken sites from inside the browser (#12880).
That's it for October. Thanks for reading, and we'll see you next month!
Powered by Buttondown
#12377: ladybird#12377
#12400: ladybird#12400
#12396: ladybird#12396
#12432: ladybird#12432
#12460: ladybird#12460
#12433: ladybird#12433
#12447: ladybird#12447
#12451: ladybird#12451
#12530: ladybird#12530
#12613: ladybird#12613
#12588: ladybird#12588
#12595: ladybird#12595
#12598: ladybird#12598
#12601: ladybird#12601
#12963: ladybird#12963
#13271: ladybird#13271
#13169: ladybird#13169
#12815: ladybird#12815
#12757: ladybird#12757
#13554: ladybird#13554
#12593: ladybird#12593
#12624: ladybird#12624
#12345: ladybird#12345
#12997: ladybird#12997
#12497: ladybird#12497
#12383: ladybird#12383
#13050: ladybird#13050
#12718: ladybird#12718
#12188: ladybird#12188
#12898: ladybird#12898
#12689: ladybird#12689
#12660: ladybird#12660
#12911: ladybird#12911
#9156: ladybird#9156
#12638: ladybird#12638
#12542: ladybird#12542
#11121: ladybird#11121
#12744: ladybird#12744
#13336: ladybird#13336
#12604: ladybird#12604
#13348: ladybird#13348
#13355: ladybird#13355
#13360: ladybird#13360
#12434: ladybird#12434
#12695: ladybird#12695
#13056: ladybird#13056
#13026: ladybird#13026
#13236: ladybird#13236
#13062: ladybird#13062
#13141: ladybird#13141
#12942: ladybird#12942
#13027: ladybird#13027
#13021: ladybird#13021
#13079: ladybird#13079
#13166: ladybird#13166
#13461: ladybird#13461
#13006: ladybird#13006
#13103: ladybird#13103
#13237: ladybird#13237
#12943: ladybird#12943
#12823: ladybird#12823
#13498: ladybird#13498
#13185: ladybird#13185
#13249: ladybird#13249
#12296: ladybird#12296
#13110: ladybird#13110
#12895: ladybird#12895
#13097: ladybird#13097
#13167: ladybird#13167
#13102: ladybird#13102
#13186: ladybird#13186
#13038: ladybird#13038
#12582: ladybird#12582
#12590: ladybird#12590
#12597: ladybird#12597
#12647: ladybird#12647
#13144: ladybird#13144
#12424: ladybird#12424
#12437: ladybird#12437
#12646: ladybird#12646
#13195: ladybird#13195
#12868: ladybird#12868
#12641: ladybird#12641
#12492: ladybird#12492
#12699: ladybird#12699
#12935: ladybird#12935
#13287: ladybird#13287
#13083: ladybird#13083
#12998: ladybird#12998
#12346: ladybird#12346
#13176: ladybird#13176
#13313: ladybird#13313
#13340: ladybird#13340
#12298: ladybird#12298
Mentions
If you run into regressions like this, please report an issue on github.com/LadybirdBrowser/ladybird/issues. Alternatively, in the Help menu, there's a "Report website issue" button. That said, Google Maps is working well for me today. Widgets all appear, I can search, etc. Perhaps there's a platform issue at hand, or something that was recently fixed. Here is a screenshot of my search for Yosemite just now: i.imgur.com
This Month in Ladybird: October 2026 This Month in Ladybird: October 2026 Ladybird Newsletter · November 5, 2026 Did someone forward you this? Subscribe to this newsletter. Hello friends! In October, we moved style and layout off the main thread, built a JavaScript JIT, replaced our WebAssembly engine, redesigned the browser UI, and passed Safari Technology Preview on Web Platform Tests. :^) Sponsors Ladybird is entirely funded by companies and individuals who believe in the open web. You can see everyone supporting the project on our sponsors page, and we're grateful to all of them. If you're interested in sponsoring, please contact us. Style and layout no longer wait for JavaScript Browsers normally run JavaScript, style, and layout on one main thread, one at a time. While a script runs, the page can't update. A few simple animations can keep going on the compositor, but everything else has to wait. We moved style and layout to their own thread, and paint recording to another (#12377, #12400). They now run at the same time as JavaScript (#12396, #12432, #12460). If a script asks for layout information, like an element's size, it waits until pending layout work is finished, so it never gets stale data. So two things now work during a long script: - CSS animations keep running while JavaScript is busy. This includes animations that change layout, like width and font-size (#12433, #12447, #12451). - :hover keeps working while JavaScript is busy. The render thread finds the element under the mouse, applies its hover styles, starts any transitions, updates the cursor, and draws a new frame. When the script ends, the main thread catches up and fires the hover events (#12530). As far as we know, no other browser can do this today. Here's a text animation while JavaScript blocks the main thread in 1.5 second bursts, with Ladybird in the top left: And here's :hover on a page running JavaScript for 250ms at a time, with Ladybird on the left and Chrome on the right: A JavaScript JIT On Linux and macOS, LibJS now compiles hot JavaScript to machine code, on both x86-64 and AArch64 (#12613). We decided against a JIT in the past, and did what we could to push and tune the interpreter instead. It's already competitive, so making it twice as fast would be a huge effort, and that would only turn a 300ms hang into a 150ms hang, which you'd still notice. So we needed an optimizing JIT. The design is deliberately boring: speculative optimization based on runtime type profiling, like other JavaScript engines. For now, we just want to go reasonably fast. While code warms up, we record things like which types and object shapes it sees (#12588). The compiled code uses those recordings to make guesses, like "this value is always an integer", and inlines small functions (#12595, #12598). To find bugs during development, we used a fuzzer that ran the same code in the JIT and the interpreter and compared the results (#12601). A new WebAssembly engine We replaced our C++ Wasm engine and Cranelift with a new engine that has its own interpreter and JIT (#12963). It supports newer parts of WebAssembly that the old engine didn't, like exception handling and GC. On the JetStream 3 Wasm workloads both engines can run, it scores about 7x higher. In July, we built flap, a small language and compiler for writing LibJS's interpreter. The Wasm interpreter is written in flap too, so one source builds it for x86-64, AArch64, and Windows x64. Hot functions move from there to the JIT, even in the middle of a running loop. We're making great progress on performance. JSLinux, an x86 PC emulator, now boots Alpine Linux to a shell in 1.8 seconds, while Chrome takes 1.5. Benchmarks Web Platform Tests (WPT) On October 26, we passed Safari Technology Preview on WPT. :^) We ended the month at 2,184,722 subtests, a gain of 75,650. Most of that gain came in five days, from about 2.12 million on October 22 to about 2.18 million on October 27. We pointed AI coding agents at WPT and asked them to fill in missing functionality. They made lots of small fixes, and those added up. Our biggest gains for the month were about 30,000 in /css and 10,000 in /editing. A new browser UI Until now, our UI had grown organically, with tinkering here and there. This was the first time we sat down and mapped out a complete design. We kept it modest and quiet, so the attention stays on the page. It covers tabs, toolbars, menus, and our own about: pages on macOS and Linux, in light, dark, and a violet dark theme for private windows (#13271, #13169, #12815). - Tabs: you can pin tabs, search all open tabs, and restore your windows on launch (#12757, #13271). - Form controls got a new look, and date and time inputs got a picker (#13554). - Scrolling: smooth mouse wheel scrolling (#12593), elastic overscroll on macOS (#12624), touchpad momentum on other platforms (#12345), and scrollbars that hide until used (#12997). Sites that work better - Google Slides: presentations open instead of showing an error (#12497). - GitHub: Mermaid diagrams render (#12383). - ChatGPT: the text box grows as you type (#13050). - nytimes.com and reuters.com get past their bot checks (#12718, #12188). - Instagram: videos show their first frame instead of staying blank (#12898). - Gmail: reloading no longer keeps the old page in memory (#12689, #12660). - x86CSS, an x86 emulator made of CSS, is now usable (#12911). New browser features - Screen readers: we've added first support for VoiceOver on macOS and Orca on Linux (#9156). There's still a lot of work to do here. - Spell checking in text fields on macOS (#12638). - Picture-in-Picture (#12542). - Links to text: links can scroll to a piece of text and highlight it, and you can create them from the context menu (#11121, #12744). - Permissions: sites can now ask for your location and microphone (#13336, #12604). - DevTools: Inspect Element (#13348), console autocomplete (#13355), and expandable objects in the console (#13360). - Smaller additions: Find in page can highlight all matches (#12434), ad blocking can be turned off per site from the toolbar (#12695), and we added Reload Without Cache (#13056). More of the web platform We rendered this page in Ladybird, using features that landed in October: From the top left, that's multi-column (#13026), display: grid-lanes for masonry (#13236), MathML (#13062, #13141), corner-shape (#12942), CSS Motion Path (#13027), much more of anchor positioning (#13021, #13079, #13166), and text-wrap: balance (#13461). We also added: - CSS: calc-size(), which lets heights animate to and from auto (#13006), plus vertical writing modes (#13103), zoom (#13237), the stretch sizing keyword (#13006), shape() and border-shape (#12942), field-sizing (#13050), view progress timelines and animation-range (#12943), and the start of SVG animation (#12823, #13498). - Web APIs and more: the HTML Sanitizer API (#13185), Touch Events (#13249), Cross-Origin-Opener-Policy (#12296), Paint Timing, Event Timing, Largest Contentful Paint (#13110), WebVTT cues (#12895), wide-gamut canvases (#13097), WebDriver BiDi (#13167), JavaScript's using and await using (#13102), and many execCommand and contenteditable fixes (#13186, #13038). Security and process isolation Web pages run in sandboxed renderer processes, so a malicious page that takes over its renderer should be stuck there. We kept fixing security issues from many sources, including ways around that sandbox. For example, a compromised renderer could ask the browser process to open any file on your computer. Now only a renderer showing local files can read them (#12582, #12590). Renderers could also fake a user click to open popups or read the clipboard. The browser process no longer trusts them on this (#12597). We also split the browser into more processes, so a compromised one can reach less: - Cross-site iframes get their own renderer by default (#12647), and so do cross-site popups (#12296). - Each top-level site gets its own network process, and the HTTP cache and third-party cookies are kept separate per site (#13144, #12424). - Each renderer has its own audio process (#12604) and image decoder (#12437). Media and Windows On Windows, video now plays and YouTube works (#12646, #13195). Hardware video decoding moved to its own process and now works on Linux through Vulkan (#12868). We also read MP4 files ourselves now instead of using FFmpeg, which fixes problems with seeking and buffering (#12641). More C++ moved to Rust LibJS's runtime moved from C++ to Rust just before the JIT landed, so our JavaScript engine is now all Rust, apart from its flap interpreter and the garbage collector (#12492). The new Wasm engine is Rust as well. WebGL, 2D canvas, IndexedDB, Streams, and URL also moved over (#12699, #12935, #13287, #13083, #12998). We also deleted the C++ style computation, so style is now computed entirely in Rust (#12346). Getting ready for alpha Our first alpha is planned for later this year. This month we added: - Release builds: macOS archives, Linux tarballs, .deb and .rpm packages, and Flatpak bundles (#13176, #13313, #13340). - Crash reports: after a crash, you can review a report and choose to send it to us (#12298, #12342). - A welcome page to pick your tab layout, search engine, and ad blocking (#12333). - Reporting broken sites from inside the browser (#12880). That's it for October. Thanks for reading, and we'll see you next month! Powered by Buttondown #12377: ladybird#12377 #12400: ladybird#12400 #12396: ladybird#12396 #12432: ladybird#12432 #12460: ladybird#12460 #12433: ladybird#12433 #12447: ladybird#12447 #12451: ladybird#12451 #12530: ladybird#12530 #12613: ladybird#12613 #12588: ladybird#12588 #12595: ladybird#12595 #12598: ladybird#12598 #12601: ladybird#12601 #12963: ladybird#12963 #13271: ladybird#13271 #13169: ladybird#13169 #12815: ladybird#12815 #12757: ladybird#12757 #13554: ladybird#13554 #12593: ladybird#12593 #12624: ladybird#12624 #12345: ladybird#12345 #12997: ladybird#12997 #12497: ladybird#12497 #12383: ladybird#12383 #13050: ladybird#13050 #12718: ladybird#12718 #12188: ladybird#12188 #12898: ladybird#12898 #12689: ladybird#12689 #12660: ladybird#12660 #12911: ladybird#12911 #9156: ladybird#9156 #12638: ladybird#12638 #12542: ladybird#12542 #11121: ladybird#11121 #12744: ladybird#12744 #13336: ladybird#13336 #12604: ladybird#12604 #13348: ladybird#13348 #13355: ladybird#13355 #13360: ladybird#13360 #12434: ladybird#12434 #12695: ladybird#12695 #13056: ladybird#13056 #13026: ladybird#13026 #13236: ladybird#13236 #13062: ladybird#13062 #13141: ladybird#13141 #12942: ladybird#12942 #13027: ladybird#13027 #13021: ladybird#13021 #13079: ladybird#13079 #13166: ladybird#13166 #13461: ladybird#13461 #13006: ladybird#13006 #13103: ladybird#13103 #13237: ladybird#13237 #12943: ladybird#12943 #12823: ladybird#12823 #13498: ladybird#13498 #13185: ladybird#13185 #13249: ladybird#13249 #12296: ladybird#12296 #13110: ladybird#13110 #12895: ladybird#12895 #13097: ladybird#13097 #13167: ladybird#13167 #13102: ladybird#13102 #13186: ladybird#13186 #13038: ladybird#13038 #12582: ladybird#12582 #12590: ladybird#12590 #12597: ladybird#12597 #12647: ladybird#12647 #13144: ladybird#13144 #12424: ladybird#12424 #12437: ladybird#12437 #12646: ladybird#12646 #13195: ladybird#13195 #12868: ladybird#12868 #12641: ladybird#12641 #12492: ladybird#12492 #12699: ladybird#12699 #12935: ladybird#12935 #13287: ladybird#13287 #13083: ladybird#13083 #12998: ladybird#12998 #12346: ladybird#12346 #13176: ladybird#13176 #13313: ladybird#13313 #13340: ladybird#13340 #12298: ladybird#12298
I have recently started to wonder whether we can really create a browser that can dethrone Google. Ladybird tries that, but Ladybird has made several really questionable decisions and has various strange policies. Now I am biased here since I was banned for "trolling" (I dispute that claim completely), but the issues go deeper. Take the following: ladybirdbrowser/ladybird Or rather: github.com/LadybirdBrowser/ladybird/blob/master/C… "We reserve the right to reject issues and other interactions that appear to be motivated by bad faith. Additionally, anyone found participating in social media brigading of Ladybird will be permanently banned from the project." Why does the Ladybird team engage in pro-actively banning people they disagree with? Does this not defeat the purpose of an open web if Ladybird goes about censoring people? And that's not the only issue here. A while ago they removed the ability, more or less, by people to report issues (or rather, contribute to the project) when they are outsiders. Or the "swift is great, we use it", then suddenly "Rust is great, we use it". A lot of this awkwardness has to do with Kling; I think it would be better if a browser would act in an agnostic manner rather than as a "brigading leads to perma-bans". That's a very user-hostile policy. Is it no longer possible to build a browser? You can't go about "we will dethrone chrome" while you pursue "brigaders will be perma-banned".
It's very easy to build it yourself if you want to try it right now. github.com/LadybirdBrowser/ladybird/blob/master/D…
Ladybird Alpha is here 👀github.com/LadybirdBrowser/ladybird/actions/runs/…
@papeto155584 @awesomekling @ladybirdbrowser Seems like different things in a short amount of time Eyeballing a little: +5k tests ladybird#13006 +6k ladybird#13014 +3k ladybird#13018 +6k ladybird#13027 +2k ladybird#13038 and many other 1-2000 tests changes
@chenhonzhou @ladybirdbrowser Not yet but you can build from source if you’re really curious 😊 LadybirdBrowser/ladybird