intermediate
Using WebAssembly
Compile Draft to WebAssembly, integrate with JavaScript, and build browser-based applications.
Learning Objectives
- Compile Draft to WASM
- Load and run WASM in the browser
- Call Draft functions from JavaScript
- Pass data between JS and WASM
Prerequisites
- Completed Building an HTTP Server
- Basic knowledge of JavaScript and the browser
Compiling to WASM
Create a Draft library that exports functions:
export action add(a, b) return a + bfin action.
export action multiply(a, b) return a * bfin action.
export action greet(name) return "Hello, " + name + "!"fin action.Compile to WASM:
draft build math.draft --target wasm -o math.wasmThis produces math.wasm and a JavaScript glue file math.js.
Browser Integration
Create an index.html file:
<!DOCTYPE html><html><head> <title>Draft + WASM</title></head><body> <h1>Draft in the Browser</h1> <div id="output"></div>
<script type="module"> import { add, multiply, greet } from "./math.js";
const output = document.getElementById("output");
const sum = add(10, 20); output.innerHTML += `<p>10 + 20 = ${sum}</p>`;
const product = multiply(6, 7); output.innerHTML += `<p>6 × 7 = ${product}</p>`;
const message = greet("Draft"); output.innerHTML += `<p>${message}</p>`; </script></body></html>Serve the directory with any static file server:
npx serve .Open http://localhost:3000 in your browser.
JavaScript Interop
Calling JS from Draft
Use the js module to call JavaScript functions:
import js
action main() @timestamp = js.now() write("Timestamp: " + timestamp)fin action.Passing Callbacks
Pass JavaScript functions to Draft:
import { processItems } from "./app.js";
function onProgress(percent) { console.log("Progress: " + percent + "%");}
processItems(items, onProgress);export action processItems(items, callback) loop i from 0 to items.length - 1 callback((i / items.length) * 100) againfin action.Complete Example: Todo List in the Browser
import js
export action init_todos() @stored = js.localStorage_get("todos") if stored then return json.decode(stored) else return [] fifin action.
export action add_todo(todos, title) @new_todo = { id: todos.length + 1, title: title, done: false } todos.push(new_todo) js.localStorage_set("todos", json.encode(todos)) return todosfin action.
export action toggle_todo(todos, id) loop i from 0 to todos.length - 1 if todos[i].id == id then todos[i].done = not todos[i].done fi again js.localStorage_set("todos", json.encode(todos)) return todosfin action.
export action delete_todo(todos, id) loop i from 0 to todos.length - 1 if todos[i].id == id then todos.remove(i) fi again js.localStorage_set("todos", json.encode(todos)) return todosfin action.<!DOCTYPE html><html><head> <title>Draft Todo</title></head><body> <h1>Draft Todo</h1> <input type="text" id="taskInput" placeholder="New task"> <button onclick="addTask()">Add</button> <ul id="taskList"></ul>
<script type="module"> import { init_todos, add_todo, toggle_todo, delete_todo } from "./todo.js";
let todos = init_todos(); render();
async function addTask() { const input = document.getElementById("taskInput"); const title = input.value.trim(); if (title) { todos = add_todo(todos, title); input.value = ""; render(); } }
async function toggleTask(id) { todos = toggle_todo(todos, id); render(); }
function render() { const list = document.getElementById("taskList"); list.innerHTML = ""; for (const todo of todos) { const li = document.createElement("li"); li.textContent = (todo.done ? "[x] " : "[ ] ") + todo.title; li.onclick = () => toggleTask(todo.id); list.appendChild(li); } } </script></body></html>Try It Yourself
- Save the Draft code as
todo.draftand compile to WASM. - Create
index.htmlwith the JavaScript code. - Serve the directory and open it in your browser.
- Add, toggle, and delete tasks.
Checkpoint
-
What flag compiles Draft to WASM?
--target wasm--wasm--output wasm
-
How do you persist data in the browser from Draft?
js.localStorage_set(key, value)fs.write("key", value)browser.storage.set(key, value)
-
What module provides JavaScript interop?
wasmjsdom
Answers
--target wasmjs.localStorage_set(key, value)js
Summary
You compiled Draft to WebAssembly and integrated it with JavaScript in the browser. WASM lets you run Draft code anywhere with near-native performance.
Next Steps
- Concurrency and Parallelism — Use threads, channels, and async operations.
