# WebAssembly

O objeto `WebAssembly` contém a interface JavaScript para WebAssembly no Azion Runtime. Uma function o usa para validar, compilar e instanciar um módulo a partir do código binário dele, e para criar a memória, as tabelas e as tags que um módulo usa. O Azion Runtime oferece a interface que a MDN Web Docs define, exceto que os dois métodos de streaming não aceitam um `Response`. Para mais informações, consulte [WebAssembly](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) e [WebAssembly JavaScript interface](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface) na MDN Web Docs.

Os exemplos declaram o código binário de um módulo inline, por isso cada um executa como está escrito. Uma function que baixa um arquivo `.wasm` com [`fetch()`](/pt-br/documentacao/devtools/runtime/api-reference/fetch/) passa o resultado de `response.arrayBuffer()` no lugar dele.

---

## Métodos

O objeto `WebAssembly` tem estes métodos estáticos.

### WebAssembly.compile()

`WebAssembly.compile()` compila código binário WebAssembly em um objeto `WebAssembly.Module`. Use-o quando você compila um módulo antes de instanciá-lo; caso contrário, use `WebAssembly.instantiate()`.

```javascript
WebAssembly.compile(bufferSource)
```

| Parâmetro      | Tipo                         | Obrigatório | Descrição                                    |
| -------------- | ---------------------------- | ----------- | -------------------------------------------- |
| `bufferSource` | Typed array ou `ArrayBuffer` | Sim         | Código binário do módulo `.wasm` a compilar. |

Este exemplo compila um módulo que exporta uma função, `add`, e lista as exportações do módulo:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 7, 1, 3, 97, 100, 100, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11]);

WebAssembly.compile(bytes).then((mod) => {
  console.log(WebAssembly.Module.exports(mod)); // [{ name: "add", kind: "function" }]
});
```

Bytes que não formam um módulo válido fazem a promise ser rejeitada com um `WebAssembly.CompileError`. Por exemplo, um módulo com uma versão não suportada é rejeitado com `WebAssembly.compile(): expected version 01 00 00 00, found 09 00 00 00 @+4`.

### WebAssembly.compileStreaming()

`WebAssembly.compileStreaming()` compila um `WebAssembly.Module` a partir de uma fonte subjacente transmitida por streaming. Use-o quando você compila um módulo antes de instanciá-lo; caso contrário, use `WebAssembly.instantiateStreaming()`.

```javascript
WebAssembly.compileStreaming(source)
```

| Parâmetro | Tipo       | Obrigatório | Descrição                                                                 |
| --------- | ---------- | ----------- | ------------------------------------------------------------------------- |
| `source`  | `Response` | Sim         | Fonte subjacente do módulo `.wasm` a transmitir por streaming e compilar. |

O Azion Runtime não aceita um `Response` como `source`: a promise é rejeitada com `TypeError: WebAssembly.compile(): Argument 0 must be a buffer source`. Para compilar um módulo a partir de uma resposta, leia o corpo com `response.arrayBuffer()` e passe o resultado para `WebAssembly.compile()`.

### WebAssembly.instantiate()

`WebAssembly.instantiate()` compila e instancia código WebAssembly. Ele tem dois overloads:

- O overload primário recebe o código binário, como um typed array ou um `ArrayBuffer`, e o compila e instancia em uma única etapa. A promise é cumprida com um objeto que contém `module` e `instance`.
- O overload secundário recebe um `WebAssembly.Module` já compilado. A promise é cumprida com uma `Instance` desse módulo.

```javascript
WebAssembly.instantiate(bufferSource, importObject)
WebAssembly.instantiate(module, importObject)
```

O overload primário recebe estes parâmetros:

| Parâmetro      | Tipo                         | Obrigatório | Descrição                                                                                                                                                                                                                                               |
| -------------- | ---------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bufferSource` | Typed array ou `ArrayBuffer` | Sim         | Código binário do módulo `.wasm` a compilar e instanciar.                                                                                                                                                                                               |
| `importObject` | Object                       | Não         | Valores a importar para a nova `Instance`, como funções ou objetos `WebAssembly.Memory`. Ele precisa de uma propriedade correspondente para cada importação que o módulo declara; caso contrário, a promise é rejeitada com um `WebAssembly.LinkError`. |

