Pangram verdict · v3.3
We believe that this text is a mix of AI and human-written content.
AI likelihood · overall
MixedArticle text · 1,462 words · 5 segments analyzed
Hello friends! In August Ladybird gained video playback on Twitch, more video formats on YouTube, CSS scroll snap, JavaScript debugging in DevTools, downloads you can pause and resume, and session restore. It’s also the month engine performance went from occasional attention to a sustained focus, with a new style engine, layout caching, and CSS animations moving off the main thread. We added caging for cell pointers stored in JavaScript values, and CSS parsing and the painting pipeline moved to Rust. Ladybird is entirely funded by the generous support of companies and individuals who believe in the open web. This month, we’re excited to welcome the following new sponsors: Arnav Guleria with $5,000 You can see everyone currently supporting the project on our sponsors page, and we’re grateful to all of them. If you’re interested in sponsoring, please contact us. Video on Twitch, and more formats on YouTube Our implementation of Media Source Extensions gained support for fragmented MP4, as well as the AVC (H.264), HEVC (H.265), AV1, and AAC codecs, with support queries now communicating our real capabilities (#11251). This allows us to play adaptive-bitrate video on many more sites, including Twitch and Plex. YouTube already worked in Ladybird since all videos are available as VP9/Opus in WebM, but some older/less popular videos only have multiple quality levels in AVC, and higher qualities (especially 8K) are often only served as AV1. We also fixed a batch of playback bugs: hovering YouTube’s video-card previews no longer crashes (#10992), players using preload="none" no longer hang (#11454), and HLS.js-based players start playing (#11480). CSS scroll snap Scroll snap landed (#10944): scroll-snap-type, scroll-snap-align and scroll-snap-stop. Wheel, keyboard, scrollbar dragging, touchpad flings and programmatic scrollTo() all snap, and content re-snaps when layout changes. (scrollIntoView() doesn’t snap yet.) Carousels and full-page scrollers are built on this. JavaScript debugging in DevTools You can now debug JavaScript in Ladybird: set breakpoints, step through code line by line, and evaluate watch expressions (#11128), built on new breakpoint support in our JavaScript engine (#10936). Wasm debugging and DOM mutation breakpoints are still missing, but the core workflow works. (As before, the Firefox DevTools frontend is a stopgap until we build our own.) Downloads that pause and resume Downloads can now be paused and resumed, and survive a browser restart, when the server supports it (#10932). We also download over four parallel connections where possible. Session restore Reopening a closed tab with Ctrl+Shift+T used to restore just the URL. It now restores the tab’s full session history, including back/forward state, and this persists across browser restarts (#11178). “Duplicate Tab” duplicates the session history too (#11286). We deliberately don’t persist form submission data yet; that needs careful handling first. Browser UI mailto: links open your mail client, and other external URL schemes prompt for confirmation, with protections against dangerous schemes and recursive launches (#10846). JavaScript dialogs no longer block the whole browser : alert(), confirm() and prompt() are now in-page overlays in the Qt UI, instead of modal system dialogs, so while (true) alert("lol") can’t lock you out. You can switch tabs, or just close the tab (#11264). Crash recovery no longer injects a fake page into your session history; you get a crash screen and your real history entry is kept. Reload picks up where the crash interrupted (#11402). Typing localhost:8000 or 127.0.0.1 in the URL bar now navigates there over http instead of failing (#11007). A pile of Wayland fixes : the omnibox stays put (#10862, #11149), Tab cycles page focus correctly (#10868), and scrollbar drags that leave the window no longer drop the mouse release (this one fixed on all of Linux, #11343). Site compatibility rules Some sites serve Ladybird broken content based on User-Agent sniffing. We now handle this with declarative site-compatibility rules loaded at runtime, instead of hardcoding per-site policy into the browser (#11327). The rules are plain JSON, so anyone can see what we do for which site. The first users are nytimes.com and cnn.com, which both render properly when we hide “Ladybird” from the User-Agent string (#11333). BeforeAfter Sites that work better chatgpt.com : a crash on the logged-in page plus three layout fixes (#11398). vscode.dev : crashed seconds after opening a new file. Hit testing read pointer-events from the wrong element, and VS Code’s empty-editor hint triggers it (#11342). icloud.com : sites that declare their character encoding more than 1KB into the page no longer render as mojibake (#11219). strava.com : two separate fixes each cut activity map load time roughly in half (#11133, #11114), chart popups follow your mouse now that svg.getScreenCTM() is implemented (#11177), and one activity page that used to grow until it ran out of memory no longer does; the memory it held onto dropped from 17.8 GiB to 61 MiB (#11055). outlook.com and Word : an Outlook crash fixed, and signing in to Word works (#11216). milliondollarhomepage.com and xkcd : <area> image-map links are clickable (#10863). CSS 3D transforms : a run of fixes filled in big missing pieces of 3D rendering: flattening at transform-style: flat boundaries (#11009), backface-visibility (#10960), and correct depth sorting of intersecting 3D planes using a BSP tree (#11045). The depth sorting was tested against cssDOOM, a DOOM renderer built out of pure CSS 3D transforms: walls now draw in the right order, and surfaces no longer flicker (#11466). overflow-wrap : long unbreakable words now emergency-break at grapheme boundaries instead of overflowing their container (RTL text doesn’t emergency-break yet) (#11416). Noticeably better on Google Translate. Right-to-left scroll containers scroll in the correct direction; previously some RTL content was unreachable (#11023). Text decorations are painted from the decorating box with its color, thickness and font geometry, which fixed the unconditional underlines on BBC Weather (#10744). Here’s a run through the first level of cssDOOM in Ladybird: And Google Translate before and after overflow-wrap: BeforeAfter Taking performance seriously We run the browser benchmarks continuously against master and track the results at linegodown.lol. Over August, our Speedometer 2 score went from about 47 to about 64, Speedometer 3 from about 2.5 to about 3.9, and StyleBench from about 3.5 to about 83.
These are still modest numbers next to the mature engines, but the movement is real. Part of the push is systematic: we benchmark individual operations against other browsers, find the ones where we’re drastically slower, and track down why. A DOM operation that’s 100x slower than Chromium’s usually isn’t 100x slower for a deep reason; something is simply wrong, and finding it helps real pages.
A month of this cut many such ratios by an order of magnitude: canvas fillStyle parsing went from about 90x slower than Chromium to about 2x (#11300), replaceChildren() from 13x to under 4x (#11306), and list insertion and removal from over 120x to under 20x (#11389). The JavaScript engine got its own batch of fast paths, for property access (#11175), spread (#11383), promise combinators (#11374), and JSON.stringify, which is now within about 15% of V8 on our benchmark (#11329).
The most satisfying fix: arrays that temporarily went sparse used to stay in slow hash-table storage forever. 30 lines later, Minecraft4k went from 10.2 to 14.5 FPS (#11423). A new style engine We replaced our selector matching, style invalidation, cascade and computed-style retention with a new engine (#11088). We want style work to be proportional to what changed, not to what might have changed. Historically, when something changes, browser engines have marked everything the change might affect, then re-matched and re-cascaded all of it. Modern engines narrow that set with techniques like invalidation sets and style sharing, but the pattern is the same, and opening a menu can still invalidate thousands of elements to change the style of a few dozen. The new engine treats DOM mutations, state changes and CSSOM edits as a stream of typed deltas, routes each delta to the selectors that depend on it, and stops as soon as an output is unchanged. In database terms: selectors are standing queries, and computed styles are materialized views kept up to date incrementally. Correctness is the hard part. A plain, cache-free evaluator serves as the reference implementation, and every fast path is checked against it. The engine’s input stream can also be recorded from a real browsing session and replayed deterministically; during development we replayed recordings of real sites, millions of events each, and treated any output divergence as a failure. On many workloads the new engine is still slower than that approach, and there’s a lot of tuning ahead. But on StyleBench, which measures exactly this kind of incremental restyling, we’re now in the same range as the major engines.
Here’s where the month ended, on an M3 MacBook Pro: Firefox is still well ahead. But this engine is a month old, and there are plenty of optimizations left to find.