Tiny Async Wasi Preview 2 Runtime
wasm wasi preview2 async runtime rust
Rust 99.9%
Other 0.1%
50 1 0

Clone this repository

https://tangled.org/staticanxiety.tngl.sh/tiny-wasm-async-runtime https://tangled.org/did:plc:v62vibqsvvdxjwcrg66fch7e/tiny-wasm-async-runtime
git@tangled.org:staticanxiety.tngl.sh/tiny-wasm-async-runtime git@tangled.org:did:plc:v62vibqsvvdxjwcrg66fch7e/tiny-wasm-async-runtime

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

tiny-async-runtime#

tiny-async-runtime is a minimal, WASI-compatible async runtime designed to run on WebAssembly with WASI Preview 2. It provides:

  • Single-threaded cooperative task scheduling
  • Futures spawning and cancellation
  • Timeout support
  • Socket I/O integration
  • File IO integration

This runtime is inspired by mio but is purpose-built for WASI environments.

Running In The Right Environment#

This crate is meant to be validated in a WASI Preview 2 host, not as a plain native executable.

  • The socket support depends on Preview 2 imports from wit/world.wit.
  • Native host runs such as cargo test on Windows or Linux do not provide those imports.
  • The intended validation path is cargo test --target wasm32-wasip2, executed under wasmtime.

The repository already includes a target runner in .cargo/config.toml, so if wasmtime is installed you can run:

cargo test --target wasm32-wasip2
cargo run --target wasm32-wasip2 --example basic_usage

Features#

  • block_on() Runs an async function to completion, driving timers, I/O readiness, and spawned tasks.

  • #[tiny_wasm_runtime::main] Wraps an async fn in WasmRuntimeAsyncEngine::block_on(...), similar to tokio::main.

  • spawn() Launches a future in the runtime. Returns a JoinHandle for cancellation or awaiting completion.

  • Timers

    • Timer::sleep(duration) creates a future that resolves after a given time.
    • Timer futures integrate into the same event loop.
  • Cancellation

    • Calling JoinHandle::cancel() removes the task from the scheduler.
    • Owned timers and pollables are cleaned up when a task is canceled.
    • Awaiting a canceled join handle still does not return a structured cancellation result.
  • Partial socket support

    • The current implementation covers connect, accept, read, and write flows on top of WASI Preview 2 sockets.

Example#

Here is a minimal example using block_on and spawn:

use tiny_wasm_runtime::{Timer, WasmRuntimeAsyncEngine};

fn main() {
    WasmRuntimeAsyncEngine::block_on(async {
        let handle = WasmRuntimeAsyncEngine::spawn(async {
            Timer::sleep(std::time::Duration::from_secs(1)).await;
            42
        });

        let result = handle.await;
        println!("Background task returned: {result}");
    });
}

You can also use the attribute macro:

use tiny_wasm_runtime::{Timer, WasmRuntimeAsyncEngine};

#[tiny_wasm_runtime::main]
async fn main() {
    let handle = WasmRuntimeAsyncEngine::spawn(async {
        Timer::sleep(std::time::Duration::from_millis(25)).await;
        12
    });

    println!("Result: {}", handle.await);
}

Validated Example#

A runnable example lives at examples/basic_usage.rs.

It demonstrates:

  • WasmRuntimeAsyncEngine::block_on
  • WasmRuntimeAsyncEngine::spawn
  • Timer::sleep
  • Timer::timeout

Run it in the Preview 2 environment with:

cargo run --target wasm32-wasip2 --example basic_usage

There is also a macro-based example at examples/macro_main.rs:

cargo run --target wasm32-wasip2 --example macro_main

More Docs#

For a deeper walkthrough, see:

  • docs/ARCHITECTURE.md
  • docs/DEVELOPMENT.md