O overload secundário recebe estes parâmetros:

| Parâmetro      | Tipo                 | Obrigatório | Descrição                                                                                                                                                                                                                                      |
| -------------- | -------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `module`       | `WebAssembly.Module` | Sim         | Módulo a instanciar.                                                                                                                                                                                                                           |
| `importObject` | Object               | Não         | Valores a importar para a nova `Instance`, como funções ou objetos `WebAssembly.Memory`. Ele precisa de uma propriedade correspondente para cada importação de `module`; caso contrário, a promise é rejeitada com um `WebAssembly.LinkError`. |

Um objeto de importação sem a função que um módulo importa faz a promise ser rejeitada com `WebAssembly.instantiate(): Import #0 "imports" "imported_func": function import requires a callable`.

Este exemplo usa o overload primário. O módulo importa `imports.imported_func` e exporta `exported_func`, que chama a função importada com o valor `42`:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 8, 2, 96, 1, 127, 0, 96, 0, 0, 2, 25, 1, 7, 105, 109, 112, 111, 114, 116, 115, 13, 105, 109, 112, 111, 114, 116, 101, 100, 95, 102, 117, 110, 99, 0, 0, 3, 2, 1, 1, 7, 17, 1, 13, 101, 120, 112, 111, 114, 116, 101, 100, 95, 102, 117, 110, 99, 0, 1, 10, 8, 1, 6, 0, 65, 42, 16, 0, 11]);

const importObject = {
  imports: {
    imported_func(arg) {
      console.log(arg); // 42
    },
  },
};

WebAssembly.instantiate(bytes, importObject).then((result) => {
  result.instance.exports.exported_func();
});
```

Este exemplo usa o overload secundário. Ele compila o módulo `add` primeiro e depois o instancia:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 7, 1, 3, 97, 100, 100, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11]);

WebAssembly.compile(bytes)
  .then((mod) => WebAssembly.instantiate(mod))
  .then((instance) => {
    console.log(instance.exports.add(40, 2)); // 42
  });
```

### WebAssembly.instantiateStreaming()

`WebAssembly.instantiateStreaming()` compila e instancia um módulo WebAssembly diretamente a partir de uma fonte subjacente transmitida por streaming.

```javascript
WebAssembly.instantiateStreaming(source, importObject)
```

| Parâmetro      | Tipo                                             | Obrigatório | Descrição                                                                                                                                                                                                                                               |
| -------------- | ------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `source`       | `Response`, ou uma promise que é cumprida com um | Sim         | Fonte subjacente do módulo `.wasm` a transmitir por streaming, compilar e instanciar.                                                                                                                                                                   |
| `importObject` | Object                                           | Não         | Valores a importar para a nova `Instance`, como funções ou objetos `WebAssembly.Memory`. Ele precisa de uma propriedade correspondente para cada importação que o módulo declara; caso contrário, a promise é rejeitada com um `WebAssembly.LinkError`. |

O Azion Runtime não aceita um `Response` como `source`: a promise é rejeitada com `TypeError: WebAssembly.compile(): Argument 0 must be a buffer source`. Para instanciar um módulo a partir de uma resposta, leia o corpo com `response.arrayBuffer()` e passe o resultado para `WebAssembly.instantiate()`.

### WebAssembly.validate()

`WebAssembly.validate()` verifica se um typed array de código binário WebAssembly forma um módulo válido. Ele retorna `true` quando os bytes formam um módulo válido e `false` quando não formam.

```javascript
WebAssembly.validate(bufferSource)
```

| Parâmetro      | Tipo                         | Obrigatório | Descrição                 |
| -------------- | ---------------------------- | ----------- | ------------------------- |
| `bufferSource` | Typed array ou `ArrayBuffer` | Sim         | Código binário a validar. |

Este exemplo valida o módulo `add` e três bytes que não são um módulo:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 7, 1, 3, 97, 100, 100, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11]);

