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