Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

WASM

The WASM generator produces a minimal JS loader and README to help get started with wasm32-unknown-unknown. Full ergonomics are planned for future releases.

Generated artifacts

  • generated/wasm/weaveffi_wasm.js — ES module loader with JSDoc
  • generated/wasm/README.md — quickstart and type conventions

Generated code examples

JS loader

The generated loader provides a loadWeaveFFI async function that instantiates a .wasm module and returns its exports:

export async function loadWeaveFFI(url) {
  const response = await fetch(url);
  const bytes = await response.arrayBuffer();
  const { instance } = await WebAssembly.instantiate(bytes, {});
  return instance.exports;
}

Usage:

const wasm = await loadWeaveFFI('lib.wasm');
const sum = wasm.weaveffi_math_add(1, 2);

Type conventions at the WASM boundary

WASM only supports numeric types natively (i32, i64, f32, f64). Complex types are encoded as follows:

Structs

Structs are passed as opaque handles (i64 pointers into linear memory). Use the generated C ABI accessor functions to read/write fields:

// Create a struct (returns i64 handle)
const handle = wasm.weaveffi_contacts_create();

// Read a field via accessor
const age = wasm.weaveffi_contacts_Contact_get_age(handle);

// Destroy when done
wasm.weaveffi_contacts_Contact_destroy(handle);

Enums

Enums are passed as i32 values corresponding to the variant’s integer discriminant:

// 0 = Red, 1 = Green, 2 = Blue
wasm.weaveffi_ui_set_color(0);

Optionals

Optional values use 0 / null to represent the absent case. For numeric optionals, a separate _is_present flag (i32: 0 or 1) is used. For handle-typed optionals, a null pointer (0) signals absence:

// Present optional: (is_present=1, value=5000)
wasm.weaveffi_config_set_timeout(1, 5000);

// Absent optional: (is_present=0, value=0)
wasm.weaveffi_config_set_timeout(0, 0);

Lists

Lists are passed as a pointer + length pair (i32 pointer, i32 length) referencing a contiguous region in linear memory. The caller is responsible for allocating and freeing the backing memory:

// Write data into WASM linear memory
const ptr = wasm.weaveffi_alloc(4 * items.length);
const view = new Int32Array(wasm.memory.buffer, ptr, items.length);
view.set(items);

// Pass pointer + length to the function
wasm.weaveffi_data_process(ptr, items.length);

// Free the memory
wasm.weaveffi_dealloc(ptr, 4 * items.length);

Type mapping reference

IDL typeWASM typeConvention
i32i32Direct value
u32i32Direct value (unsigned interpretation)
i64i64Direct value
f64f64Direct value
booli320 = false, 1 = true
stringi32+i32Pointer + length in linear memory
bytesi32+i32Pointer + length in linear memory
handlei64Opaque 64-bit identifier
StructNamei64Opaque handle (pointer)
EnumNamei32Integer discriminant
T?varies_is_present flag or null pointer
[T]i32+i32Pointer + length in linear memory

Build

macOS

rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --release

Linux

rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --release

The build commands are identical on both platforms since WASM is a cross-compilation target.

Serve the .wasm file and load it with the provided JS helper.