Une étape majeure pour les composants WebAssembly
La spécification WASI 0.3.0 a été officiellement lancée le 11 juin 2026, après un vote de ratification du sous-groupe dédié. Cette nouvelle version refonde WASI sur les primitives asynchrones du WebAssembly Component Model, rendant l'asynchrone natif pour les composants. La spécification est désormais stable, et les supports dans les environnements d'exécution et les chaînes de compilation commencent à être déployés.
Ce qui change fondamentalement
Avec WASI 0.2, chaque composant devait gérer sa propre boucle d'événements ou environnement d'exécution asynchrone. Cela signifiait que si un composant utilisait des interfaces de flux ou des API asynchrones, il ne pouvait pas être composé avec d'autres composants : les boucles d'événements ne pouvaient pas coordonner entre elles. WASI 0.3 résout ce problème en confiant à l'hôte la responsabilité de piloter l'unique boucle d'événements partagée par tous les composants.
Cette intégration est rendue possible par l'ajout de stream<T>, future<T> et async comme constructions de première classe dans l'ABI canonique. stream<T> et future<T> se comportent comme des types de ressources : ce sont des poignées possédées, dont la propriété est transférée lors du passage d'une frontière de composant. Contrairement aux ressources, elles ne peuvent pas être empruntées. Le moteur d'exécution, et non chaque composant, gère l'ordonnancement : lorsqu'une valeur est livrée à un future, l'exécution planifie la tâche qui l'attend, même si cette valeur a transité par plusieurs frontières de composants. Le modèle asynchrone adopté est un modèle basé sur l'achèvement, similaire à celui de io_uring sous Linux ou d'IOCP/IoRing sous Windows, et non sur la disponibilité. Une interface de type epoll/kqueue peut être émulée par-dessus pour les programmes nécessitant une compatibilité héritée.
Des interfaces mécaniquement simplifiées
La plupart des modifications apportées aux interfaces de WASI 0.3 sont mécaniques. WASI 0.2 devait recourir à des acrobaties pour gérer l'asynchrone via le paquet wasi:io, avec des ressources comme pollable, input-stream, output-stream et des méthodes poll, subscribe, start-foo, finish-foo. Désormais, ces éléments sont remplacés par des constructions natives du Component Model : future<T>, stream<u8>, et la simple attente (await) sur un futur, tandis que les fonctions asynchrones sont exportées et importées directement via async func. Cette refonte élimine également un problème de WASI 0.2 : les erreurs terminales étaient signalées en ligne lors de chaque lecture sur un flux, ce qui empêchait les lecteurs s'arrêtant tôt de distinguer une fermeture de flux d'une erreur. En WASI 0.3, les flux renvoient un futur supplémentaire qui se résout indépendamment de la quantité de flux consommée.
Des liaisons natives pour chaque langage
L'un des atouts majeurs du Component Model est la facilité avec laquelle il permet de générer des liaisons vers et depuis d'autres langages. Avec l'asynchrone de première classe, les générateurs de liaisons peuvent créer des interfaces asynchrones qui paraissent idiomatiques dans leur langage respectif. Par exemple, l'interface wasi:http/handler expose une fonction handle marquée async func. En Rust, cela se traduit par un trait Guest et une fonction async fn handle, grâce à la crate wit-bindgen. La prise en charge de l'asynchrone est également en cours pour Python, JavaScript, C# et C, tous reposant sur des coroutines sans pile. Le modèle ABI asynchrone du Component Model a été conçu pour accueillir côte à côte des coroutines sans pile et avec pile. Go, par exemple, peut convertir des appels à synchronisation apparente en appels asynchrones grâce à ses goroutines. Une implémentation d'un serveur HTTP en Go utilise componentize-go pour exporter une fonction Handle et traiter les corps de flux via des goroutines qui effectuent des appels bloquants, le moteur d'exécution mettant en pause la goroutine à la frontière ABI et la reprenant lorsque le flux est prêt.
Prochaines étapes
Avec le lancement de WASI 0.3, les chaînes de compilation invitées et les environnements d'exécution hôtes peuvent commencer à stabiliser leurs implémentations respectives. Dans les semaines et les mois à venir, de nombreux projets devraient annoncer leur support de cette nouvelle spécification, rendant l'écosystème des composants WebAssembly plus interopérable et plus efficace.