WebAssembly Targets

Compile Tish to WebAssembly for browser or Wasmtime.

Tish compiles to two self-contained WebAssembly targets, plus a raw bytecode chunk for hosts that already ship the VM runtime:

TargetOutputRuntimeUse when
wasm.wasm + .js + .htmlBrowserDeploy to web
wasiSingle .wasmWasmtime, wasmer, etc.CLI, serverless, edge
bytecodeSingle file (raw chunk)A tish VM runtime you already shipCustom embeds & bundlers

Browser (wasm)

Produces files for browser execution:

  • {output}_bg.wasm — VM binary
  • {output}.js — wasm-bindgen glue
  • {output}.html — Loader (open via local server for CORS)
tish build hello.tish -o app --target wasm

Requirements: rustup target add wasm32-unknown-unknown, cargo install wasm-bindgen-cli

Serve and open in a browser:

python3 -m http.server 8765
# Visit http://localhost:8765/app.html

Wasmtime/WASI (wasi)

Produces a single .wasm file with embedded bytecode. Run with Wasmtime or any WASI-compatible runtime:

tish build hello.tish -o app --target wasi
wasmtime app.wasm

Requirements: rustup target add wasm32-wasip1, install Wasmtime

Known limitations (WASI)

WASI output uses the bytecode VM (same runtime as Cranelift). The same subset of Tish that works with Cranelift works with WASI. Some constructs and builtins may fail or produce incomplete output. For full compatibility, prefer the Rust native backend or the JS target.

Bytecode chunk (bytecode)

Emits only the serialized bytecode program — no VM binary, no wasm-bindgen glue, no HTML loader:

tish build hello.tish -o app.tbc --target bytecode

This is the exact byte sequence that --target wasm embeds (as base64) inside its generated HTML loader, written out raw. Use it when the host already ships the tish VM runtime and only needs the program to run — for example a web app that builds tishlang_wasm_runtime once with wasm-bindgen and then fetches the chunk as a separate, cacheable asset:

import init, { run } from './tish_vm.js';   // your prebuilt VM runtime (wasm-bindgen)
await init('./tish_vm_bg.wasm');
const chunk = new Uint8Array(await (await fetch('./app.tbc')).arrayBuffer());
run(chunk);                                  // deserialize + execute

Unlike --target wasm, nothing is built or discarded: no standalone VM .wasm, no .js, no .html. This makes it ideal for bundlers (Vite, esbuild, …) that fingerprint the runtime and the bytecode chunk as independent assets, and for custom embeddings whose runtime exposes its own entry (e.g. a WebGPU host's start(chunk, env)).

Requirements: none beyond the tish CLI — the host supplies the runtime.

For Node.js or bundlers (no WebAssembly), use:

tish build hello.tish -o app --target js
node app.js

Improve this documentation