console.log(WebAssembly.validate(bytes)); // true
console.log(WebAssembly.validate(new Uint8Array([1, 2, 3]))); // false
```

---

## Construtores

O objeto `WebAssembly` contém estes construtores.

### WebAssembly.CompileError()

`WebAssembly.CompileError()` cria um objeto `CompileError`, que indica um erro durante a decodificação ou a validação de WebAssembly.

```javascript
new WebAssembly.CompileError()
new WebAssembly.CompileError(message)
new WebAssembly.CompileError(message, fileName)
new WebAssembly.CompileError(message, fileName, lineNumber)
```

| Parâmetro    | Tipo   | Obrigatório | Descrição                                                 |
| ------------ | ------ | ----------- | --------------------------------------------------------- |
| `message`    | String | Não         | Descrição legível do erro.                                |
| `fileName`   | String | Não         | Nome do arquivo que contém o código que causou a exceção. |
| `lineNumber` | Number | Não         | Número da linha do código que causou a exceção.           |

Este exemplo lança um `CompileError` e o lê em um bloco `catch`:

```javascript
try {
  throw new WebAssembly.CompileError('Hello', 'someFile', 10);
} catch (e) {
  console.log(e instanceof WebAssembly.CompileError); // true
  console.log(e.message);                             // "Hello"
  console.log(e.name);                                // "CompileError"
  console.log(e.stack);                               // the location where the code ran
}
```

`CompileError` é uma propriedade do objeto `WebAssembly`, não um global: teste-o com `e instanceof WebAssembly.CompileError`.

### WebAssembly.Instance()

`WebAssembly.Instance()` cria um objeto `Instance`, uma instância executável e com estado de um `WebAssembly.Module`.

```javascript
new WebAssembly.Instance(module, importObject)
```

| Parâmetro      | Tipo                 | Obrigatório | Descrição                                                                                |
| -------------- | -------------------- | ----------- | ---------------------------------------------------------------------------------------- |
| `module`       | `WebAssembly.Module` | Sim         | Módulo a instanciar.                                                                     |
| `importObject` | Object               | Não         | Valores a importar para a nova `Instance`, como funções ou objetos `WebAssembly.Memory`. |

Este exemplo compila o módulo `add` e o instancia de forma síncrona:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 7, 1, 3, 97, 100, 100, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11]);

const mod = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(mod, {});
console.log(instance.exports.add(1, 1)); // 2
```

### WebAssembly.LinkError()

`WebAssembly.LinkError()` cria um objeto `LinkError`, que indica um erro durante a instanciação do módulo, além dos traps da função start.

```javascript
new WebAssembly.LinkError()
new WebAssembly.LinkError(message)
new WebAssembly.LinkError(message, fileName)
new WebAssembly.LinkError(message, fileName, lineNumber)
```

| Parâmetro    | Tipo   | Obrigatório | Descrição                                                 |
| ------------ | ------ | ----------- | --------------------------------------------------------- |
| `message`    | String | Não         | Descrição legível do erro.                                |
| `fileName`   | String | Não         | Nome do arquivo que contém o código que causou a exceção. |
| `lineNumber` | Number | Não         | Número da linha do código que causou a exceção.           |

Este exemplo lança um `LinkError` e o lê em um bloco `catch`:

```javascript
try {
  throw new WebAssembly.LinkError('Hello', 'someFile', 10);
} catch (e) {
  console.log(e instanceof WebAssembly.LinkError); // true
  console.log(e.message);                          // "Hello"
  console.log(e.name);                             // "LinkError"
  console.log(e.stack);                            // the location where the code ran
}
```

`LinkError` é uma propriedade do objeto `WebAssembly`, não um global: teste-o com `e instanceof WebAssembly.LinkError`.

### WebAssembly.Memory()

`WebAssembly.Memory()` cria um objeto `Memory`. A propriedade `buffer` dele é um `ArrayBuffer` ou `SharedArrayBuffer` redimensionável que contém os bytes brutos de memória que uma `Instance` WebAssembly acessa. Uma memória criada por JavaScript ou por código WebAssembly é acessível e mutável tanto a partir de JavaScript quanto de WebAssembly.

```javascript
new WebAssembly.Memory(memoryDescriptor)
```

