- La norme Wasm 3.0 est annoncée officiellement, avec de grandes fonctionnalités préparées depuis 6 à 8 ans
- Des éléments comme l’espace d’adressage 64 bits, le garbage collection, les typed references, les tail calls et la gestion des exceptions facilitent la compilation de langages de haut niveau vers Wasm
- Ces principales nouveautés renforcent les applications haute performance, les runtimes multilangages, la sûreté et l’extensibilité
- Elles sont adaptées non seulement au Web, mais aussi aux écosystèmes hors Web qui doivent traiter des volumes et des jeux de données plus importants
- La prise en charge existe déjà dans les principaux navigateurs Web et devrait bientôt être finalisée dans des moteurs autonomes comme Wasmtime, ce qui renforcera encore la place de Wasm comme plateforme d’exécution généraliste
Présentation de la sortie de Wasm 3.0
- La version 3.0 du standard WebAssembly a été publiée le 17 septembre 2025
- Il s’agit de la première mise à jour majeure en trois ans depuis la version 2.0 (finalisée en 2022), qui avait introduit les instructions vectorielles, les opérations mémoire bulk, les valeurs de retour multiples et des types de référence simples
- Le groupe communautaire et le groupe de travail du W3C ont poursuivi le développement, et cette version apporte des changements d’ampleur avec de grandes fonctionnalités préparées depuis 6 à 8 ans
- Wasm conserve son esprit de langage bas niveau tout en renforçant son système mémoire et son système de types afin de mieux prendre en charge la compilation de langages de haut niveau
- Les fonctionnalités développées après la version 2.0 sont désormais finalisées et s’installent comme standard Live, tandis que leur prise en charge s’étend dans les navigateurs et les moteurs autonomes
- L’état de prise en charge par moteur peut être suivi sur la page Wasm feature status
- Cette première version a été produite avec la nouvelle chaîne d’outils SpecTec, ce qui améliore la fiabilité
Principaux changements et nouvelles fonctionnalités
- Espace d’adressage 64 bits
- Les mémoires et les tables peuvent être déclarées avec le type i64
- L’espace d’adressage des applications Wasm peut passer d’environ 4 Go jusqu’aux limites physiques (théoriquement 16 exaoctets)
- Sur le Web, une limite de 16 Go s’applique, mais dans les écosystèmes hors Web, cela est utile pour prendre en charge de grandes applications et de grands jeux de données
- Mémoire multiple
- Il est possible de déclarer plusieurs objets mémoire dans un même module et d’y accéder directement
- Cela ouvre des usages variés comme la fusion de modules, la séparation d’espaces d’adressage, le buffering ou la sécurité
- Des outils de linking statique comme wasm-merge peuvent ainsi s’appliquer à tous les modules Wasm
- Garbage collection (GC)
- En plus de la mémoire linéaire, prise en charge d’un stockage géré automatiquement par le runtime Wasm
- Les compilateurs déclarent directement les layouts de données, comme les types struct/array et les entiers unboxed
- Seules les briques de base de la gestion mémoire sont fournies, et les systèmes d’objets de haut niveau ou les closures peuvent être conçus séparément selon le langage d’implémentation
- Typed references
- Le système de types de Wasm est étendu afin de décrire plus précisément la forme des valeurs sur le tas et les références de fonctions
- Avec la prise en charge du sous-typage (subtyping) et de la récursivité des types, la nouvelle instruction
call_ref permet des appels indirects de fonctions sûrs sans vérification de type à l’exécution
- Tail calls
- Prise en charge des structures de tail call qui retournent immédiatement sans utiliser davantage d’espace de pile que la fonction existante
- Cela peut servir aux langages fonctionnels ou à certaines optimisations internes de runtime
- Gestion des exceptions
- Wasm introduit un système natif de gestion des exceptions
- Déclaration de tags d’exception et de payloads, capture sélective, et gestionnaires d’exceptions au niveau des blocs
- Cela améliore la portabilité et les performances sans passer par les méthodes inefficaces qui contournaient auparavant le problème via JS
- Instructions vectorielles relaxed
- Pour s’adapter aux différences matérielles des instructions SIMD, Wasm fournit des variants relaxed laissant à l’implémentation une liberté sur certains détails de comportement
- Cela permet diverses optimisations à l’intérieur de l’ensemble des comportements valides
- Profil déterministe
- Même dans les situations où le résultat d’une même instruction est non déterministe (calcul en virgule flottante, relaxed SIMD, etc.), un mode d’exécution déterministe entre plateformes est défini
- Cela permet de garantir la reproductibilité et la portabilité pour la blockchain, les systèmes rejouables et d’autres cas similaires
- Syntaxe d’annotations personnalisées
- Ajout d’une syntaxe d’annotation lisible et écrivable par des humains dans le code source
- Le standard ne l’interprète pas directement, mais elle pourra servir à de futures implémentations du standard et de ses extensions
Liaison avec JavaScript et compatibilité
- JS string builtins
- Les valeurs de chaînes de caractères de JS peuvent être transmises et manipulées dans Wasm via externref
- En important de nouvelles fonctions intégrées, Wasm peut utiliser directement des chaînes JS externes en interne
Utilité et perspectives de Wasm 3.0
- Fournit les bases essentielles à la compilation vers Wasm des langages de programmation avancés
- Des langages majeurs comme Java, OCaml, Scala, Kotlin, Scheme, Dart commencent eux aussi à exploiter activement les fonctionnalités GC
État de la spécification et du déploiement
- Wasm 3.0 est le premier standard produit avec la nouvelle chaîne d’outils SpecTec
- La plupart des grands navigateurs Web prennent déjà en charge Wasm 3.0, et des moteurs autonomes comme Wasmtime devraient bientôt finaliser leur support
- L’état de prise en charge par moteur est consultable sur la page Wasm feature status
2 commentaires
Est-ce que cela ne risque pas aussi de susciter des tentatives de créer une base de données en mémoire ?
Avis Hacker News
Ce qui m’enthousiasme vraiment, c’est que le 64 bits devienne la valeur par défaut du spec, surtout pour les webapps comme les éditeurs vidéo en ligne, qui subissent encore aujourd’hui beaucoup de contraintes à cause des limites du 32 bits ; Figma rencontre aussi directement ce genre de limites. Je me demande juste si, sur mobile, les limites de mémoire adressable par onglet resteront les mêmes ; en général, elles sont définies par l’OS, donc elles ne sont peut-être pas directement liées à l’espace 32 bits.
Je me demande s’il est vraiment souhaitable que des apps comme un éditeur vidéo arrivent dans un navigateur de documents ; c’est dommage qu’on n’utilise plus vraiment les systèmes d’exploitation natifs bien conçus. Si l’on a besoin d’une machine virtuelle encore plus puissante que la virtualisation offerte par les processus d’un OS classique, je pense qu’il serait plus honnête de concevoir une abstraction pensée pour cet usage. Là, on a l’impression de forcer un simple lecteur de documents à devenir un éditeur vidéo.
Malheureusement, la fonctionnalité Memory64 entraîne un coût en performances assez important. En 32 bits, le runtime allouait systématiquement l’ensemble des 4 Go, ce qui supprimait pratiquement le besoin de vérifications de bornes ; en 64 bits, il faut vérifier explicitement les limites. Si l’on a absolument besoin de plus de 4 Go de mémoire, il faut faire avec.
J’attends aussi avec impatience l’arrivée du GC, des types de référence et de l’API de chaînes JS. Cela faisait longtemps qu’on n’avait pas eu un J aussi bienvenu ; je me demande comment il va.
Il semble assez naturel que les webapps se heurtent à la limite de 4 Gio de mémoire. On a l’impression de vivre dans un monde où il faut désormais 512 Gio juste pour lire ses mails.
Je trouve fascinant qu’on ajoute un ramasse-miettes. Jusqu’ici, Wasm ne permettait pas d’accéder directement à la pile, ce qui rendait impossibles les approches GC traditionnelles comme le stack scanning. Du coup, on conserve le caractère bas niveau du langage, tout en décrivant explicitement la disposition mémoire via des types
struct,array, des entiers tagués non boxed, etc., et c’est Wasm qui se charge de l’allocation et de la durée de vie. C’est tout. Impressionnant.C’est rafraîchissant de voir qu’avec l’arrivée du GC, l’architecture continue malgré tout de prendre en charge les environnements sans GC. Sur ce point, cela ressemble à D (qui prend en charge compilation et exécution rapides avec et sans GC). À ce propos, on peut désormais générer du Wasm avec LDC, le compilateur Dlang : Generating WebAssembly with LDC
Je me demande si ce changement permettra de réduire la taille des objets
WebAssembly.Memory. C’est un sujet très important, car même après libération, la mémoire reste encore allouée côté navigateur : issue1 issue2Je me demande quand WASM pourra manipuler directement le DOM. J’ai l’impression que c’était l’objectif central au départ, alors qu’aujourd’hui cela ressemble presque à une créature séparée sans grand rapport avec le web. Je me demande aussi à quel moment on pourra enfin se passer de JavaScript.
J’espère que ce point, ainsi que l’accès multithread, seront correctement pris en charge. J’aimerais écrire une app Rust, la compiler en wasm, puis l’invoquer directement comme ceci :
Pour les webapps hautes performances, ou pour des choses comme les extensions de navigateur, les problèmes de mémoire et de performances sont bien réels, donc ce serait une aide énorme. Avec une app fondée sur wasm, on pourrait aussi contourner v8 et utiliser directement un moteur comme wasmer. Si les technologies web sont utilisées dans des apps desktop comme Electron, c’est à mon avis parce que les API desktop sont vraiment médiocres et peu portables. Si le support natif de WASM se renforce, des apps comme Slack, VSCode ou Discord pourraient devenir plus légères.
On peut déjà accéder au DOM depuis un programme WASM, mais il faut passer par les API JS existantes. À une époque, des API dédiées à WASM avaient été discutées, mais elles apportaient trop d’inconvénients et ont finalement été abandonnées.
J’attends de voir apparaître un langage frontend bien conçu. Cela dit, je me demande si le passage par des wrappers JS pour accéder au DOM est vraiment si inefficace. La plupart des codes sont déjà inefficaces de toute façon, donc je pense que le surcoût lié à cela ne ressort pas tant que ça en pratique.
Si vous pensez que JavaScript a des problèmes, vous allez découvrir que le DOM est encore pire.
Le fait d’avoir des références vers le DOM est délicat, parce que cela permettrait d’observer directement des objets gérés par le GC. Or, dans le modèle de sécurité de JavaScript sur le web, on n’est pas censé pouvoir inspecter l’intérieur du GC. Si WASM détenait des pointeurs vers le DOM, la question serait de savoir comment traiter cela. Une fois le GC correctement introduit, on pourra peut-être rouvrir le sujet, mais pour WASM sans GC, cela semble presque insoluble.
Comme je n’avais pas suivi le développement de WASM depuis environ un an, je découvre seulement maintenant qu’on est passé à un modèle de releases par version. Je pensais que de nombreuses fonctionnalités resteraient optionnelles, mais il semble désormais qu’une implémentation doive prendre en charge toutes les fonctionnalités pour pouvoir se dire compatible avec une version donnée (WASM 3.0, etc.). Je me demande quel runtime hors navigateur sera le deuxième à prendre entièrement en charge la 3.0 ; je parierais sur wasmtime (j’exclus deno, puisqu’il repose sur v8). Le GC me semble être une fonctionnalité particulièrement délicate. Je me demande aussi si quelqu’un sait comment cette release 3.0 s’articule avec l’ancien modèle « evergreen ». Dans ce modèle, on continuait à mettre à jour le brouillon du standard sans publier de version finale officielle distincte ; le dernier Candidate Recommendation Draft était en pratique traité comme le standard. état des fonctionnalités wasm actualités wasm 2.0 dernier brouillon du standard
wasmtime prend déjà en charge toutes les principales fonctionnalités de wasm 3.0. Le GC a été implémenté il y a plusieurs années par mon collègue Nick Fitzgerald, les tail calls ont été entièrement implémentés l’an dernier par Jamey Sharp et Trevor Elliott (sans restriction de signature, sans besoin de trampoline), et la gestion des exceptions est aussi prête, avec une sortie officielle prévue bientôt. Il faut voir la release « 3.0 » comme un signal indiquant que les moteurs avaient déjà préparé toutes ces fonctionnalités. Je suis mainteneur de wasmtime et de Cranelift.
Wizard est un outil de recherche, mais il prend lui aussi en charge l’ensemble de Wasm 3.0. En revanche, il n’a qu’un interpréteur et un compilateur baseline, pas de compilateur optimisant comme v8 ou wasmtime. Du coup, il reste lent.
Je pense que le versioning va fonctionner un peu comme les feature sets en JavaScript, c’est-à-dire qu’on décrira chaque runtime par l’ensemble de fonctionnalités qu’il prend en charge. Je me demande comment fonctionne la feature discovery côté wasm.
Je suis vraiment ravi de l’ajout du support du GC ; auparavant, dans WASM, l’accès direct à la pile n’était pas possible, ce qui rendait pratiquement impossible une implémentation de GC traditionnelle fondée sur le stack scanning.
J’ai l’impression que la communauté WebAssembly devrait accorder davantage d’attention à l’expérience développeur (DX). J’ai moi-même écrit un compilateur ciblant Wasm, et l’expérience était assez inconfortable. Je pensais cibler un langage à la sémantique bien formalisée, mais en pratique, en générant du Wasm via Binaryen.js, je n’avais pas vraiment l’impression de viser un ensemble d’instructions clairement défini. J’imagine que cela tient surtout à Binaryen lui-même et au manque de documentation. Consolation : écrire des snippets de texte Wasm était amusant. compilateur wasm jasmine
Binaryen traîne beaucoup d’héritage de l’époque où Wasm était un AST. Les nouvelles fonctionnalités s’intègrent difficilement dans ce modèle existant. Dans notre compilateur, nous avons défini notre propre structure de données pour une représentation abstraite de Wasm, et par défaut nous exportons en
.wasm, avec sortie en.watpour le debug. Je trouve l’ensemble d’instructions assez intuitif. backend wasm de Scala.jsJ’ai eu la même frustration en essayant d’utiliser Binaryen depuis TypeScript. Je suis passé à
wasm-tools, basé sur Rust, et l’expérience était bien meilleure.Je serais curieux de savoir ce qui était concrètement difficile. Les erreurs de validation peuvent être vraiment pénibles, c’est pourquoi j’ai ajouté une option
--trace-validationà Wizard. Elle permet de visualiser plus facilement le processus de validation.La documentation et les bindings de
binaryen.jssont effectivement très insuffisants aujourd’hui. Les efforts se concentrent actuellement sur l’amélioration des optimisations dans le cœur de Binaryen, donc le versant JS/TS progresse lentement. Cela dit, si quelqu’un consacrait du temps à améliorer les bindings JS/TS, ce serait bénéfique pour tout le monde.J’ai aussi eu l’impression qu’il était plus simple de produire directement du code assembleur pur à partir de zéro. La plupart des ressources se concentrent sur les outils Rust, mais l’expérience d’écriture manuelle a aussi son importance. Un compilateur et l’assembleur, ce n’est pas la même chose. Il faut aussi considérer que l’intérêt pour Wasm ne vient pas uniquement des développeurs de compilateurs.
J’ai toujours beaucoup d’attentes vis-à-vis de WASM, et cette release a l’air excellente. Nous faisons tourner des plugins WASM à fort trafic dans envoy, nous utilisons aussi WASM pour des plugins d’applications terminales comme zellij, et sur de petits side projects, j’exploite également des webapps wasm fondées sur Rust leptos. Honnêtement, sur ces trois cas, deux ne sont peut-être pas les meilleurs choix techniques, mais j’ai l’impression que la dynamique ira dans le bon sens. Bravo à tous pour le travail accompli.
Le plus simple reste le mieux. Mon souhait, c’est une manière plus simple et plus rapide de faire passer des structs Go, pour pouvoir injecter ou extraire des structs Go dans le runtime sans que le code se torde dans tous les sens et sans devoir recourir à des solutions bricolées. Une solution générique réutilisable dans plusieurs langages serait bien aussi, et je peux accepter qu’il y ait des limites pragmatiques. Pour moi, Go reste la priorité.
Je suis d’accord avec ça, et en pratique ce n’est pas tellement mieux non plus pour les langages sans GC. En réalité, les runtimes gérés par GC sur wasm sont souvent encore plus chaotiques. Ma pire expérience en JavaScript jusqu’ici a été la gestion manuelle des pointeurs. En C++, un destructeur s’en charge à la sortie de portée ; en wasm et en JS, il faut tout gérer soi-même, et même mes souvenirs de JNI étaient meilleurs (Go compris). Et une fois qu’on a enfin réussi à faire passer une struct, le surcoût par appel est si élevé qu’on finit par empaqueter des blocs plus gros. Moi aussi, j’espère surtout que le pipeline wasm devienne correct ; jusqu’ici, c’était difficile.
En code natif, la solution est la même : soit on s’aligne entre langages sur une structure standardisée (comme un
structC), soit on sérialise/désérialise. Quand on mélange plusieurs runtimes et que les langages n’offrent pas de support direct, cela devient vraiment pénible. Il est évident de comprendre pourquoi c’est un problème.Je ne suis pas sûr de comprendre exactement ce que vous cherchez, mais le component model, qui sous-tend WASI, pourrait aider. Ce modèle permet à chaque module de définir lui-même sa manière de mapper les données en mémoire (et plus tard même dans un tas GC), y compris pour des types comme les structures, puis laisse le compilateur générer automatiquement le glue code à partir de ces interfaces.
Cela me semble relever non pas du spec WASM, mais plutôt du domaine des bibliothèques. J’ai déjà eu de bonnes expériences en utilisant ce type de générateur de code en interne.
J’attends avec impatience le support d’OpenMP. Je fais tourner à titre expérimental un build web de Solvespace, et la prise en charge d’OpenMP serait un gros plus. démo en ligne de solvespace, un CAD open source qui tourne dans le navigateur.
Je trouve Solvespace vraiment génial. J’avais déjà conçu un boîtier de clavier scindé en suivant des tutoriels YouTube, puis je l’avais fabriqué sur CNC. On obtient vite des résultats. Merci de continuer à le maintenir.
C’est selon moi la meilleure interface web fondée sur WASM que j’aie vue jusqu’à présent. Je serais curieux de savoir quelle a été la partie la plus difficile lors du port du build desktop avec Emscripten.
Comme cela n’a pas encore été mentionné, je laisse cette remarque : je me demande si la fonctionnalité multiple-memories pourrait servir à éviter les copies redondantes lors du mapping des ressources WebGPU. Aujourd’hui, comme le mapping se fait sur
ArrayBuffer, WASM doit passer par JS pour copier, ce qui pénalise les performances. Plusieurs mémoires WASM combinées aux address spaces de Clang/LLVM semblent être une piste, mais je ne sais pas si c’est réellement aussi simple.Il y a bien une discussion sur le support toolchain du multi-memory, mais je ne sais pas si une implémentation exploitant réellement plusieurs espaces d’adressage dans LLVM a abouti.
Tout cela me rappelle les segmented memory et les far pointers d’autrefois. Je code récemment sur Gameboy, donc le memory mapping fait certes partie du « plaisir », mais je n’ai pas envie de revivre ça dans un environnement sans ces contraintes. Si on a enterré les far pointers de l’époque DOS/Win16, ce n’est pas sans raison.