Happen to know this particular fellow who authored the lib from the Deno discord (really brilliant, nice guy) and he took the time to explain the same question to me earlier in writing this.
This is the gist of it:
- WASM is sandboxed. The shortest way to explain it is that anything that uses a syscall won't work. These syscalls include things like networking and filesystem access.
- WASI is a standard interface/specification for WASM. What it does is provide a spec of function signatures for syscalls, and provide the compile-time swap of stdlib functions that use these.
For example, Rust’s "open" (and I believe C's "fopen") is implemented by calling "(__wasi_)path_open" when it’s compiled to WebAssembly via WASI. And "path_open" is meant to act like the "openat" syscall.
You can already run other languages compiled to WASM on Deno, by just loading the .wasm file bytes and instantiating.
You can also run native code in Deno through Rust "native Ops"/plugins. This can be pure Rust, or Rust calling C/C++ externs, etc.
So what is the point then, why bother?
WASI allows you to compile and run programs which have behavior that requires syscalls, and hopefully get the functionality fully emulated.
So with an implemented WASI interface in a language, then you can take some compiled WASM lib using WASI and (mostly) assume it'll run in that environment too.
---
Edit: Also a note, I have fairly little understanding of low-level programming so I may have butchered this. I make no claims to accuracy, this is my rough understanding.
Edit2: What really helped my understanding was looking at the Typescript implementation of these syscalls, so here you can see the implementation of "path_open" in TS that provides WASI the functionality it needs for using that method:
To expand, this functionality is of course not unique. There are numerous WASM runtimes out there, like wasmtime [1] or wasmer [2].
The interesting aspects of using Deno for this are:
a) v8 is bound to have a high quality wasm JIT and already has a sophisticated sandbox (although JS and the browser context probably bring in a lot of complexity that a pure WASM sandbox doesn't have to deal with)
b) easy interop with Javascript/Typescript code
c) Deno is experimenting with finer grained permission based sandboxing, so this fits well within the domain
Just to clarify my understanding, none of this is free though, right? If I understand correctly, every WASI will have to be maintained to achieve and preserve feature parity as new features are added to the language or, in the worst case, a breaking change is introduced.
This may be a naive question, but this is also only for server-side code, right? Would you be making these kinds of syscalls in code you deploy to the client? Forgive me, I'm not entirely up to speed on webasm.
> Just to clarify my understanding, none of this is free though, right? If I understand correctly, every WASI will have to be maintained to achieve and preserve feature parity as new features are added to the language or, in the worst case, a breaking change is introduced.
WASI is versioned by namespace, which is just a prefix for the modules; so v1 and v2 of WASI may in theory actually have nothing in common so the runtime needs to support that particular version of the interface.
e.g; a module compiled today with only the MVP WebAssembly features targeting wasi_snapshot_preview1 (the current version) today should continue to run just fine as long as the runtime doesn't drop support for that version of WASI.
Features in WebAssembly itself do not necessarily require a rewrite, at-least in the current specification but it depends what happens going forward.
> This may be a naive question, but this is also only for server-side code, right? Would you be making these kinds of syscalls in code you deploy to the client? Forgive me, I'm not entirely up to speed on webasm.
Browsers too; e.g a browser game or app can use standard library i/o which calls into WASI; altho my web-wasi implementation is not up to par at the moment as I'm waiting for the outcome of a proposal Emscripten's kripken put out on how to deal with async/await in browsers.
This is the gist of it:
- WASM is sandboxed. The shortest way to explain it is that anything that uses a syscall won't work. These syscalls include things like networking and filesystem access.
- WASI is a standard interface/specification for WASM. What it does is provide a spec of function signatures for syscalls, and provide the compile-time swap of stdlib functions that use these.
For example, Rust’s "open" (and I believe C's "fopen") is implemented by calling "(__wasi_)path_open" when it’s compiled to WebAssembly via WASI. And "path_open" is meant to act like the "openat" syscall.
You can already run other languages compiled to WASM on Deno, by just loading the .wasm file bytes and instantiating.
You can also run native code in Deno through Rust "native Ops"/plugins. This can be pure Rust, or Rust calling C/C++ externs, etc.
So what is the point then, why bother?
WASI allows you to compile and run programs which have behavior that requires syscalls, and hopefully get the functionality fully emulated.
So with an implemented WASI interface in a language, then you can take some compiled WASM lib using WASI and (mostly) assume it'll run in that environment too.
---
Edit: Also a note, I have fairly little understanding of low-level programming so I may have butchered this. I make no claims to accuracy, this is my rough understanding.
Edit2: What really helped my understanding was looking at the Typescript implementation of these syscalls, so here you can see the implementation of "path_open" in TS that provides WASI the functionality it needs for using that method:
https://deno.land/x/wasi/mod.ts#L881