I am able to build programs using upstream LLVM and clang, with a self-compiled wasi-libc sysroot, and I can run them locally using wasmtime (mostly, I ran into some issues with tmpfile not being defined in wasi-libc at link time, but that's not a wasmtime problem). I've been trying to find a way to run these wasm files on a browser, but it looks like I need some polyfill for WASI. Some time ago there was a WASI polyfill available for browsers (I guess there's still a version of it lying around at https://wasi.dev/polyfill/), but that older version doesn't work with some namespace changes done on WASI (looks like the namespace now is called wasi_snapshot_preview1).
Looks like there was some work to move the polyfill implementation to Rust, but that seems to have stalled (https://github.com/bytecodealliance/wasmtime/pull/720 , waiting on a generator implementation using *.witx files?).
I guess my question is if there is any way to experiment with WASI on a modern web browser?
There are a few different options; could you say more about what specifically you're looking to do?
I'm mostly just trying to learn the ecosystem and how everything ties together. I was mostly curious if there was a more up-to-date polyfill available, as the one in https://wasi.dev/polyfill/ doesn't seem to be compatible anymore (I might be able to hack something from it to make it work again?).
The application I'm trying to run as an experiment right now is something I wrote over the summer (https://gitlab.com/gemarcano/libspc_tag), just a simple command-line parser for SNES .spc metadata. I'm not even trying to get it to read in data, just to run and print the help string as a proof of concept (even if running means sending all output to console.log).
From converting the wasm file to a .wat file, these are the required imports:
(import "wasi_snapshot_preview1" "proc_exit" (func (;0;) (type 4)))
(import "wasi_snapshot_preview1" "args_sizes_get" (func (;1;) (type 1)))
(import "wasi_snapshot_preview1" "args_get" (func (;2;) (type 1)))
(import "wasi_snapshot_preview1" "fd_prestat_get" (func (;3;) (type 1)))
(import "wasi_snapshot_preview1" "fd_prestat_dir_name" (func (;4;) (type 0)))
(import "wasi_snapshot_preview1" "fd_fdstat_get" (func (;5;) (type 1)))
(import "wasi_snapshot_preview1" "path_open" (func (;6;) (type 13)))
(import "wasi_snapshot_preview1" "fd_close" (func (;7;) (type 2)))
(import "wasi_snapshot_preview1" "fd_fdstat_set_flags" (func (;8;) (type 1)))
(import "wasi_snapshot_preview1" "fd_read" (func (;9;) (type 7)))
(import "wasi_snapshot_preview1" "fd_seek" (func (;10;) (type 14)))
(import "wasi_snapshot_preview1" "fd_write" (func (;11;) (type 7)))
As an actual goal a little further down the line, I have an ARM emulator written in C that I would like to run inside a web browser (https://github.com/lab11/M-ulator). I'm in the process of refactoring it to make it easier to run in single-threaded environments.
In reality, I don't think I need all of the file IO functions for either program, as I should be able to have JS code read in whatever into the webasm memory and just pass those buffers around if I call the underlying functions manually from Javascript.
Most of the WASI ecosystem right now is focused on non-browser use cases, but there are a few polyfills which may get you pretty close: https://github.com/bjorn3/rust/blob/compile_rustc_wasm4/rustc.html
https://github.com/WebAssembly/waterfall/blob/master/src/wasi.js is another
I just wrote my own custom polyfill since none of the ones I saw seemed to be updated recently:
https://salsa.debian.org/Kazan-team/power-cpu-sim/-/blob/master/index.html
Thanks for all the pointers! I'll take a look at them.
Worst case scenario, I think I might be able to get away by stubbing all of the IO related required imports since I don't think I'll actually need them for what I'm trying to run in the web, so long as I can export some of the underlying functions used in the programs so I can call them from Javascript directly.
Last updated: Dec 23 2024 at 12:05 UTC