WebAssembly System Interface, or WASI, is a new family of API's being designed by the Wasmtime project to propose as a standard engine-independent non-Web system-oriented API for WebAssembly. Initially, the focus is on WASI Core, an API module that covers files, networking, and a few other things. Additional modules are expected to be added in the future.
WebAssembly is designed to run well on the Web, however it's not limited to the Web. The core WebAssembly language is independent of its surrounding environment, and WebAssembly interacts with the outside world exclusively through APIs. On the Web, it naturally uses the existing Web APIs provided by browsers. However outside of browsers, there's currently no standard set of APIs that WebAssembly programs can be written to. This makes it difficult to create truly portable non-Web WebAssembly programs.
WASI is an initiative to fill this gap, with a clean set of APIs which can be implemented on multiple platforms by multiple engines, and which don't depend on browser functionality (although they still can run in browsers; see below).
The design follows CloudABI's (and in turn Capsicum)'s concept of capability-based security, which fits well into WebAssembly's sandbox model. Files, directories, network sockets, and other resources are identified by UNIX-like file descriptors, which are indices into external tables whose elements represent capabilities. Similar to how core WebAssembly provides no ability to access the outside world without calling imported functions, WASI APIs provide no ability to access the outside world without an associated capability.
For example, instead of a typical open system call, WASI provides an openat-like system call, requiring the calling process to have a file descriptor for a directory that contains the file, representing the capability to open files within that directory. (These ideas are common in capability-based systems.)
However, the WASI libc implementation still does provide an
implementation of open, by taking the approach of
libpreopen.
Programs may be granted capabilities for directories on launch, and
the library maintains a mapping from their filesystem path to the
file descriptor indices representing the associated capabilities.
When a program calls open, they look up the file name in the map,
and automatically supply the appropriate directory capability. It
also means WASI doesn't require the use of CloudABI's program_main
construct. This eases porting of existing applications without
compromising the underlying capability model. See the diagram below
for how libpreopen fits into the overall software architecture.
WASI also automatically provides file descriptors for standard
input and output, and WASI libc provides a normal printf
. In
general, WASI is aiming to support a fairly full-featured libc
implementation, with the current implementation work being based on
musl.
WASI is being designed from the ground up for WebAssembly, with sandboxing, portability, and API tidiness in mind, making natural use of WebAssembly features such as i64, import functions with descriptive names and typed arguments, and aiming to avoid being tied to a particular implementation.
We'll often call functions in these APIs "syscalls", because they serve an analogous purpose to system calls in native executables. However, they're just functions that are provided by the surrounding environment that can do I/O on behalf of the program.
WASI is starting with a basic POSIX-like set of syscall functions, though adapted to suit the needs of WebAssembly, such as in excluding functions such as fork and exec which aren't easily implementable in some of the places people want to run WebAssembly, and such as in adopting a capabilities-oriented design.
And, as WebAssembly grows support for host bindings and related features, capabilities can evolve to being represented as opaque, unforgeable reference typed values, which can allow for finer-grained control over capabilities, and make the API more accessible beyond the C-like languages that POSIX-style APIs are typically aimed at.
To facilitate use of the WASI API, a libc implementation called WASI libc is being developed, which presents a relatively normal musl-based libc interface, implemented on top of a libpreopen-like layer and a system call wrapper layer (derived from the "bottom half" of cloudlibc). The system call wrapper layer makes calls to the actual WASI implementation, which may map these calls to whatever the surrounding environment provides, whether it's native OS resources, JS runtime resources, or something else entirely.
This libc is part of a "sysroot", which is a directory containing compiled libraries and C/C++ header files providing standard library and related facilities laid out in a standard way to allow compilers to use it directly.
With the LLVM 8.0 release, the WebAssembly backend is now officially stable, but LLVM itself doesn't provide a libc - a standard C library, which you need to build anything with clang. This is what the WASI-enabled sysroot provides, so the combination of clang in LLVM 8.0 and the new WASI-enabled sysroot provides usable Rust and C compilation environments that can produce wasm modules that can be run in Wasmtime with WASI support, in browsers with the WASI polyfill, and in the future other engines as well.
The first version of WASI is relatively simple, small, and POSIX-like in order to make it easy for implementers to prototype it and port existing code to it, making it a good way to start building momentum and allow us to start getting feedback based on experience.
Future versions will change based on experience and feedback with the first version, and add features to address new use cases. They may also see significant architectural changes. One possibility is that this API could evolve into something like Fuchsia's low-level APIs, which are more complex and abstract, though also more capable.
We also expect that whatever WASI evolves into in the future, it should be possible to implement this initial API as a library on top.
Yes! We have a polyfill which implements WASI and runs in browsers. At the WebAssembly level, WASI is just a set of callable functions that can be imported by a .wasm module, and these imports can be implemented in a variety of ways, including by a JavaScript polyfill library running within browsers.
And in the future, it's possible that builtin modules could take these ideas even further allowing easier and tighter integration between .wasm modules importing WASI and the Web.
WASI is currently experimental. Feedback is welcome!