今月のLadybird – 2026年4月
(ladybird.org)- Ladybirdは4月に35人のコントリビューターによる333件のPRをマージし、Human Rights Foundationから5万ドル、Jakub Stęplowskiから1,000ドルの新たな支援を受けた
- インラインPDFビューアー、閲覧履歴ベースのアドレスバー自動補完、GTK4/libadwaita Linuxフロントエンド、
about:bookmarks管理UIが追加され、ブラウジング機能とデスクトップUIが拡張された - HTMLパーサーはレスポンス本文を段階的にパースし、推測パーサーがリソースを先読みし、JavaScriptのトップレベルコンパイルはバックグラウンドスレッドへ移され、YouTubeの読み込みでメインスレッド時間を約200ms削減した
- JavaScriptエンジンはfor-inキャッシュ、O(1)レジスター割り当て器、ゼロコピーの識別子共有、lazy
JS::Substring、typed-array view cacheの改善などにより、Speedometerと実サイトの読み込み性能が向上した Cache/CacheStorage、image-set()、CSS anchor positioning、非同期DNS、dmabufベースのGPUペインティング、mimallocのデフォルト化、Rust必須化が含まれ、WPTスコアは2,003,537から2,067,263へ上昇した
開発規模と支援
- 4月のLadybirdは35人のコントリビューターによる333件のPRをマージし、このうち7人はLadybirdへの初コミットだった
- 新たな支援者として、Human Rights Foundationが「AI for Individual Rights」プログラムを通じて5万ドル、Jakub Stęplowskiが1,000ドルを支援した
- Ladybirdは、オープンウェブを支持する企業と個人の支援のみによって運営されている
ブラウジング機能とフロントエンド
-
インラインPDFビューアー
- PDFはバンドルされたpdf.jsビューアーを通じてインラインレンダリングされる(#9132)
- pdf.jsはJavaScript、HTML、CSSのみで書かれたPDFビューアーで、ページ移動、テキスト選択、ズーム、文書内検索を提供する
- Intel ISA Manualをpdf.jsで読み込む過程で、typed-array view cacheと
:has()無効化の改善点が明らかになった
-
閲覧履歴とアドレスバー自動補完
- アドレスバー入力時に閲覧履歴ベースの豊富な候補が表示され、過去に訪問したページのファビコンとタイトル、検索エンジンのショートカット、一般的なURL補完を含む(#8933)
- SQLiteベースの
HistoryStoreが、すべてのナビゲーションのタイトル、ファビコン、訪問回数、最終訪問時刻を保存する - プライバシー設定ページに「Clear browsing history」が接続され、QtとAppKit UIの両方が新しいリッチ行を描画する
-
GTK4 / libadwaitaフロントエンド
- LadybirdにGTK4およびlibadwaitaベースの新しいLinuxフロントエンドが追加され、既存のQtフロントエンドと並行して提供される(#8691)
- GNOME Web(Epiphany)から着想を得ており、GNOMEの設計指針に従ってメニューバーなしでハンバーガーメニューと
AdwTabViewタブを使用する - URLバーの自動補完とセキュリティアイコン、ページ内検索、フルスクリーン、コンテキストメニュー、alert/confirm/prompt/color/fileダイアログ、クリップボード、マルチウィンドウ、ライト/ダークテーマ、DPRスケーリングを提供する
- まだ初期段階のため、QtおよびAppKitフロントエンドとの機能同等性には達していない
-
ブックマーク
- 先月追加されたブックマークに管理UIが加わった
about:bookmarksページでブックマークとフォルダーを管理できる(#8825)- 新しいページでブックマークのインポートとエクスポートをサポートする(#8938)
- ブックマークとフォルダー編集用のコンテキストメニューが追加された(#8715)
- すべてのブックマークとフォルダーに
date_addedタイムスタンプが追加された(#8867) - ブックマークバーで新しいタブを開く、URLをコピーする、中クリックおよびCtrl/Cmd+クリックで新しいタブを開く操作をサポートする(#8758)
- HTML5ドラッグ&ドロップAPIが接続され、
about:bookmarksではこれを並べ替えに使用し、一般のWebページでも動作する(#8783)
HTMLパース、スクリプト実行、レンダリングパイプライン
-
推測および段階的HTMLパース
- HTMLパーサーがレスポンス本文を段階的に消費するように変更(#9151)
- バイト列はストリーミングテキストデコーダーを通ってトークナイザーにチャンク単位で入力され、入力が不足するとトークナイザーは停止し、さらに到着すると再開する
- 本文全体の受信を待ってからパースを開始していた従来モデルを置き換える
- 推測HTMLパーサーも実装(#9114)
- メインパーサーが同期外部スクリプトでブロックされると、別のトークナイザーがまだパースされていない入力を先行してスキャンし、
<script src>、<link rel=stylesheet|preload>、<img src>リソースの推測フェッチを発行する <base href>を追跡し、template および foreign content の内部を正しくスキップする- 推測パーサーはドキュメントの preload map に接続され、推測で見つかったリソースは通常パーサーによる後続のフェッチと重複排除される(#9164)
-
オフスレッドJavaScriptコンパイル
- 取得したスクリプトのトップレベルコードのバイトコード生成がバックグラウンドスレッドプールで実行される(#9118)
- ワーカースレッドはバイトコードと
Executable生成に必要なデータを作成し、VM または GC ヒープに触れる作業はメインスレッドに残す - classic script、module、トップレベル IIFE を処理し、YouTube の読み込みだけでも約 200ms のメインスレッド時間がバックグラウンドスレッドへ移される
-
Navigableごとのラスタライズ
- 各 Navigable が独自のスレッドで独立してラスタライズされる(#8793)
- 以前は iframe が親 display list 内のネストされた display list として同期的にペイントされ、最上位 traversable のレンダリングスレッドだけがアクティブだった
- 親 display list は теперь
ExternalContentSourceを通じて各 iframe のラスタライズ済み出力を参照するため、iframe の無効化で親の再記録は不要になる - 並列性に加え、iframe を別個のサンドボックスプロセスへ移すための準備作業でもある
-
Linux dmabufベースのGPUペインティング
JavaScriptエンジンの性能と互換性
-
JS-to-JS 呼び出し最適化
-
O(1) バイトコードレジスタ割り当て器
Generator::allocate_registerは利用可能なプールを走査して最も小さい番号のレジスタを探す構造で、x.com の読み込み中、この関数だけで約 800ms を消費していた- C++/Rust パイプライン同等性期間の終了後、割り当て器は単純な LIFO スタックに変更された(#9007)
-
キャッシュされた for-in 反復
for (key in obj)の位置が平坦化された enumerable key スナップショットをキャッシュし、receiver の shape、indexed storage、prototype chain が維持されている間は再利用する(#8856)- Speedometer 2 は 67.7 → 73.6、Speedometer 3 は 4.11 → 4.22 に向上
-
その他のエンジン改善
- パーサーは lexer、parser、scope collector 全体で識別子名を zero-copy で共有し、Webサイトの JS コーパスでパースが 1.14倍 高速化、RSS は 282MB 減少した(#8801)
- 短い文字列連結では、結果がどうせ flat string として観測される場合に rope 表現をスキップし、密な
a + bループで 2.13倍 高速化した(#9184) - lexical-this arrow function は呼び出しごとに function environment を割り当てないため、マイクロベンチマークで 2.13倍 改善した(#9192)
- sparse array は hole に対する即時コストを払わず、
Array(20_000_000)は 2000 万個の仮想要素に比例する処理の代わりに、主にメタデータとして維持される(#8847) - 新しい lazy
JS::Substring型が regexp capture やslice、split、indexed access などの string builtin を支え、Octane regexp ベンチマークで 1.066倍 改善した(#8863) - バイトコード source map で source position が end-to-end で保持され、x.com で約 250ms を節約した(#9027)
- zero-copy
TransferArrayBufferが YouTube の読み込みで約 130ms を節約した(#9088) - cached typed-array view が
WeakHashSetから intrusive list に変更され、pdf.js で Intel ISA PDF を読み込む際に約 250ms を節約した(#9180) - すべての
Promiseが、キャプチャしないAK::Functionクロージャを持つPromiseResolvingFunctionセル 2 個を割り当てていた構造から、Kindenum でディスパッチされる static function へと変更され、resolver ごとの割り当てが不要になった(#9188) - non-dictionary shape の property-table marking をスキップすることで、maptiler.com の読み込み中の GC 時間が 1.3秒 短縮された(#9044)
- packed array 向けの
Array.prototype.indexOffast path が追加された(#9123) Array.prototype.sortは比較のたびに再トランスコードせず、キャッシュ済み UTF-16 を再利用する(#9036)- WASM、JSON、CSS modules の import が追加された(#6029)
ShadowRealm提案は標準化プロセスで停滞したため、サポートが削除された(#8753)
WebプラットフォームAPIとCSS
-
CacheとCacheStorage
CacheとCacheStorageがエンドツーエンドで実装された(#8745)open、has、delete、keys、match、matchAll、add、addAll、putの9つのメソッドが一時的なインメモリストレージを基盤として動作する
-
CSS機能とレンダリング修正
image-set()の標準形式および-webkit-prefix 形式に対する基本サポートが追加され、ペイント時に device pixel ratio に最も適した解像度候補を選択し、サポートされていない MIME タイプはスキップする(#9090)image-set()のサポートにより、gocomics.com のヘッダー画像が表示されるようになったposition-anchorと CSS anchor positioning の初期サポートが追加され、cssdoom.wtf の手と銃の位置が修正された(#8686)- 色補間が css-color-4 に合わせて書き直され、
u8ではなく float 上で補間し、missing/powerless component、out-of-gamut sRGB、alpha multiplier を一貫して処理する(#8934) align、bgcolorのような legacy presentational HTML attribute が直接 cascaded properties を使わず、通常の author declaration のように cascade を通過するようになり、var()の置換と invalid-at-computed-value-time fallback が正しく動作する(#9176)- presentational hint cascade の変更により、html.spec.whatwg.org でのクラッシュが修正された
<thead>、<tbody>、<tfoot>、<tr>がalignpresentational attribute を反映するようになり、bricklink.com のボタン配置が修正された(#9177)stroke-dasharrayの補間により、SVG の dash が滑らかにアニメーションする(#9133)autofocusattribute を持つ要素が、ページ読み込み時に実際に focus を受けるようになった(#9016)- RTL テキストの list marker が右側に配置されるようになり、Arabic Wikipedia のリストレンダリングが修正された(#9099)
- inline flex/grid container の baseline が最後の折り返し行ではなく child の first line box から導出されるようになり、nos.nl のリンクテキストとアイコンの配置が修正された(#9183)
ネットワーキングとスタイル無効化
-
ネットワーキング
getaddrinfoが event loop をブロックしなくなった- LibDNS は lookup を thread pool で実行し、
AとAAAAquery を並列に発行、同じ名前に対する同時 lookup を統合する(#9109) - RequestServer の preconnect パスが resolver を迂回していたため、libcurl の threaded resolver が main thread で
pthread_joinを引き起こしていた問題を修正し、同じ DNS pool パスにルーティングされるようになった(#9109) - WebContent がネットワークより遅い場合、RequestServer の queued response data drain は O(n²) で、YouTube 動画を開く際に
memcpyに約 30秒、Vector::removeに 3秒を費やしていた AllocatingMemoryStreamは singly-linked chunk list に変更され、消費が O(1) になった(#9028)- 画像リクエストの
Acceptheader で AVIF と WebP を告知するようになり、他のエンジンと足並みをそろえた。一部の CDN はこの header に基づいて最新フォーマットを返すか、JPEG fallback にするかを決定する(#9046)
-
スタイル無効化
- 従来の selector invalidation は、selector が下方向しか見ないという前提で単純だったが、
:hostと:has()により descendant の変更が ancestor の:has()の結果を変え得るため、上方向への walk が必要になった - stylesheet mutation が 1 つの scope だけを変更した場合に、すべての style scope cache を再構築しないようにし、Reddit の rule cache rebuild は 13.2秒 → 3.2秒 に短縮された(#9138)
- sibling structural invalidation が position を監視しない descendant に伝播しないようになり、Reddit の infinite scroll で不要な recompute が 11% 減少した(#9155)
:has()mutation invalidation は影響を受けない anchor をスキップするようになり、azure.com で大幅な削減が計測された(#9168)- Intel ISA PDF では
:has()child-list visit が 71k → 1.6k に減少し、pdf.js の読み込みで約 650ms を節約した(#9179) - 新しい structural-invalidation テスト群が複数の無効化漏れを明らかにし、これを修正した(#9095)
- hover、stylesheet mutation scope、custom-property map、computed-style diffing 周辺の小さな改善も含まれる(#9077, #9049, #9079, #9080, #9141)
- 従来の selector invalidation は、selector が下方向しか見ないという前提で単純だったが、
メモリ割り当てとビルド体制
-
mimalloc デフォルトアロケータ
- C++ と Rust のコードはそれぞれ system allocator を経由せず、mimalloc v2 の単一 allocator instance を共有する(#8752)
malloc()をシステム全体で override しないため、third-party library は独自の allocator contract を維持する- JS benchmark は全体的に改善した
-
Rust 必須化とビルドシステム整理
-
GC とメモリ関連の変更
-ftrivial-auto-var-init=zeroでコンパイルし、関数突入時に古い GC pointer を 0 で上書きすることで、conservative stack scanner がそれを見つけにくくした(#9171)- まれに使われる
UsedValuesproperty を lazy pointer の後ろへ移動し、struct は 424バイト → 176バイト に縮小、sainsburys.co.uk の読み込み中にLayoutState::populate_node_from()は 139ms → 65ms に短縮された(#9104) - fetch body chunk は、chunk ごとに GC object を 7 個割り当てていた pull-promise パスを経由する構造から、byte stream controller に直接入るように変更された(#9169)
改善されたサイトの動作
-
Reddit
-
YouTube
-
その他のサイト
- gocomics.com は
image-set()によりヘッダー画像が表示されるようになりました - yandex.com/maps では、
WEBGL_debug_renderer_info拡張を含む WebGL 修正により、vector-tile WebGL レンダリングが動作します(#9043) - strava.com は、
Navigator.getBatteryが独自エラーではなく仕様で定められたエラー型を投げるようになり、ログインが動作するようになりました(#8770) - GitHub Insights は、
Element.matches()と.closest()の selector cache により、約 100ms 速くロードされます(#8987) - tweakers.net のノートPC比較ページは、indexed
HTMLFormElementproperty name lookup により約 31% 高速化しました(#9009) - neon.com はもうクラッシュしません(#8812)
- channel4.com では、flex auto-margin resolution の修正により、category text の縦方向の整列問題が解消されました(#9050)
- Cloudflare Turnstile はまだ通過できませんが、auth-scheme handling、
Array.prototype.shift()の最適化、<input>range および number 要素の UA event handler hardening により、はるかに速く失敗するようになりました(#9063)
- gocomics.com は
WPT とその他のプラットフォーム変更
-
Web Platform Tests
- WPT のスコアは 2,003,537 → 2,067,263 に上がり、今月は 63,726 件の subtest 増加を記録しました
- ただし、WPT は公式の ECMAScript conformance suite である test262 を upstream から取り込み、JavaScript subtest が 53,207件 追加されました
- Ladybird は test262 を何年も別途実行しており、LibJS の conformance も良好なため、このうち 52,045件、つまり 97.8% を通過しています
- 63.7k の増加分のうち約 52k は test262 の import によるもので、残り約 11.7k が実際の新しいブラウザプラットフォームの進展です
- test262 の import により、WPT は JavaScript conformance を他のプラットフォーム要素とあわせて測定するようになりました
-
テキスト、レイアウト、プロセス、UI
- ligature を含むテキストの selection と hit testing は、1 glyph あたり 1 code unit を仮定する方式から、grapheme cluster を走査し、その grapheme 群に glyph advance を分配する方式へ変更されました(#8829)
- shadow root に
innerHTMLを設定しても document 全体の layout tree を無効化しなくなり、pomax.github.io/bezierinfo では layout-and-paint 時間が 21% 短縮されました(#9191) - popup tab を別サイトへ移動しても、親の WebContent process は終了しなくなりました(#8730)
- Qt UI では
Ctrl+TabとCtrl+Shift+Tabで開いているタブを巡回できます(#8704) - マウスの中央ボタンを押したままドラッグしてスクロールしたり、その場でクリックして autoscroll mode に入ったりできます(#8881, #8928)
- アドレスバーの入力を URL や検索クエリとして sanitize できない場合、入力を黙って捨てる代わりに適切な error page が表示されます(#9072)
TextDecoderの streaming counterpart であるTextDecoderStreamが実装され、chunk 境界で partial UTF-8 を hold-back できるようになり、Reddit のコメント編集が可能になりました(#9143)- cross-process
BroadcastChannelメッセージは WebContent process と WebWorker process の間で IPC によってルーティングされ、listener がどの process にあっても他のブラウザーと同じように動作します(#8865)
1件のコメント
Hacker Newsのコメント
Rust GUIフレームワークのDioxusがネイティブレンダラーの一部として開発しており、FlutterのようにSkiaの代替を自前で作ろうという方向性だが、Flutter webのようにキャンバスだけを使うのではなく、WebでもHTML/CSS標準で動作する
既存のブラウザコードであるChromium、Gecko、WebKitには依存せず、Servoでも使われているstyloやtaffyのようなRustクレートを活用した、ほぼゼロから作られた実装に近い: https://github.com/DioxusLabs/blitz (
/apps/browser)多くのWebサイトは特定のブラウザの読み込みを強制的にブロックし、Chromiumだけを許可しているが、これがLadybirdが直面する現実であり、新しいブラウザの競争を阻む大きな要因になっている
DRM Widevineも新しいブラウザが獲得するのは非常に難しく、ユーザー1,000万人のZen Browserでさえ確保に失敗している
この20年間ずっとFirefoxだけを使ってきたが、互換性のためにChromiumに切り替えろと要求するサイトを一度も見たことがない
Widevineは本物の関門ではあるが、現実的にはNetflix、Disneyなど一部ストリーミングサイトの4K再生を止める程度だ
ZenがWidevineなしでもユーザー1,000万人を集めたことを見れば、そこまで決定的とも言いにくい
ブラウザ自体を制御できるなら、DRM関連の問題を除いてほとんど不可能なことはない
こういう記事は、ゲームエミュレーターのアップデートを読むときの楽しさを思い出させる
「Xバグを修正したらYが正しく動くようになり、その結果Zゲームが動くようになった」といった感じで、今回直したものの1つがCSS Doomなので、ゲーム方面との重なりもある程度ある
Andreasがブラウザを作ることはエミュレーターを作ることと同じだと何度も言っているのを聞いたことがある
Webサイトごとに異なる機能を異なるやり方で使っていて、彼はWebサイトをROMにたとえている
長年のFirefoxユーザーだが、Ladybirdがごく初期のアルファに入り、事前コンパイル済みビルドが出始めたら、ぜひ早い段階で使ってみるつもりだ
GTK4 / libadwaita frontendなのはうれしいQtよりGTK UI/UXのほうを好むので、こちらの開発の進展に期待している
strava.com : Login works now that Navigator.getBattery throws the spec-mandated error type instead of one of our own (#8770).Stravaはなぜ私のバッテリー残量を欲しがるのだろう?
開発途上国向けのWeb専用版があるのかもしれないし、バッテリーが少ないときは節約のために位置情報取得の頻度を下げようとしているのかもしれない
完全に推測だが、Stravaのようなサイトがバッテリー情報を要求するのはまったく不合理というほどではなく、ただ全体としては少し怪しくはある
Webサイトとしても使えるとすれば、位置情報取得頻度を調整して精度と消費電力の間で折り合いをつけようとしている可能性が高い
ただ、RTLテキストのリストマーカーのスクリーンショットは同じに見える
どちらの場合もリストマーカーが左側にある
一方「before」画像 https://ladybird.org/assets/img/newsletter-apr-2026-rtl-befo... では、箇条書き記号がテキストの左側にあるだけでなく、パネルの外に出そうなほど左に寄りすぎている
LadybirdのRedditテストでEvangelionのr/unixpornを使った人には本当に敬意を表したい
Evangelionはそれほど多く見たわけではないが、解説ドキュメンタリーは数え切れないほど見たし、しばらく壁紙にもしていたくらい好きだ
要点は、RedditがLadybirdで動いているのがすごいということだ
YouTubeが動くのかは分からないが、それも動いてくれたらいいし、Ladybirdが本当に日常利用可能になってきた感じがする
Ladybirdに寄付したhttps://jakubsteplow.ski/にも感謝したい
オープンソースプロジェクトに寄付する人たちを、Google広告のようなものより良い方法でもっと積極的に知らせたいし、Jakubに良いことがあるよう願っているし、ほかの人たちもLadybirdのようなプロジェクトに独自に寄付してほしい
Human Rights Foundationのhttps://hrf.org/program/ai-for-individual-rights/にも感謝したい
ブラウザがほぼ単独または複数による寡占状態だったのに、1人がここまでやったというのは驚くべきことで、本当に刺激を受ける
大きく2つの側面があって、1つは素晴らしい美学を持つメカ/エイリアン/怪物SFで、もう1つは自己嫌悪と孤独に焦点を当てた個人ドラマだ
たいていの人には前者のほうが魅力的だろうが、今なお残っているのは後者だ
見るなら視聴順には注意したほうがいい
オリジナルTVシリーズと映画『End of Evangelion』へ続くタイムラインがあり、完全なリブートとして始まりながら、どういうわけか原作の最終的なリブート/リメイク/続編にもなった『Rebuild of Eva』映画シリーズが別にある
「今日ブラウザの開発に携わっている人は何人か?」という問いへの答えとして、現在のLadybirdには有給のフルタイムエンジニアが8人おり、大きなボランティア貢献者コミュニティもあると書かれている
その大半も動くが、速度以外で最大の問題は、多くの**『あなたが人間か確認する』チェック**がLadybirdでは正しく動作しないことだ