WebAssembly (às vezes abreviado como Wasm) é um padrão aberto que define um formato de código binárioportátil para programas executáveis e uma linguagem assembly textual correspondente, bem como interfaces para facilitar as interações entre esses programas e seu ambiente hospedeiro. O principal objetivo do WebAssembly é habilitar aplicativos de alto desempenho em páginas web, mas o formato é projetado para ser executado e integrado em outros ambientes também, incluindo os autônomos.
WebAssembly (ou seja, WebAssembly Core Specification (então a versão 1.0, 1.1 está em rascunho) e WebAssembly JavaScript Interface) tornou-se uma recomendação do World Wide Web Consortium em 5 de dezembro de 2019, junto com HTML, CSS e JavaScript.
WebAssembly pode suportar (pelo menos em teoria) qualquer linguagem (por exemplo, compilada ou interpretada) em qualquer sistema operacional (com a ajuda de ferramentas apropriadas), e na prática todas as linguagens mais populares já têm pelo menos algum nível de suporte.
O Emscripten SDK pode compilar qualquer código-fonte escrito em linguagens suportadas por LLVM (como C, C++ ou Rust, entre outras) em um arquivo binário que é executado na mesma sandbox como código JavaScript. Emscripten fornece ligações para várias interfaces de ambiente comumente usadas, como WebGL. Não há acesso direto ao Document Object Model (DOM); entretanto, é possível criar funções proxy para isso, por exemplo através de stdweb, web_sys, e js_sys ao usar a linguagem Rust.
As implementações do WebAssembly geralmente usam compilação ahead-of-time (AOT) ou just-in-time (JIT), mas também podem usar um interpretador. Embora as implementações atualmente mais conhecidas possam ser em navegadores web, também existem implementações sem navegador para uso geral, incluindo WebAssembly Micro Runtime, um projeto da Bytecode Alliance (com o subprojeto iwasm code VM suportando "interpretador, compilação ahead-of-time (AoT) e compilação Just-in-Time (JIT)"), Wasmtime, e Wasmer.
O WebAssembly foi anunciado pela primeira vez em 2015, e a primeira demonstração foi a execução do Angry Bots do Unity no Firefox, Google Chrome, e Microsoft Edge. As tecnologias precursoras foram asm.js da Mozilla e Google Native Client, e a implementação inicial foi baseada no conjunto de recursos do asm.js. A tecnologia asm.js já fornece velocidades de execução de código quase nativas e pode ser considerada uma alternativa viável para navegadores que não oferecem suporte ao WebAssembly ou que o desativaram por motivos de segurança.
Em março de 2017, o projeto do produto viável mínimo (MVP) foi declarado concluído e a fase de prévia encerrada. No final de setembro de 2017[update], o Safari 11 foi lançado com suporte. Em fevereiro de 2018, o Grupo de Trabalho WebAssembly publicou três rascunhos de trabalho público para a Especificação Central, Interface JavaScript, e API Web.
Implementações
Embora o WebAssembly tenha sido projetado inicialmente para permitir uma velocidade de execução de código quase nativa no navegador da web, ele foi considerado valioso fora disso, em contextos mais generalizados. Uma vez que os ambientes de tempo de execução (RE) do WebAssembly são máquinas de pilha virtual de baixo nível (semelhantes a JVM ou Flash VM) que podem ser incorporadas em aplicativos hospedeiros, alguns deles se tornaram ambientes de tempo de execução autônomos como Wasmtime e Wasmer.
Navegadores web
Em novembro de 2017, a Mozilla declarou o suporte "em todos os principais navegadores", depois que WebAssembly foi habilitado por padrão no Edge 16. O suporte inclui navegadores móveis para iOS e Android. Em março de 2021[update], 93% dos navegadores instalados (93% dos navegadores de desktop e 94% dos navegadores móveis) suportam WebAssembly. Mas para navegadores mais antigos, Wasm pode ser compilado em asm.js por um polyfill JavaScript.
Compiladores
Como os executáveis do WebAssembly são pré-compilados, é possível usar uma variedade de linguagens de programação para criá-los. Isso é conseguido através da compilação direta no Wasm, ou através da implementação das máquinas virtuais correspondentes no Wasm. Há cerca de 40 linguagens de programação conhecidas que suportam Wasm como um alvo de compilação.
A partir da versão 8, um Clang autônomo pode compilar C e C++ para Wasm.
Seu objetivo inicial é oferecer suporte à compilação de C e C++, embora o suporte para outras linguagens de fonte como Rust, linguagens .NET e AssemblyScript (similar a TypeScript) também esteja surgindo. Após o lançamento do MVP, existem planos para suportar multithreading e coleta de lixo, o que tornaria o WebAssembly um alvo de compilação para linguagens de programação coletadas como C# (suportado via Blazor), F# (suportado via Bolero com ajuda de Blazor), Python e até JavaScript onde a velocidade de compilação just-in-time do navegador é considerada muito lenta. Várias outras linguagens têm algum suporte, incluindo Python, Java, Julia, Zig, e Ruby, bem como Go.
Limitações
Em geral, WebAssembly não permite interação direta com o DOM. Toda interação deve fluir por meio da interoperabilidade JavaScript.
O WebAssembly é compatível com desktops e dispositivos móveis, mas no último, na prática (para alocações de memória não pequenas, como com o motor de jogo Unity) existem "limitações graves que tornam muitos aplicativos inviáveis para serem implantados de forma confiável em navegadores móveis [..] Atualmente, alocar mais de ~300 MB de memória não é confiável no Chrome no Android sem recorrer a soluções alternativas específicas do Chrome, nem no Safari no iOS."
Todos os navegadores web principais permitem o WebAssembly se Content-Security-Policy não for especificado, ou se "unsafe-eval" é usado, mas, caso contrário, os principais navegadores web se comportam de maneira diferente. Na prática, o WebAssembly não pode ser usado no Chrome sem "unsafe-eval", enquanto uma solução alternativa baseada em worker thread está disponível.
Considerações de segurança
Em junho de 2018, um pesquisador de segurança apresentou a possibilidade de usar o WebAssembly para contornar as mitigações do navegador para as vulnerabilidades de segurança Spectre e Meltdown assim que o suporte para threads com memória compartilhada for adicionado. Devido a essa preocupação, os desenvolvedores do WebAssembly suspenderam o desenvolvimento do recurso. No entanto, a fim de explorar essas futuras extensões de linguagem, o Google Chrome adicionou suporte experimental para a proposta de thread WebAssembly em outubro de 2018.
O WebAssembly foi criticado por permitir maior facilidade de ocultar as evidências para criadores de malware, golpistas e atacantes de phishing; O WebAssembly só está presente na máquina do usuário em sua forma compilada, o que "torna a detecção [do malware] difícil". A velocidade e capacidade de ocultação do WebAssembly levaram ao seu uso na criptomineração oculta no dispositivo do visitante do site. Coinhive, um serviço extinto que facilita a mineração de criptomoedas nos navegadores dos visitantes do site, afirma que seu "minerador usa WebAssembly e executa com cerca de 65% do desempenho de um minerador nativo." Um estudo feito em junho de 2019 pela Universidade de Tecnologia de Braunschweig (Technische Universität Braunschweig) analisou o uso do WebAssembly nos 1 milhão de websites mais acessados do mundo na lista da Alexa e descobriu que o uso predominante era para criptomineração maliciosa e que o malware era responsável por mais da metade dos sites que usam o WebAssembly estudados. Um estudo feito em abril de 2021 pela Universidade de Estugarda (Universität Stuttgart) descobriu que, desde então, a criptomineração foi marginalizada, caindo para menos de 1% de todos os módulos WebAssembly coletados de uma ampla gama de fontes, incluindo também os 1 milhão de websites mais acessados do mundo na lista da Alexa.
A capacidade de ofuscar com eficácia grandes quantidades de código também pode ser usada para desativar o bloqueio de anúncios e ferramentas de privacidade que impedem o rastreamento da web, como o Privacy Badger.
Como o WebAssembly só oferece suporte a fluxo de controle estruturado, é adequado para técnicas de verificação de segurança, incluindo execução simbólica. Os esforços atuais nessa direção incluem o mecanismo de execução simbólica Manticore.
WASI
WebAssembly System Interface (WASI) é uma interface simples (ABI e API) projetada pela Mozilla para ser portável para qualquer plataforma. Ele fornece recursos tipo POSIX, como E/S de arquivo restrito pela segurança baseada em capacidade. Existem também algumas outras ABI/APIs propostas.
WASI é influenciado por CloudABI e Capsicum.
Solomon Hykes, um cofundador do Docker, escreveu em 2019: "Se WASM+WASI existisse em 2008, não precisaríamos criar o Docker. Isso é o quão importante é. WebAssembly no servidor é o futuro da computação." O Wasmer, lançado na versão 1.0, fornece "contêinerização de software, criamos binários universais que funcionam em qualquer lugar sem modificação, incluindo sistemas operacionais como Linux, macOS, Windows e navegadores web. O Wasm automaticamente coloca os aplicativos em sandbox por padrão para execução segura".
Especificação
Ambiente hospedeiro
O padrão geral fornece especificações básicas para a API JavaScript e detalhes sobre incorporação.
Máquina virtual
O código Wasm (código binário, ou seja, bytecode) deve ser executado em uma máquina virtual de pilha (VM) portátil. A VM foi projetada para ser mais rápida de analisar e executar do que o JavaScript e ter uma representação de código compacta. Uma funcionalidade externa (como chamadas de sistema) que pode ser esperada pelo código binário Wasm não é estipulada pelo padrão. Em vez disso, fornece uma maneira de fornecer interface via módulos pelo ambiente hospedeiro em que a implementação da VM é executada.
Programa Wasm
Um programa Wasm é projetado para ser um módulo separado contendo coleções de vários valores definidos pelo Wasm e definições de tipo de programa. Eles são expressos em formato binário ou textual (veja abaixo), ambos com uma estrutura comum.
Conjunto de instruções
O padrão central para o formato binário de um programa Wasm define uma arquitetura do conjunto de instruções (ISA) que consiste em codificações binárias específicas de tipos de operações que são executadas pela VM (sem especificar como exatamente elas devem ser executadas). A lista de instruções inclui instruções de carregamento/armazenamento de memória padrão, numéricas, paramétricas, controle de fluxo e instruções de variáveis específicas do Wasm.
O número de opcodes usados no padrão original (MVP) era um pouco menos do que 200 dos 256 opcodes possíveis. As versões subsequentes do WebAssembly aumentaram o número de opcodes um pouco acima de 200. A proposta WebAssembly SIMD (para processamento paralelo) apresenta um prefixo de opcode alternativo (0xfd) para SIMD de 128 bits. A concatenação do prefixo SIMD, mais um opcode válido após o prefixo SIMD, forma um opcode SIMD. Os opcodes SIMD trazem 236 instruções adicionais para a capacidade SIMD do "produto viável mínimo" (MVP) (para um total de cerca de 436 instruções). Essas instruções, os "opcodes finalizados" são implementados no V8 do Google (no Google Chrome) e no mecanismo correspondente no Mozilla Firefox (mas não ativados em versões estáveis dos navegadores web), e também há proposta adicional de instruções para "pós SIMD MVP" posterior, e também há uma proposta "relaxed-simd" separada em discussão.
Esses opcodes SIMD também são portáveis e traduzem para conjuntos de instruções nativos como x64 e ARM. Em contraste, nem JVM do Java (nem CIL) suportam SIMD, no nível de opcode delas (enquanto ambos fornecem paralelo prático algum aumento de velocidade de SIMD), ou seja, no padrão, mas há uma extensão disponível adicionando intrínsecos para SIMD x64, que não seria portável, ou seja, não utilizável em ARM ou smartphones. Os smartphones podem oferecer suporte a SIMD chamando o código assembly com SIMD, e C# tem suporte semelhante.
Representação de código
Em março de 2017, o WebAssembly Community Group chegou a um consenso sobre o formato binário inicial (MVP), API JavaScript e interpretador de referência. Ele define um formato binário do WebAssembly (.wasm), que não é projetado para ser usado por humanos, bem como um formato de texto WebAssembly legível (.wat) que se assemelha a um cruzamento entre expressões S e linguagens de montagem tradicionais.
A tabela abaixo mostra um exemplo de uma função fatorial escrita em C e seu código WebAssembly correspondente após a compilação, mostrado em formato de texto .wat (uma representação textual legível de WebAssembly) e em formato binário .wasm (o bytecode bruto, expresso abaixo em hexadecimal), que é executado por um navegador web ou ambiente de tempo de execução que suporta WebAssembly.
Todas as constantes inteiras são codificadas usando uma codificação LEB128 de tamanho variável e eficiente em espaço.
O formato de texto WebAssembly é escrito mais canonicamente em um formato dobrado usando expressões S. Para instruções e expressões, este formato é puramente açúcar sintático e não tem diferenças comportamentais com o formato linear. Por meio do wasm2wat, o código acima se decompila para:
(module
(type $t0 (func (param i64) (result i64)))
(func $f0 (type $t0) (param $p0 i64) (result i64)
(if $I0 (result i64) ; $I0 is an unused label name
(i64.eqz
(local.get $p0)) ; the name $p0 is the same as 0 here
(then
(i64.const 1))
(else
(i64.mul
(local.get $p0)
(call $f0 ; the name $f0 is the same as 0 here
(i64.sub
(local.get $p0)
(i64.const 1))))))))
Observe que um módulo é gerado implicitamente pelo compilador. A função é, na verdade, referenciada por uma entrada da tabela de tipos no binário, portanto, uma seção de tipos e o tipo emitido pelo descompilador. O compilador e o descompilador podem ser acessados online.
Bibliografia
Haas, Andreas; Rossberg, Andreas; Schuff, Derek L.; Titzer, Ben L.; Gohman, Dan; Wagner, Luke; Zakai, Alon; Bastien, JF; Holman, Michael (junho de 2017). «Bringing the web up to speed with WebAssembly». Association for Computing Machinery. Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation: 185–200. ISBN9781450349888. doi:10.1145/3062341.3062363
↑De acordo com a documentação oficial, o Emscripten SDK pode ser usado para criar arquivos .wasm que depois podem ser executados em um navegador web. Mesmo que o Emscripten possa consumir várias linguagens ao usar o Clang, alguns problemas podem surgir.
Referências
↑«WebAssembly/design/Semantics.md». GitHub (em inglês). Consultado em 23 de fevereiro de 2021. Cópia arquivada em 13 de setembro de 2026. WebAssembly code can be considered a structured stack machine; a machine where most computations use a stack of values, but control flow is expressed in structured constructs such as blocks, ifs, and loops. In practice, implementations need not maintain an actual value stack, nor actual data structures for control; they need only behave as if they did so.
↑«Introduction — WebAssembly 1.0». webassembly.github.io. Consultado em 18 de junho de 2019. Cópia arquivada em 22 de outubro de 2026. ... this specification is complemented by additional documents defining interfaces to specific embedding environments such as the Web. These will each define a WebAssembly application programming interface (API) suitable for a given environment.
↑«Introduction — WebAssembly 1.1». webassembly.github.io. Consultado em 19 de fevereiro de 2021. Cópia arquivada em 22 de outubro de 2026. Its main goal is to enable high performance applications on the Web, but it does not make any Web-specific assumptions or provide Web-specific features, so it can be employed in other environments as well.
↑Haas, Andreas; Rossberg, Andreas; Schuff, Derek L.; Titzer, Ben L.; Holman, Michael; Gohman, Dan; Wagner, Luke; Zakai, Alon; Bastien, JF (14 de junho de 2017). «Bringing the Web Up to Speed with WebAssembly». SIGPLAN Notices. 52 (6): 185–200. ISSN0362-1340. doi:10.1145/3140587.3062363. While the Web is the primary motivation for WebAssembly, nothing in its design depends on the Web or a JavaScript environment. It is an open standard specifically designed for embedding in multiple contexts, and we expect that stand-alone implementations will become available in the future.
↑«stdweb - Rust». docs.rs. Consultado em 5 de junho de 2019. Cópia arquivada em 21 de fevereiro de 2019. The goal of this crate is to provide Rust bindings to the Web APIs and to allow a high degree of interoperability between Rust and JavaScript.
↑«web_sys - Rust». docs.rs. Consultado em 5 de junho de 2019. Raw API bindings for Web APIs. This is a procedurally generated crate from browser WebIDL which provides a binding to all APIs that browser provide on the web.
↑«js_sys - Rust». docs.rs. Consultado em 5 de junho de 2019. Bindings to JavaScript's standard, built-in objects, including their methods and properties.