00
:
00
:
00
:
00
Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

JavaScript API

L’oggetto globale WebAssembly

Il browser espone l’oggetto WebAssembly con metodi per caricare, compilare e istanziare moduli .wasm.

WebAssembly.instantiateStreaming()

Il metodo raccomandato per caricare Wasm. Compila e istanzia mentre il download è ancora in corso (streaming).

const importObject = {
  env: {
    log: (value) => console.log("Da Wasm:", value),
    abort: () => { throw new Error("abort chiamato"); },
  },
};

// Metodo preferito: streaming
const { module, instance } = await WebAssembly.instantiateStreaming(
  fetch("calculator.wasm"),
  importObject
);

// Chiamare una funzione esportata
const result = instance.exports.add(10, 20);
console.log(result); // 30

Nota: il server deve restituire il file con Content-Type application/wasm, altrimenti instantiateStreaming fallisce.

WebAssembly.instantiate()

Versione non-streaming: riceve un ArrayBuffer già completo. Utile quando il .wasm proviene da fonti diverse dalla rete.

// Caricamento da ArrayBuffer
const response = await fetch("calculator.wasm");
const bytes = await response.arrayBuffer();

const { module, instance } = await WebAssembly.instantiate(
  bytes,
  importObject
);

console.log(instance.exports.multiply(6, 7)); // 42

WebAssembly.compile() e WebAssembly.Module

Puoi separare la compilazione dall’istanziazione. Questo è utile per creare più istanze dallo stesso modulo.

// Compilare il modulo una sola volta
const module = await WebAssembly.compileStreaming(fetch("game.wasm"));

// Creare più istanze con import diversi
const instance1 = await WebAssembly.instantiate(module, importObj1);
const instance2 = await WebAssembly.instantiate(module, importObj2);

WebAssembly.Module può anche essere inviato a un Web Worker tramite postMessage:

// Thread principale
const module = await WebAssembly.compileStreaming(fetch("heavy.wasm"));
worker.postMessage({ module }); // Module è "structured cloneable"

// Nel Worker
self.onmessage = async (e) => {
  const instance = await WebAssembly.instantiate(e.data.module, imports);
  // Usare instance...
};

WebAssembly.Instance

L’istanza è l’oggetto che contiene le funzioni e la memoria esportate.

const { instance } = await WebAssembly.instantiateStreaming(
  fetch("math.wasm"),
  {}
);

// Accedere alle export
console.log(instance.exports);
// { add: [Function], sub: [Function], memory: Memory }

// Chiamare funzioni
instance.exports.add(1, 2); // 3

// Accedere alla memoria esportata
const mem = new Uint8Array(instance.exports.memory.buffer);

L’importObject

L’oggetto di import fornisce al modulo Wasm tutto ciò di cui ha bisogno dall’esterno. La struttura deve corrispondere esattamente alle dichiarazioni import nel modulo.

;; Il modulo WAT si aspetta queste import
(module
  (import "env" "log" (func $log (param i32)))
  (import "env" "memory" (memory 1))
  (import "math" "sqrt" (func $sqrt (param f64) (result f64)))
)
// L'importObject deve rispecchiare i namespace
const importObject = {
  env: {
    log: (val) => console.log(val),
    memory: new WebAssembly.Memory({ initial: 1 }),
  },
  math: {
    sqrt: Math.sqrt,
  },
};

Esportare Funzioni da Diversi Linguaggi

Da C (Emscripten):

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int square(int x) {
    return x * x;
}

Da Rust (wasm-bindgen):

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn square(x: i32) -> i32 {
    x * x
}

Da AssemblyScript:

export function square(x: i32): i32 {
  return x * x;
}

In tutti i casi, dopo la compilazione, la funzione square sarà disponibile in instance.exports.square.

Pattern di Caricamento Completo

async function loadWasm(url, imports = {}) {
  try {
    // Provare streaming per prima cosa
    return await WebAssembly.instantiateStreaming(fetch(url), imports);
  } catch {
    // Fallback per server senza Content-Type corretto
    const response = await fetch(url);
    const bytes = await response.arrayBuffer();
    return await WebAssembly.instantiate(bytes, imports);
  }
}

// Uso
const { instance } = await loadWasm("app.wasm", {
  env: { log: console.log },
});

Questo pattern con fallback garantisce la compatibilità anche quando il server non serve il MIME type corretto.