Back to Wasm Bindgen

WebAssembly JSPI + OPFS example

examples/jspi-opfs/index.html

0.2.1282.1 KB
Original Source

WebAssembly JSPI + OPFS example

JSPI lets plain (non-async) Rust functions await JS Promises by suspending the WASM fiber — without blocking the event loop. This example applies that to the browser's Origin Private File System (OPFS), whose entire API surface is Promise-based.

WebAssembly.Suspending``navigator.storage.getDirectoryWASM module

How it works

wasm-bindgen-futuresJSPI
Rust call styleasync fnordinary fn
Awaiting Promises.awaitblock_on_promise()
Event loop blocked?nono
Needs async call chain?yesno

Four OPFS operations — each requires multiple Promise awaits — are exposed as plain Rust functions via #[wasm_bindgen(jspi)]:

// ── write a file ─────────────────────────────────────#[wasm\_bindgen(jspi)]pub fnopfs\_write(path: String, content: String) {letroot =opfs\_root();// suspends onceletfh = block_on_promise(&root.get\_file\_handle\_with\_options(...));letwr = block_on_promise(&fh.create\_writable());// suspends againblock_on_promise(&wr.write\_with\_str(&content));
    block_on_promise(&WritableStream::close(&wr));
}// ── read a file ──────────────────────────────────────#[wasm\_bindgen(jspi)]pub fnopfs\_read(path: String) -> String {letfh: FileSystemFileHandle = block_on_promise(&opfs\_root()
        .get\_file\_handle(&path)).dyn\_into()...;letfile: File = block_on_promise(&fh.get\_file()).dyn\_into()...;
    block_on_promise(&Blob::text(&file)).as\_string()...
}

The generated JS glue wraps each export with WebAssembly.promising, so JavaScript callers simply await the result as usual.

Live demo

File path (OPFS key)

ContentHello from plain Rust via JSPI + OPFS! Second line here 🦀

WriteReadHas?Delete▶ Run all

clear