Mozilla Hacksの「Autogenerating Rust-JS bindings with UniFFI」を読みました。Firefox Syncチームが、Rustで書いた共有コンポーネントをFirefox DesktopのJavaScriptからも使えるようにするため、UniFFIにJavaScriptバインディング生成を加えた話です。
記事の要点
Mozillaは以前から、履歴、ログイン、同期といった機能を各プラットフォームごとの実装から、Rustで書いた共通のコアへ寄せる方針を進めていました。AndroidではKotlin、iOSではSwiftのラッパーを使えますが、手書きラッパーは時間がかかるだけでなく、深刻なバグやクラッシュの原因にもなります。そこで生まれたのが、Rustライブラリ向けに外部言語バインディングを自動生成するUniFFIです。
当初のUniFFIはKotlinとSwiftを支えていましたが、Firefox Desktopのフロントエンドを動かすJavaScriptには届いていませんでした。Firefox 105でUniFFIによるJavaScriptバインディング生成が入ったことで、同じRustコンポーネントをDesktop、Android、iOSの3系統で共有する道が開けた、というのがこの記事の中心です。
参照先も確認したこと
元記事から、2019年のRust FFI戦略の記事、UniFFIのユーザーガイド、ADR、過去のC++/WebIDL実装PR、FFIの説明、js-ctypes、FirefoxのWeb IDL bindingsドキュメント、MDNのWeb WorkersとPromise、Glean、GeckoViewも確認しました。
UniFFIの現在のドキュメントでは、Rustライブラリに対して外部言語バインディングを自動生成し、複数プラットフォーム向けのビジネスロジックを1つのRustライブラリへまとめるための道具だと説明されています。記事で出てくるWebIDL bindingsの仕組みも、Firefox内部のC++/GeckoコードとJavaScript APIをつなぐ生成基盤として位置づけられています。
気づき
今回の気づきは、Rustで共通化する価値は「コアが安全になる」だけでは完結しないという点です。コアがRustでも、各プラットフォームとの境界を手書きでつなぐなら、その境界が新しいバグの温床になります。UniFFIはその境界を生成物として管理し、Rustの安全性をアプリ全体の構造に届かせるための仕組みに見えます。
JavaScript対応で特に面白いのは、FirefoxのフロントエンドJavaScriptではメインスレッドを止められないため、UniFFI呼び出しをPromiseベースの非同期APIに寄せた点です。Rust側のモデルをそのまま押しつけるのではなく、JavaScript側の実行モデルに合わせてAPIを再設計しているところに、実運用の重さがあります。
2024年のReact Native向けUniFFI記事とあわせて読むと、UniFFIは単なるバインディング生成器ではなく、Rustを共通ロジックの基盤にしながら、各UI/アプリ環境の作法へ橋を架けるプロジェクトだと分かります。Firefox 108でリモートタブ同期エンジンが3プラットフォーム共有になったという成果は、その設計が実際に製品コードへ届いた例として印象的でした。

コメントを残す