| Parâmetro                  | Tipo    | Obrigatório | Padrão  | Descrição                                                                                                                                                                                                                                                                              |
| -------------------------- | ------- | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `memoryDescriptor.initial` | Number  | Sim         | —       | Tamanho inicial da memória, em páginas WebAssembly.                                                                                                                                                                                                                                    |
| `memoryDescriptor.maximum` | Number  | Não         | —       | Tamanho máximo que a memória pode atingir, em páginas WebAssembly. Quando presente, indica ao mecanismo que reserve memória antecipadamente; o mecanismo pode ignorar ou limitar a reserva. Uma memória não compartilhada não precisa de um máximo; uma memória compartilhada precisa. |
| `memoryDescriptor.shared`  | Boolean | Não         | `false` | Define se a memória é uma memória compartilhada. Defina como `true` para uma memória compartilhada.                                                                                                                                                                                    |

Este exemplo cria uma memória de 10 páginas que pode crescer até 100 páginas:

```javascript
var memory = new WebAssembly.Memory({initial:10, maximum:100});
console.log(memory.buffer.byteLength); // 655360
```

Com `initial` definido como `10`, o buffer contém 655.360 bytes, portanto uma página WebAssembly contém 65.536 bytes.

Este exemplo cria uma memória compartilhada. O `buffer` dela é um `SharedArrayBuffer`:

```javascript
let memory = new WebAssembly.Memory({initial:10, maximum:100, shared:true});
console.log(memory.buffer.constructor.name); // "SharedArrayBuffer"
```

### WebAssembly.Module()

`WebAssembly.Module()` cria um objeto `Module`, que contém código WebAssembly sem estado, já compilado, que pode ser instanciado várias vezes. O construtor compila o código binário de forma síncrona. A principal forma de obter um `Module` é uma função de compilação assíncrona, como `WebAssembly.compile()`.

```javascript
new WebAssembly.Module(bufferSource)
```

| Parâmetro      | Tipo                         | Obrigatório | Descrição                                    |
| -------------- | ---------------------------- | ----------- | -------------------------------------------- |
| `bufferSource` | Typed array ou `ArrayBuffer` | Sim         | Código binário do módulo `.wasm` a compilar. |

Este exemplo compila o módulo `add` de forma síncrona e depois o instancia com `WebAssembly.instantiate()`:

```javascript
const bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 7, 7, 1, 3, 97, 100, 100, 0, 0, 10, 9, 1, 7, 0, 32, 0, 32, 1, 106, 11]);

const mod = new WebAssembly.Module(bytes);
WebAssembly.instantiate(mod).then((instance) => {
  console.log(instance.exports.add(40, 2)); // 42
});
```

### WebAssembly.RuntimeError()

`WebAssembly.RuntimeError()` cria um objeto `RuntimeError`, o tipo que o WebAssembly lança sempre que especifica um trap.

```javascript
new WebAssembly.RuntimeError()
new WebAssembly.RuntimeError(message)
new WebAssembly.RuntimeError(message, fileName)
new WebAssembly.RuntimeError(message, fileName, lineNumber)
```

| Parâmetro    | Tipo   | Obrigatório | Descrição                                                                               |
| ------------ | ------ | ----------- | --------------------------------------------------------------------------------------- |
| `message`    | String | Não         | Descrição legível do erro.                                                              |
| `fileName`   | String | Não         | Nome do arquivo que contém o código que causou a exceção. O objeto de erro não o expõe. |
| `lineNumber` | Number | Não         | Número da linha do código que causou a exceção. O objeto de erro não o expõe.           |

Este exemplo lança um `RuntimeError` e o lê em um bloco `catch`. O construtor aceita `fileName` e `lineNumber`, mas `e.fileName`, `e.lineNumber` e `e.columnNumber` são lidos como `undefined`:

```javascript
try {
  throw new WebAssembly.RuntimeError('Hello', 'someFile', 10);
} catch (e) {
  console.log(e instanceof WebAssembly.RuntimeError); // true
  console.log(e.message);                             // "Hello"
  console.log(e.name);                                // "RuntimeError"
  console.log(e.fileName);                            // undefined
  console.log(e.lineNumber);                          // undefined
  console.log(e.columnNumber);                        // undefined
  console.log(e.stack);                               // "RuntimeError: Hello", then the call stack
}
```

### WebAssembly.Table()

`WebAssembly.Table()` cria um objeto `Table` com o tamanho e o tipo de elemento informados.

```javascript
new WebAssembly.Table(tableDescriptor)
```

