Как UniFFI связал общие Rust-компоненты с JavaScript в Firefox

Команда синхронизации Mozilla использовала общие Rust-компоненты для нескольких платформ, но ручные обвязки для JavaScript, Kotlin и Swift требовали большого сопровождения. В инженерном разборе объясняется, как генератор UniFFI помог сократить эту работу.

Два уровня интерфейса

Нижний слой UniFFI предоставляет функции через C ABI. Поверх него создаётся удобный интерфейс для конкретного языка. В Firefox генерация C++ и WebIDL обслуживала именно нижний слой, а пользовательский API был реализован на JavaScript: ограничения WebIDL при этом не определяли возможности всего интерфейса.

Почему вызовы возвращают Promise

В описанной интеграции блокирующие обращения к Rust нельзя было выполнять в главном потоке интерфейса. Поэтому JavaScript-вызовы возвращают Promise, а работа выполняется в пуле потоков. Это архитектурное решение конкретной интеграции, а не общее требование делать любую быструю функцию асинхронной.

Поддержка UniFFI была внедрена в движке синхронизации, который стал примером общего компонента для Desktop, Android и iOS с обвязками на трёх языках.