Skip to content

Tracking: standalone WASI target (--target wasi, wasm32-wasip2) #11375

Open
5 of 6 issues completed
Open

Description

@proggeramlug

Goal

Compile a Perry program to a standalone .wasm that runs under a WASI runtime (wasmtime, wasmer, …) with no JavaScript host, independent of the existing browser --target wasm/web.

Why not extend perry-codegen-wasm

The browser backend is a thin emitter: strings, objects, arrays, closures, JSON etc. are ~250 functions imported from wasm_runtime.js (~5k lines, values live on the JS heap). A WASI host has no JS, so reusing it would mean re-implementing that whole runtime inside the module — a second runtime that shares nothing with perry-runtime, where Perry's Node parity actually lives.

Chosen route

The native LLVM pipeline targeting wasm32-wasip2 (Tier-2 Rust target, prebuilt std), linked against perry-runtime built for that target.

  • GC: Perry keeps its own collector in linear memory (as Go/.NET do). Wasm code cannot scan its own stack, so roots come from the existing shadow-stack fallback that codegen already uses on targets without a frame walker. Wasm GC (Wasm 3.0) is not usable here — LLVM cannot emit GC types — and would only matter for a separate, future browser backend with a non-NaN-boxed value representation.
  • Networking: available on preview 2 (wasi:sockets, ip-name-lookup, wasi:http). socket2 (with all) builds for wasm32-wasip2 but not wasm32-wasip1. Needs a WASI event-loop backend (turnloop is compiled out on wasm).
  • Threads: wasm32-wasip1-threads exists but has no preview-2 equivalent yet. Default: parallelMap/parallelFilter run sequentially, spawn runs on the main thread (correct, not parallel). A threaded build can come later.
  • Child processes: no WASI proposal provides process spawning; child_process throws a clear "not supported on WASI" error.
  • Exceptions: runtime + generated code use setjmp/longjmp → LLVM's wasm SjLj lowering on the exception-handling proposal, wasi-libc libsetjmp, and a runtime with EH enabled.

Measured starting point (2026-09-26)

cargo check -p perry-runtime --target wasm32-wasip1 --no-default-features:

  • blocked first by unconditional socket2/hickory-proto and the perry_sjlj.c build (no WASI sysroot);
  • with those gated off: 61 name-resolution-stage errors (a floor — type-check errors surface after). Two families: 64-bit assumptions (FRAME_RELEASED: usize = 1 << 63, offset_of!(ObjectHeader, meta) == 8, Map/Set/HotTls/shadow-stack/Box layout asserts) and platform code without a WASI arm (child_process/turnloop_proc, DNS, eh.rs dladdr/unwind regs, date.rs local time).

The ILP32 family also means arm64_32-apple-watchos no longer builds — nothing in CI checks a 32-bit target.

Phases

  • 1. perry-runtime builds for 32-bit (ILP32) targets; CI cargo check arm so it stays that way
  • 2. WASI arms for platform code (fs via preopens, UTC-only local time, sockets/DNS via wasip2, sequential threads, child_process unsupported, event-loop backend)
  • 3. Codegen: initialize the WebAssembly LLVM backend, shadow-stack roots, SjLj via wasm EH
  • 4. --target wasi: wasm-ld/component link, .wasm output, wasmtime smoke test
  • 5. CI: gap-suite subset under a WASI runtime

Activity

  1. proggeramlug commented on Oct 8, 2026

    @proggeramlug
    ContributorAuthor

    Progress: #12208 (complete standalone WASIp2 acceptance support) is merged. Leaving this tracking issue open for the remaining items.

  2. guest271314 commented on Oct 11, 2026

    @guest271314

    @proggeramlug So is this in the latest release on NPM?

  3. proggeramlug commented on Oct 11, 2026

    @proggeramlug
    ContributorAuthor

    @guest271314 not yet on npm, I'll tag you once this is the case. this is on latest main only thus far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions