WASM 3.0 concluído
(webassembly.org)- O padrão Wasm 3.0 foi oficialmente anunciado, incluindo grandes funcionalidades preparadas ao longo de 6 a 8 anos
- Recursos como espaço de endereçamento de 64 bits, coleta de lixo, referências tipadas, tail calls e tratamento de exceções tornam mais fácil compilar linguagens de alto nível para Wasm
- As principais novidades ajudam em aplicações de alto desempenho, runtimes de várias linguagens, segurança e extensibilidade
- É adequado não só para a web, mas também para ecossistemas fora da web, em casos que exigem lidar com capacidades e conjuntos de dados maiores
- Já é suportado pelos principais navegadores web, e deve ser concluído em breve também em motores independentes como o Wasmtime, consolidando ainda mais o Wasm como uma plataforma de execução de uso geral
Visão geral do lançamento do Wasm 3.0
- A versão 3.0 do padrão WebAssembly foi lançada em 17 de setembro de 2025
- É a principal atualização em 3 anos desde a versão 2.0 (concluída em 2022), que introduziu instruções vetoriais, operações de memória em lote, múltiplos valores de retorno e tipos de referência simples
- O Community Group e o Working Group do W3C continuaram o desenvolvimento, e este lançamento traz grandes recursos preparados ao longo de 6 a 8 anos, representando uma mudança de escala considerável
- O Wasm mantém seu espírito de linguagem de baixo nível, ao mesmo tempo em que fortalece o sistema de memória e de tipos para oferecer melhor suporte à compilação de linguagens de alto nível
- Os recursos desenvolvidos desde a versão 2.0 foram finalizados e se estabeleceram como padrão Live, com suporte ampliado em navegadores web e motores independentes
- É possível acompanhar o status de suporte de cada engine na página página de status dos recursos do Wasm
- A primeira versão foi produzida com a nova toolchain SpecTec, aumentando a confiabilidade
Principais mudanças e novos recursos
- Espaço de endereçamento de 64 bits
- Memórias e tabelas podem ser declaradas com o tipo i64
- O espaço de endereçamento de aplicações Wasm pode ser expandido de cerca de 4 GB até o limite físico (teoricamente 16 exabytes)
- Na web, aplica-se um limite de 16 GB, mas em ecossistemas fora da web isso é útil para dar suporte a aplicações e conjuntos de dados de grande porte
- Múltiplas memórias
- É possível declarar e acessar diretamente vários objetos de memória dentro de um único módulo
- Isso permite diversos usos, como fusão de módulos, separação de espaço de endereçamento, buffering e segurança
- Ferramentas de linkedição estática como wasm-merge passam a poder ser usadas com todos os módulos Wasm
- Coleta de lixo (GC)
- Além da memória linear, há suporte a armazenamento gerenciado automaticamente pelo runtime do Wasm
- O compilador declara diretamente layouts de dados como tipos struct/array e inteiros sem boxing
- São fornecidos apenas os blocos fundamentais de gerenciamento de memória, enquanto sistemas de objetos de alto nível ou closures podem ser projetados separadamente de acordo com a linguagem de implementação
- Referências tipadas
- O sistema de tipos do Wasm foi expandido para descrever com mais precisão a forma de valores no heap e referências de função
- Há suporte a subtipagem e tipos recursivos, e a nova instrução
call_refpermite chamadas indiretas seguras de função sem checagem de tipo em tempo de execução
- Tail calls
- Há suporte à estrutura de tail call, que retorna imediatamente sem uso adicional de espaço de pilha da função existente
- Isso pode ser usado em linguagens funcionais ou em otimizações internas de runtimes
- Tratamento de exceções
- O Wasm passa a ter um sistema nativo de tratamento de exceções
- Ele fornece declaração de tags e payloads de exceção, captura seletiva e handlers de exceção em nível de bloco
- Isso permite melhorar portabilidade e desempenho sem recorrer aos métodos ineficientes antes contornados via JS
- Instruções vetoriais relaxadas
- Para lidar com diferenças de hardware nas instruções SIMD, há uma variante relaxada que deixa a implementação livre para definir certos detalhes de algumas instruções
- Isso permite várias otimizações dentro do conjunto de comportamentos válidos
- Perfil determinístico
- Mesmo em situações em que o resultado da mesma instrução pode ser não determinístico (como operações de ponto flutuante e SIMD relaxado), ele define execução determinística entre plataformas
- Isso permite garantir reprodutibilidade e portabilidade em blockchain, sistemas reproduzíveis e afins
- Sintaxe de anotações customizadas
- Foi adicionada uma sintaxe de anotações legível e gravável por humanos dentro do código-fonte
- Embora não seja interpretada diretamente pelo padrão, ela pode ser usada no futuro em implementações de padrões e extensões
Integração com JavaScript e compatibilidade
- JS string builtins
- Valores de string do JS podem ser passados e manipulados no Wasm como externref
- Ao importar novas funções embutidas, passa a ser possível usar diretamente strings externas de JS dentro do Wasm
Utilidade e perspectivas do Wasm 3.0
- Fornece a base essencial para a compilação de linguagens de programação avançadas para Wasm
- Linguagens importantes como Java, OCaml, Scala, Kotlin, Scheme, Dart e outras já começaram a aproveitar ativamente os recursos de GC
Situação da criação da especificação e da distribuição
- O Wasm 3.0 é o primeiro padrão produzido com a nova toolchain SpecTec
- A maioria dos principais navegadores web já oferece suporte ao Wasm 3.0, e motores independentes como o Wasmtime também devem concluí-lo em breve
- É possível verificar o status de suporte por engine na página Wasm feature status
2 comentários
Não acabaria surgindo também uma tentativa de criar um banco de dados em memória?
Comentários no Hacker News
O ponto mais empolgante é que 64 bits vai virar o padrão da spec; apps web como editores de vídeo online ainda sofrem várias limitações por causa do limite de 32 bits, e a própria Figma já passou por isso na prática. Uma dúvida é se o limite de memória endereçável por aba em dispositivos móveis vai continuar o mesmo; em geral isso é definido pelo SO, então talvez não esteja ligado diretamente ao espaço de 32 bits.
Fico em dúvida se faz sentido um app como um editor de vídeo entrar no navegador de documentos. É uma pena que exista um sistema operacional nativo bem feito e, ainda assim, quase ninguém mais o use. Se é preciso uma máquina virtual ainda mais forte do que a virtualização oferecida por processos tradicionais do sistema operacional, me parece mais honesto projetar uma abstração adequada ao propósito. Dá a sensação de estar forçando um simples leitor de documentos a virar um editor de vídeo.
Infelizmente, o recurso Memory64 traz uma penalidade de desempenho considerável. Nos 32 bits anteriores, o runtime alocava os 4 GB completos de uma vez, então na prática nem era preciso fazer checagem de limites; em 64 bits, é preciso verificar os limites manualmente. Se você realmente precisa de mais de 4 GB de memória, aí não tem jeito.
Também estou animado com a chegada de GC, tipos de referência e a JS string API. Faz tempo que não vejo um J tão bem-vindo; espero que esteja bem.
Parece natural que webapps batam no limite de 4 GiB de memória. Hoje em dia até para ler e-mail parece que o mínimo é 512 GiB.
É realmente impressionante que estejam adicionando garbage collection. Antes, não era possível acessar diretamente a stack no Wasm, então abordagens tradicionais de GC como stack scanning eram inviáveis. Com isso, ele mantém a natureza de linguagem de baixo nível, explicitando layouts de memória com
struct, tiposarray,unboxed tagged inte afins, enquanto o Wasm cuida da alocação e do tempo de vida. Que coisa incrível.Acho interessante que, com a chegada do GC, a estrutura ainda suporte também ambientes sem GC. Nesse ponto lembra a linguagem D (o D suporta compilação e execução rápidas tanto com quanto sem GC). Aliás, agora já é possível gerar Wasm com o compilador LDC do Dlang: Generating WebAssembly with LDC
Fico curioso se essa mudança vai permitir reduzir o tamanho de objetos
WebAssembly.Memory. Isso é um ponto importantíssimo, já que mesmo ao liberar memória ela continua alocada no navegador issue 1 issue 2Queria saber quando o WASM vai poder mexer diretamente no DOM. Isso parecia ser o objetivo central original do WASM, mas hoje ele passa a impressão de ser um monstro separado, quase sem relação com a web. Quando será que vai dar para não precisar mais usar JavaScript?
Espero que isso e o acesso a multithreading sejam bem suportados. Quero poder escrever um app em Rust, compilar para wasm e chamar direto assim:
Em webapps de alto desempenho, ou em coisas como extensões de navegador, problemas de memória e desempenho realmente importam, então isso ajudaria muito. Se o app for baseado em wasm, também daria para pular o v8 e usar diretamente um engine como o wasmer. Acho que o motivo de tecnologias web irem parar em apps desktop como Electron é que as APIs desktop são ruins demais e não têm portabilidade. Se o suporte nativo a WASM ficar mais forte, apps como Slack, VSCode e Discord podem ficar mais leves.
Já dá para acessar o DOM a partir de programas WASM hoje, mas é preciso passar pelas APIs existentes em JS. Em certo momento até se discutiu uma API dedicada para WASM, mas ela acabou sendo abandonada por trazer muitas desvantagens.
Estou acompanhando a situação à espera de uma linguagem de frontend bem projetada. Mas fico pensando se passar por wrappers em JS para acessar o DOM é mesmo tão ineficiente assim. A maior parte do código já é ineficiente por natureza, então acho que o overhead disso nem aparece tanto na prática.
Se você acha que o problema está no JavaScript, espere até descobrir o quão pior é o lado do DOM.
A parte complicada é que, ao ter referências ao DOM, você passa a poder observar diretamente objetos coletáveis por garbage collection. No modelo de segurança do JavaScript na web, você não deveria conseguir inspecionar o interior do GC; se o WASM tiver um ponteiro para o DOM, a questão é como lidar com isso. Talvez esse ponto volte a ser discutido depois que o GC estiver plenamente introduzido, mas em WASM sem GC isso parece quase sem solução.
Faz cerca de um ano que eu não acompanhava o desenvolvimento de WASM, e só agora descobri que migraram para um modelo de releases por versão. Eu achava que vários recursos continuariam opcionais, mas agora parece que só dá para dizer que uma implementação é compatível com certa versão se suportar todos os recursos dela (WASM 3.0 etc.). Também fiquei curioso sobre qual runtime non-browser vai ser o segundo a ter suporte completo ao 3.0; imagino que seja o wasmtime (excluindo o deno por ser baseado em v8). O GC em particular parece um recurso complicado. Se alguém souber como o release 3.0 se conecta ao antigo modelo "evergreen", queria entender melhor. O evergreen era aquele modelo em que só se iam atualizando rascunhos da especificação, sem uma versão final oficial separada. Hoje o Candidate Recommendation Draft mais recente parece ser tratado como padrão de fato. status dos recursos do wasm notícia do wasm 2.0 rascunho mais recente do padrão
O wasmtime já suporta todos os principais recursos do wasm 3.0. O GC foi implementado há alguns anos pelo meu colega Nick Fitzgerald, e no ano passado o Jamey Sharp e o Trevor Elliott implementaram tail call com suporte completo (sem limitação de assinatura e sem necessidade de trampoline). O tratamento de exceções também já saiu e deve ser lançado oficialmente em breve. Esse release "3.0" é mais um sinal de que os engines já vinham preparando todos esses recursos há algum tempo. Eu sou mantenedor do wasmtime e do Cranelift.
O Wizard é uma ferramenta de pesquisa, mas também suporta integralmente o Wasm 3.0. Em compensação, só tem interpretador e compilador baseline, sem um compilador otimizado como v8 ou wasmtime, então em velocidade ele é lento.
Parece que o versionamento vai acabar funcionando como o modelo de conjunto de recursos do JavaScript, ou seja, falando em quais feature sets cada runtime suporta. Fico curioso sobre como funciona a descoberta de recursos no wasm.
Fiquei muito feliz com a adição de suporte a GC. Antes, como não havia acesso direto à stack no WASM, implementar GC tradicional com stack scanning era praticamente impossível.
Tenho a impressão de que a comunidade WebAssembly precisa se preocupar mais com a experiência do desenvolvedor (DX). Já escrevi um compilador mirando Wasm e achei a experiência bem desconfortável. Eu imaginava que fosse uma linguagem com semântica mais formalizada, mas ao gerar Wasm com Binaryen.js não dava muito a sensação de estar mirando um conjunto de instruções claro. Suspeito que isso se deva ao próprio Binaryen e à falta de documentação. Pelo menos foi divertido escrever snippets em texto de Wasm. compilador wasm jasmine
O Binaryen carrega muito legado de quando o Wasm antigo era uma AST. Os recursos novos são difíceis de encaixar naquele modelo. No nosso compilador, definimos uma estrutura de dados separada para representar um Wasm abstrato; por padrão compilamos para
.wasme, em modo de debug, exportamos para.wat. Acho isso bem intuitivo, então para mim o conjunto de instruções está ok. backend wasm do Scala.jsTive uma sensação parecida de frustração ao usar Binaryen em TypeScript. Migrei para o wasm-tools baseado em Rust e a experiência foi muito melhor.
Queria entender especificamente quais partes foram difíceis. Às vezes erros de validação são muito irritantes, então no Wizard existe a opção
--trace-validation, que mostra o processo de validação de forma visual e mais fácil de acompanhar.A documentação e os bindings de
binaryen.jsrealmente deixam bastante a desejar. Hoje o foco está mais em melhorar as otimizações do core do Binaryen, então o lado JS/TS evolui devagar. Ainda assim, se alguém dedicar tempo a melhorar os bindings JS/TS, isso seria ótimo para todo mundo.Também tive a impressão de que pode ser mais fácil escrever assembly puro do zero. A maior parte do material se concentra nas ferramentas de Rust, mas a experiência de escrever tudo manualmente também importa. Compiler e assembly são coisas diferentes; é preciso considerar que não são só desenvolvedores de compiladores que se interessam por Wasm.
Ainda tenho expectativa com WASM, e esse release parece muito bom. Rodo plugins WASM com bastante tráfego no envoy, uso WASM também em plugins para apps de terminal como o zellij, e num projetinho paralelo mantenho um webapp em wasm com rust leptos. Sendo sincero, em 2 dos 3 casos talvez não seja a escolha tecnicamente ideal, mas acho que essa direção ainda vai longe. Parabéns a todos pelo trabalho.
O simples é melhor. O que eu mais quero é uma forma mais fácil e rápida de passar
structde Go. Queria poder colocar ou tirarstructde Go no runtime sem virar um emaranhado de código nem depender de soluções improvisadas. Uma solução genérica que servisse para várias linguagens seria ótima, mas também aceito limitações realistas. Para mim, Go é o mais importante.Concordo com isso. E, na prática, mesmo em linguagens sem GC não fica muito melhor. Na verdade, os runtimes com GC em wasm têm sido até mais bagunçados. A pior experiência que já tive com JavaScript foi gerenciando ponteiros manualmente. Em C++ o destrutor resolve isso ao sair do escopo, mas em wasm e JS você tem que cuidar de tudo na mão; comparado a isso, minhas lembranças com JNI foram melhores (inclusive com Go). E, depois de todo esse esforço para passar um único
struct, o overhead por chamada ainda é alto, então no fim você começa a empacotar blocos maiores de dados por vez. Eu também só quero que o pipeline do wasm fique decente; até agora tem sido difícil.Se for código nativo, a solução é a mesma de sempre: alinhar entre linguagens uma estrutura padrão (como
structde C) ou então serializar/desserializar. Quando você mistura vários runtimes e as linguagens não oferecem suporte direto, a situação fica realmente desgastante. É bem óbvio por que isso vira problema.Não sei exatamente o que você quer, mas o component model do WASI, que é a base dele, talvez ajude. Nesse modelo, cada módulo define como seus dados são mapeados em memória por conta própria (e no futuro talvez até no heap de GC), e coisas como tipos de estrutura também são definidas na interface, para o compilador gerar automaticamente o código glue.
Isso me parece mais assunto de biblioteca do que da spec do WASM. Já tive boa experiência usando internamente geradores de código desse tipo.
Estou na expectativa por suporte a OpenMP. Estou rodando experimentalmente uma build web do Solvespace, e isso deve melhorar bastante quando houver suporte a OpenMP. demo online do solvespace, um CAD open source que roda no navegador.
Acho o Solvespace uma ferramenta realmente incrível. Uma vez projetei a carcaça de um teclado split seguindo tutoriais no YouTube e até mandei cortar em CNC. Consegui chegar no resultado bem rápido. Obrigado por manter o projeto.
Acho que é a melhor UI web baseada em WASM que já vi. Queria saber qual foi a parte mais difícil ao portar a build desktop com Emscripten.
Deixo um ponto que ainda não vi ser mencionado: será que o recurso multiple-memories pode ser usado no mapeamento de recursos do WebGPU para evitar cópias duplicadas? Hoje existe o mapeamento em
ArrayBuffer, então no WASM é preciso copiar passando por JS, o que prejudica o desempenho. Parece que múltiplas memórias do WASM junto com o recurso de address space do Clang/LLVM poderiam resolver isso, mas não sei se na prática é tão simples assim.Existe uma discussão sobre suporte toolchain para multi-memory, mas não sei se chegou a haver de fato uma implementação no LLVM usando múltiplos espaços de endereçamento.
Tudo isso me faz lembrar segmented memory e far pointers de antigamente. Tenho brincado de escrever jogos para Game Boy recentemente, então mapeamento de memória até faz parte da "diversão", mas repetir isso em um ambiente sem essas restrições me parece bem desagradável. Não é à toa que enterraram os far pointers da era DOS/Win16.