webassembly
Especialista em WebAssembly (Wasm) baseado na documentação oficial do MDN Web Docs (developer.mozilla.org/pt-BR/docs/WebAssembly), complementado por WebAssembly: The Definitive Guide (Brian Sletten),
SKILL.mdskills/domains/webassembly/SKILL.md
GitHubHabilidade de IA: WebAssembly (Wasm Specialist)
Esta skill orienta a inteligência artificial a atuar como especialista em WebAssembly, alinhada à documentação oficial do MDN Web Docs (https://developer.mozilla.org/pt-BR/docs/WebAssembly). Cobre desde os conceitos de arquitetura (Module, Memory, Table, Instance) até o uso avançado da API JavaScript, compilação cross-language (C/C++, Rust, AssemblyScript), formato texto .wat, SIMD, exceções e JSPI.
📖 Referência canônica: consulte references/wasm-mdn-guide.md para o guia consolidado (conceitos, API JavaScript, Memória, Tabelas, Globais, tipos de valor, segurança).
📚 Referências complementares:
- references/wasm-definitive-guide.md — WebAssembly: The Definitive Guide (Brian Sletten): toolchain WABT, WASI, Emscripten, runtimes fora do browser, padrões host↔guest.
- references/wasm-with-rust.md — Programming WebAssembly with Rust (Kevin Hoffman): wasm-bindgen, wasm-pack, Yew, hosts em Rust.
🧭 Diretrizes Fundamentais
Ao atuar nesta skill, aplique os seguintes padrões:
1. Modelo Mental Correto
- Wasm complementa o JavaScript, não o substitui: execute lado a lado na mesma VM; use wasm para hot paths computacionais (games 3D, AR/VR, visão computacional, edição de imagem/vídeo, codecs, criptografia) e JS/DOM para a camada de aplicação.
- Conceitos 1:1 com a API JS:
Module(binário compilado, sem estado, compartilhável viapostMessage()comoBlob),Instance(Module + estado),Memory(ArrayBufferredimensionável — Linear Memory em páginas de 64 KB),Table(array redimensionável de referências —funcref, base para ponteiros de função). - Multiplicidade: 1 Module → N Instances; 0–1 Memory/Table por Instance; 1 Memory/Table compartilhada por N Instances (fundamento do dynamic linking).
2. Carregamento e Instanciação
- Sempre prefira streaming:
WebAssembly.instantiateStreaming(fetch(url), importObject)— compila e instancia direto do stream, semArrayBufferintermediário. - Sirva
.wasmcom MIMEapplication/wasme CORS habilitado (requisito para compile streaming). - Valide antes quando a origem dos bytes não for confiável:
WebAssembly.validate(bytes); - Introspecção:
Module.imports(),Module.exports(),Module.customSections(). - Cache grandes módulos de bytes no IndexedDB para acelerar o startup.
3. Fronteira JS ↔ Wasm
- Imports usam namespace de dois níveis:
{ imports: { imported_func: fn } }↔(import "imports" "imported_func"). - Só tipos numéricos primitivos cruzam a fronteira por padrão; dados estruturados passam pela Linear Memory via
Uint8Array/Int32Arrayetc. sobrememory.buffer. i64cruza a fronteira comoBigInt. Referências host-side usamexternref; funções usamfuncrefemWebAssembly.Table.- Chamadas frequentes JS↔wasm têm custo de fronteira: mova o loop inteiro para o wasm, não itere elemento a elemento via exports.
4. Memória
- Sempre declare
initiale preferencialmentemaximumemWebAssembly.Memory(pré-reserva eficiente; excedente lançaRangeError). - ⚠️ Buffer detachment: após
memory.grow(), omemory.bufferé novo — recrie todas as TypedArrays; views antigas ficam inválidas. - Memórias compartilhadas (
shared: true) →SharedArrayBuffertransferível entre Window/Worker compostMessage(); sincronize comAtomics. - Prefira definir
maximumantecipadamente em vez de crescer indefinidamente (fragmentação/reattribuição).
5. Compilação por Ferramenta
- Emscripten (C/C++): produz
.wasm+ glue JS + HTML; implementação de SDL/OpenGL/POSIX sobre Web APIs; wasm não acessa DOM — só chama JS. Use para portar código C/C++ legado e apps com AL. - Rust:
wasm-pack+ cratewasm-bindgen; gera pacote npm tipado; preferir para módulos novos com ABI ergonômica. - AssemblyScript: sintaxe tipo TypeScript; bundle pequeno; performance um pouco abaixo de C/Rust; ideal para devs web sem background C.
- WAT direto: para ferramentas/compiladores customizados; converter com WABT (
wat2wasm,wasm2wat).
6. Erros e Exceções
- Trate especificamente:
CompileError(bytes inválidos),LinkError(imports/exports incompatíveis),RuntimeError(unreachable, acesso fora da memória),SuspendError(JSPI). - Exceções estruturadas:
WebAssembly.Tag+WebAssembly.Exception(is(),getArg(),stack); no wasm usetry_table/catch/throw/throw_ref. - JSPI (quando disponível):
new WebAssembly.Suspending(promiseFn)para importações suspensoras eWebAssembly.promising(export)para transformar export wasm em função que retorna Promise — wasm pausa durante operações assíncronas sem bloquear.
🛠️ Padrões de Código Recomendados
Carregamento streaming idiomático
const importObject = {
imports: { imported_func: (arg) => console.log(arg) },
};
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject)
.then(({ instance }) => instance.exports.exported_func())
.catch((err) => {
if (err instanceof WebAssembly.CompileError) {
console.error("Bytes wasm inválidos ou MIME incorreto:", err);
}
});
Troca de dados via Linear Memory
const memory = new WebAssembly.Memory({ initial: 10, maximum: 100 });
WebAssembly.instantiateStreaming(fetch("memory.wasm"), { js: { mem: memory } })
.then(({ instance }) => {
let i32 = new Uint32Array(memory.buffer);
for (let i = 0; i < 10; i++) i32[i] = i;
const sum = instance.exports.accumulate(0, 10);
// ⚠️ se o módulo chamar memory.grow internamente, recrie a view:
i32 = new Uint32Array(memory.buffer);
});
Global compartilhado para vínculo dinâmico
const sharedCounter = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
WebAssembly.instantiateStreaming(fetch("global.wasm"), { js: { global: sharedCounter } })
.then(({ instance }) => {
sharedCounter.value = 42; // JS escreve
instance.exports.incGlobal(); // wasm incrementa
console.log(sharedCounter.value); // 43
});
Tabela como array de funções (ponteiros de função)
WebAssembly.instantiateStreaming(fetch("table.wasm")).then(({ instance }) => {
const tbl = instance.exports.tbl;
console.log(tbl.get(0)()); // 13 — get() devolve a referência; segundo () invoca
});
🔒 Segurança e Práticas Seguras
- Sandbox e Same-Origin Policy: wasm roda sob as mesmas políticas do browser; sem acesso direto a DOM, rede ou filesystem — toda interação I/O via glue JS.
- Validação de binários: nunca instancie
.wasmde fontes não confiáveis semWebAssembly.validate(); binários são dados, e um wasm malicioso pode abusar de imports JS (ex.: importareval-like via glue). - Mínimo de superfície de imports: exponha apenas as funções JS estritamente necessárias ao módulo; prefira wrappers que fazem whitelist de operações.
- Limites de memória: sempre defina
maximumpara impedir exaustão de memória do cliente; trateRangeErroremgrow(). - Memória compartilhada: exija
SharedArrayBuffercom COOP/COEP corretos em multi-thread (Atomics para sincronização — data races geram undefined behavior). - DoS via wasm: módulos com loops infinitos bloqueiam a main thread — execute em Web Worker quando o processamento for longo.
- Supply chain: confirme procedência de
.wasmde terceiros (SBOM/assinatura), recompile de fonte auditada quando possível.
🧰 Toolchain Beyond MDN
Além do guia MDN, o ecossistema wasm de produção (cf. WebAssembly: The Definitive Guide — Brian Sletten) gira em torno de:
- WABT (WebAssembly Binary Toolkit):
wat2wasm(texto→binário),wasm2wat(binário→texto),wasm-objdump -x(inspeção de seções/símbolos),wasm-interp(REPL de execução),wasm-validateewasm2c. Use--debug-namesemwat2wasmpara preservar nomes de funções/locais (Custom section) na depuração. - WASI: contract I/O portátil (
wasi_snapshot_preview1—fd_write,proc_exit,environ_get...). Módulos exportammemory+_start. Segurança por capabilities (unforgeable handles): conceda acesso com flags comowasmtime --dir=.(preopened file descriptors). Toolchains:wasi-sdk(clang/C), Rustwasm32-wasi,cargo wasi run. - Runtimes fora do browser: Wasmtime, Wasmer, wasm3, WasmEdge — embutíveis como engine de plug-ins/serverless. No Wasmtime (Rust):
Engine→Store(unidade de isolamento) →Module→Instance+get_typed_functipado. Hosts válidos (Hoffman) devem: carregar/validar, expor exports, satisfazer imports, executar e isolar módulos entre si. - Emscripten: além do MDN, flags-chave:
-s INVOKE_RUN=0+Module.callMain()(execução atrasada demain),-s MODULARIZE=1(API Promise-like),-s USE_SDL=2(port), FS virtual MEMFS (código C que escreve em disco roda no sandbox),emcc --bind(embind para classes C++↔JS),-s SIDE_MODULE=1(dynamic linking). - Threading: memórias
shared+Atomics.wait/notifydentro de Web Workers (requer COOP/COEP); confirme suporte via feature testing antes de depender da proposta.
Detalhes completos: references/wasm-definitive-guide.md
🦀 Wasm + Rust no Browser
Padrão idiomático de wasm-bindgen (cf. Programming WebAssembly with Rust — Kevin Hoffman, cap. 4): a macro #[wasm_bindgen] injeta metadados no .wasm; a CLI lê esses metadados e gera o "wrapper bridge" JavaScript — incluindo classes JS a partir de structs Rust.
use wasm_bindgen::prelude::*;
// Import 'window.alert'
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
// Export a 'hello' function
#[wasm_bindgen]
pub fn hello(name: &str) {
alert(&format!("Hello, {}!", name));
}
Build manual (livro): cargo build --target wasm32-unknown-unknown + wasm-bindgen target/wasm32-unknown-unknown/debug/bindgenhello.wasm --out-dir .. Em produção prefira wasm-pack build --target web|bundler|nodejs|no-modules (gera pacote npm com .d.ts).
Dicas extras do livro:
- Imports nominais:
#[wasm_bindgen(js_namespace = console)] fn log(s: &str);e classes JS externas viapub type Display; #[wasm_bindgen(method, structural, js_namespace = ROT)]. - Serialização: com feature
serde-serialize+serde, envie structs Rust comoJsValue(JsValue::from_serde(&stats).unwrap()) — mais leve que espelhar classes nos dois lados. - UI em Rust puro: framework Yew (componentes + Virtual DOM), sem escrever glue JS à mão.
Detalhes completos: references/wasm-with-rust.md
🔗 Integração com Outras Skills
- lang-c / lang-cpp: código-fonte C/C++ compilado via Emscripten para o alvo wasm.
- lang-rust: módulos Rust com
wasm-pack,wasm-bindgene alvowasm32-unknown-unknown. - lang-typescript: glue code tipado (
WebAssembly.Module,Memory,Instance,exports) e libs como AssemblyScript. - frontend-developer: integração de módulos wasm em aplicações web (fetch, workers, perf budget, Core Web Vitals).
- program-containers: Wasm fora do browser (runtimes Wasmtime/Wasmer, WASI) para workloads server-side e edge.