| Parâmetro                 | Tipo   | Obrigatório | Descrição                                                                                                |
| ------------------------- | ------ | ----------- | -------------------------------------------------------------------------------------------------------- |
| `tableDescriptor.element` | String | Sim         | Tipo de valor que a tabela armazena: `"anyfunc"` para funções ou `"externref"` para referências de host. |
| `tableDescriptor.initial` | Number | Sim         | Número inicial de elementos da tabela.                                                                   |
| `tableDescriptor.maximum` | Number | Não         | Número máximo de elementos até o qual a tabela pode crescer.                                             |

Este exemplo cria uma tabela de duas funções, lê o comprimento e os elementos dela e adiciona a tabela a um objeto de importação:

```javascript
var tbl = new WebAssembly.Table({initial:2, element:"anyfunc"});
var len = tbl.length;  // 2
var v1 = tbl.get(0);  // null
var v2 = tbl.get(1);  // null

// Creating an import object that contains the table
var importObj = {
  js: {
    tbl:tbl
  }
};
```

### WebAssembly.Tag()

`WebAssembly.Tag()` cria um objeto `WebAssembly.Tag`.

```javascript
new WebAssembly.Tag(type)
```

| Parâmetro         | Tipo             | Obrigatório | Descrição                                                                                                                 |
| ----------------- | ---------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- |
| `type.parameters` | Array de strings | Sim         | Tipos de dados dos valores que a tag carrega: `"i32"`, `"i64"`, `"f32"`, `"f64"`, `"v128"`, `"externref"` ou `"anyfunc"`. |

O construtor lança um `TypeError` quando `type.parameters` não é fornecido, não contém nenhum valor ou contém um descritor de tag não suportado.

Este exemplo cria uma tag com dois valores:

```javascript
const tag = new WebAssembly.Tag({ parameters: ["i32", "i64"] });
```

### WebAssembly.Exception()

`WebAssembly.Exception()` cria um objeto `WebAssembly.Exception`. O construtor recebe uma `Tag` e um array de payload com campos de dados. O tipo de dados de cada elemento do payload precisa corresponder ao tipo de dados correspondente da `Tag`.

```javascript
new WebAssembly.Exception(tag, payload, options)
```

| Parâmetro            | Tipo              | Obrigatório | Padrão  | Descrição                                                                                                                                                |
| -------------------- | ----------------- | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tag`                | `WebAssembly.Tag` | Sim         | —       | Tag que define o tipo de dados de cada valor do payload.                                                                                                 |
| `payload`            | Array             | Sim         | —       | Um ou mais campos de dados que compõem o payload da exceção. Os elementos precisam corresponder aos tipos de dados dos elementos correspondentes da tag. |
| `options.traceStack` | Boolean           | Não         | `false` | `true` quando o código WebAssembly que lança a exceção pode anexar um stack trace à propriedade `stack` da exceção.                                      |

O construtor lança um `TypeError` quando o payload e a tag não têm o mesmo número de elementos ou quando os elementos não são de tipos correspondentes.

Este exemplo cria uma tag e a usa para criar uma exceção, depois lê a exceção de volta:

```javascript
// Create tag and use it to create an exception
const tag = new WebAssembly.Tag({ parameters: ["i32", "f32"] });
const exception = new WebAssembly.Exception(tag, [42, 42.3]);
console.log(exception.is(tag)); // true
console.log(exception.getArg(tag, 0)); // 42
console.log(exception.getArg(tag, 1)); // 42.29999923706055
```

O segundo valor é lido como `42.29999923706055` porque a tag o armazena como um `f32`, um float de 32 bits.

---

## Recursos relacionados

- [fetch](/pt-br/documentacao/devtools/runtime/api-reference/fetch.md): Como uma function baixa um arquivo `.wasm` antes de compilar o módulo.
- [Response](/pt-br/documentacao/devtools/runtime/api-reference/response.md): O objeto em que `fetch()` resolve, que carrega os bytes do módulo no corpo dele.
- [Padrões web](/pt-br/documentacao/devtools/runtime/api-reference/web-standards.md): Os padrões JavaScript e Web que o Azion Runtime implementa.
- [Web APIs](/pt-br/documentacao/devtools/runtime/api-reference/javascript.md): As outras Web APIs que o Azion Runtime suporta.
