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: