1# WebAssembly System Interface (WASI) 2 3<!--introduced_in=v12.16.0--> 4 5> Stability: 1 - Experimental 6 7<!-- source_link=lib/wasi.js --> 8 9The WASI API provides an implementation of the [WebAssembly System Interface][] 10specification. WASI gives sandboxed WebAssembly applications access to the 11underlying operating system via a collection of POSIX-like functions. 12 13```mjs 14import fs from 'fs'; 15import { WASI } from 'wasi'; 16 17const wasi = new WASI({ 18 args: process.argv, 19 env: process.env, 20 preopens: { 21 '/sandbox': '/some/real/path/that/wasm/can/access' 22 } 23}); 24const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 25 26const wasm = await WebAssembly.compile(fs.readFileSync('./demo.wasm')); 27const instance = await WebAssembly.instantiate(wasm, importObject); 28 29wasi.start(instance); 30``` 31 32```cjs 33'use strict'; 34const fs = require('fs'); 35const { WASI } = require('wasi'); 36const wasi = new WASI({ 37 args: process.argv, 38 env: process.env, 39 preopens: { 40 '/sandbox': '/some/real/path/that/wasm/can/access' 41 } 42}); 43const importObject = { wasi_snapshot_preview1: wasi.wasiImport }; 44 45(async () => { 46 const wasm = await WebAssembly.compile(fs.readFileSync('./demo.wasm')); 47 const instance = await WebAssembly.instantiate(wasm, importObject); 48 49 wasi.start(instance); 50})(); 51``` 52 53To run the above example, create a new WebAssembly text format file named 54`demo.wat`: 55 56```text 57(module 58 ;; Import the required fd_write WASI function which will write the given io vectors to stdout 59 ;; The function signature for fd_write is: 60 ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written 61 (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) 62 63 (memory 1) 64 (export "memory" (memory 0)) 65 66 ;; Write 'hello world\n' to memory at an offset of 8 bytes 67 ;; Note the trailing newline which is required for the text to appear 68 (data (i32.const 8) "hello world\n") 69 70 (func $main (export "_start") 71 ;; Creating a new io vector within linear memory 72 (i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string 73 (i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - The length of the 'hello world\n' string 74 75 (call $fd_write 76 (i32.const 1) ;; file_descriptor - 1 for stdout 77 (i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0 78 (i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one. 79 (i32.const 20) ;; nwritten - A place in memory to store the number of bytes written 80 ) 81 drop ;; Discard the number of bytes written from the top of the stack 82 ) 83) 84``` 85 86Use [wabt](https://github.com/WebAssembly/wabt) to compile `.wat` to `.wasm` 87 88```console 89$ wat2wasm demo.wat 90``` 91 92The `--experimental-wasi-unstable-preview1` and `--experimental-wasm-bigint` 93CLI arguments are needed for this example to run. 94 95## Class: `WASI` 96<!-- YAML 97added: 98 - v13.3.0 99 - v12.16.0 100--> 101 102The `WASI` class provides the WASI system call API and additional convenience 103methods for working with WASI-based applications. Each `WASI` instance 104represents a distinct sandbox environment. For security purposes, each `WASI` 105instance must have its command-line arguments, environment variables, and 106sandbox directory structure configured explicitly. 107 108### `new WASI([options])` 109<!-- YAML 110added: 111 - v13.3.0 112 - v12.16.0 113--> 114 115* `options` {Object} 116 * `args` {Array} An array of strings that the WebAssembly application will 117 see as command-line arguments. The first argument is the virtual path to the 118 WASI command itself. **Default:** `[]`. 119 * `env` {Object} An object similar to `process.env` that the WebAssembly 120 application will see as its environment. **Default:** `{}`. 121 * `preopens` {Object} This object represents the WebAssembly application's 122 sandbox directory structure. The string keys of `preopens` are treated as 123 directories within the sandbox. The corresponding values in `preopens` are 124 the real paths to those directories on the host machine. 125 * `returnOnExit` {boolean} By default, WASI applications terminate the Node.js 126 process via the `__wasi_proc_exit()` function. Setting this option to `true` 127 causes `wasi.start()` to return the exit code rather than terminate the 128 process. **Default:** `false`. 129 * `stdin` {integer} The file descriptor used as standard input in the 130 WebAssembly application. **Default:** `0`. 131 * `stdout` {integer} The file descriptor used as standard output in the 132 WebAssembly application. **Default:** `1`. 133 * `stderr` {integer} The file descriptor used as standard error in the 134 WebAssembly application. **Default:** `2`. 135 136### `wasi.start(instance)` 137<!-- YAML 138added: 139 - v13.3.0 140 - v12.16.0 141--> 142 143* `instance` {WebAssembly.Instance} 144 145Attempt to begin execution of `instance` as a WASI command by invoking its 146`_start()` export. If `instance` does not contain a `_start()` export, or if 147`instance` contains an `_initialize()` export, then an exception is thrown. 148 149`start()` requires that `instance` exports a [`WebAssembly.Memory`][] named 150`memory`. If `instance` does not have a `memory` export an exception is thrown. 151 152If `start()` is called more than once, an exception is thrown. 153 154### `wasi.initialize(instance)` 155<!-- YAML 156added: 157 - v14.6.0 158--> 159 160* `instance` {WebAssembly.Instance} 161 162Attempt to initialize `instance` as a WASI reactor by invoking its 163`_initialize()` export, if it is present. If `instance` contains a `_start()` 164export, then an exception is thrown. 165 166`initialize()` requires that `instance` exports a [`WebAssembly.Memory`][] named 167`memory`. If `instance` does not have a `memory` export an exception is thrown. 168 169If `initialize()` is called more than once, an exception is thrown. 170 171### `wasi.wasiImport` 172<!-- YAML 173added: 174 - v13.3.0 175 - v12.16.0 176--> 177 178* {Object} 179 180`wasiImport` is an object that implements the WASI system call API. This object 181should be passed as the `wasi_snapshot_preview1` import during the instantiation 182of a [`WebAssembly.Instance`][]. 183 184[WebAssembly System Interface]: https://wasi.dev/ 185[`WebAssembly.Instance`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance 186[`WebAssembly.Memory`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory 187