11cb0ef41Sopenharmony_ci# WebAssembly System Interface (WASI)
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ci<!--introduced_in=v12.16.0-->
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci> Stability: 1 - Experimental
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci<!-- source_link=lib/wasi.js -->
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciThe WASI API provides an implementation of the [WebAssembly System Interface][]
101cb0ef41Sopenharmony_cispecification. WASI gives sandboxed WebAssembly applications access to the
111cb0ef41Sopenharmony_ciunderlying operating system via a collection of POSIX-like functions.
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci```mjs
141cb0ef41Sopenharmony_ciimport { readFile } from 'node:fs/promises';
151cb0ef41Sopenharmony_ciimport { WASI } from 'wasi';
161cb0ef41Sopenharmony_ciimport { argv, env } from 'node:process';
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciconst wasi = new WASI({
191cb0ef41Sopenharmony_ci  args: argv,
201cb0ef41Sopenharmony_ci  env,
211cb0ef41Sopenharmony_ci  preopens: {
221cb0ef41Sopenharmony_ci    '/sandbox': '/some/real/path/that/wasm/can/access',
231cb0ef41Sopenharmony_ci  },
241cb0ef41Sopenharmony_ci});
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci// Some WASI binaries require:
271cb0ef41Sopenharmony_ci//   const importObject = { wasi_unstable: wasi.wasiImport };
281cb0ef41Sopenharmony_ciconst importObject = { wasi_snapshot_preview1: wasi.wasiImport };
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciconst wasm = await WebAssembly.compile(
311cb0ef41Sopenharmony_ci  await readFile(new URL('./demo.wasm', import.meta.url)),
321cb0ef41Sopenharmony_ci);
331cb0ef41Sopenharmony_ciconst instance = await WebAssembly.instantiate(wasm, importObject);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciwasi.start(instance);
361cb0ef41Sopenharmony_ci```
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci```cjs
391cb0ef41Sopenharmony_ci'use strict';
401cb0ef41Sopenharmony_ciconst { readFile } = require('node:fs/promises');
411cb0ef41Sopenharmony_ciconst { WASI } = require('wasi');
421cb0ef41Sopenharmony_ciconst { argv, env } = require('node:process');
431cb0ef41Sopenharmony_ciconst { join } = require('node:path');
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciconst wasi = new WASI({
461cb0ef41Sopenharmony_ci  args: argv,
471cb0ef41Sopenharmony_ci  env,
481cb0ef41Sopenharmony_ci  preopens: {
491cb0ef41Sopenharmony_ci    '/sandbox': '/some/real/path/that/wasm/can/access',
501cb0ef41Sopenharmony_ci  },
511cb0ef41Sopenharmony_ci});
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci// Some WASI binaries require:
541cb0ef41Sopenharmony_ci//   const importObject = { wasi_unstable: wasi.wasiImport };
551cb0ef41Sopenharmony_ciconst importObject = { wasi_snapshot_preview1: wasi.wasiImport };
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci(async () => {
581cb0ef41Sopenharmony_ci  const wasm = await WebAssembly.compile(
591cb0ef41Sopenharmony_ci    await readFile(join(__dirname, 'demo.wasm')),
601cb0ef41Sopenharmony_ci  );
611cb0ef41Sopenharmony_ci  const instance = await WebAssembly.instantiate(wasm, importObject);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  wasi.start(instance);
641cb0ef41Sopenharmony_ci})();
651cb0ef41Sopenharmony_ci```
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ciTo run the above example, create a new WebAssembly text format file named
681cb0ef41Sopenharmony_ci`demo.wat`:
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci```text
711cb0ef41Sopenharmony_ci(module
721cb0ef41Sopenharmony_ci    ;; Import the required fd_write WASI function which will write the given io vectors to stdout
731cb0ef41Sopenharmony_ci    ;; The function signature for fd_write is:
741cb0ef41Sopenharmony_ci    ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written
751cb0ef41Sopenharmony_ci    (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci    (memory 1)
781cb0ef41Sopenharmony_ci    (export "memory" (memory 0))
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    ;; Write 'hello world\n' to memory at an offset of 8 bytes
811cb0ef41Sopenharmony_ci    ;; Note the trailing newline which is required for the text to appear
821cb0ef41Sopenharmony_ci    (data (i32.const 8) "hello world\n")
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci    (func $main (export "_start")
851cb0ef41Sopenharmony_ci        ;; Creating a new io vector within linear memory
861cb0ef41Sopenharmony_ci        (i32.store (i32.const 0) (i32.const 8))  ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string
871cb0ef41Sopenharmony_ci        (i32.store (i32.const 4) (i32.const 12))  ;; iov.iov_len - The length of the 'hello world\n' string
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci        (call $fd_write
901cb0ef41Sopenharmony_ci            (i32.const 1) ;; file_descriptor - 1 for stdout
911cb0ef41Sopenharmony_ci            (i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0
921cb0ef41Sopenharmony_ci            (i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one.
931cb0ef41Sopenharmony_ci            (i32.const 20) ;; nwritten - A place in memory to store the number of bytes written
941cb0ef41Sopenharmony_ci        )
951cb0ef41Sopenharmony_ci        drop ;; Discard the number of bytes written from the top of the stack
961cb0ef41Sopenharmony_ci    )
971cb0ef41Sopenharmony_ci)
981cb0ef41Sopenharmony_ci```
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ciUse [wabt](https://github.com/WebAssembly/wabt) to compile `.wat` to `.wasm`
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci```console
1031cb0ef41Sopenharmony_ci$ wat2wasm demo.wat
1041cb0ef41Sopenharmony_ci```
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci## Class: `WASI`
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci<!-- YAML
1091cb0ef41Sopenharmony_ciadded:
1101cb0ef41Sopenharmony_ci - v13.3.0
1111cb0ef41Sopenharmony_ci - v12.16.0
1121cb0ef41Sopenharmony_ci-->
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ciThe `WASI` class provides the WASI system call API and additional convenience
1151cb0ef41Sopenharmony_cimethods for working with WASI-based applications. Each `WASI` instance
1161cb0ef41Sopenharmony_cirepresents a distinct sandbox environment. For security purposes, each `WASI`
1171cb0ef41Sopenharmony_ciinstance must have its command-line arguments, environment variables, and
1181cb0ef41Sopenharmony_cisandbox directory structure configured explicitly.
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci### `new WASI([options])`
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci<!-- YAML
1231cb0ef41Sopenharmony_ciadded:
1241cb0ef41Sopenharmony_ci - v13.3.0
1251cb0ef41Sopenharmony_ci - v12.16.0
1261cb0ef41Sopenharmony_ci-->
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci* `options` {Object}
1291cb0ef41Sopenharmony_ci  * `args` {Array} An array of strings that the WebAssembly application will
1301cb0ef41Sopenharmony_ci    see as command-line arguments. The first argument is the virtual path to the
1311cb0ef41Sopenharmony_ci    WASI command itself. **Default:** `[]`.
1321cb0ef41Sopenharmony_ci  * `env` {Object} An object similar to `process.env` that the WebAssembly
1331cb0ef41Sopenharmony_ci    application will see as its environment. **Default:** `{}`.
1341cb0ef41Sopenharmony_ci  * `preopens` {Object} This object represents the WebAssembly application's
1351cb0ef41Sopenharmony_ci    sandbox directory structure. The string keys of `preopens` are treated as
1361cb0ef41Sopenharmony_ci    directories within the sandbox. The corresponding values in `preopens` are
1371cb0ef41Sopenharmony_ci    the real paths to those directories on the host machine.
1381cb0ef41Sopenharmony_ci  * `returnOnExit` {boolean} By default, WASI applications terminate the Node.js
1391cb0ef41Sopenharmony_ci    process via the `__wasi_proc_exit()` function. Setting this option to `true`
1401cb0ef41Sopenharmony_ci    causes `wasi.start()` to return the exit code rather than terminate the
1411cb0ef41Sopenharmony_ci    process. **Default:** `false`.
1421cb0ef41Sopenharmony_ci  * `stdin` {integer} The file descriptor used as standard input in the
1431cb0ef41Sopenharmony_ci    WebAssembly application. **Default:** `0`.
1441cb0ef41Sopenharmony_ci  * `stdout` {integer} The file descriptor used as standard output in the
1451cb0ef41Sopenharmony_ci    WebAssembly application. **Default:** `1`.
1461cb0ef41Sopenharmony_ci  * `stderr` {integer} The file descriptor used as standard error in the
1471cb0ef41Sopenharmony_ci    WebAssembly application. **Default:** `2`.
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci### `wasi.start(instance)`
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci<!-- YAML
1521cb0ef41Sopenharmony_ciadded:
1531cb0ef41Sopenharmony_ci - v13.3.0
1541cb0ef41Sopenharmony_ci - v12.16.0
1551cb0ef41Sopenharmony_ci-->
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci* `instance` {WebAssembly.Instance}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ciAttempt to begin execution of `instance` as a WASI command by invoking its
1601cb0ef41Sopenharmony_ci`_start()` export. If `instance` does not contain a `_start()` export, or if
1611cb0ef41Sopenharmony_ci`instance` contains an `_initialize()` export, then an exception is thrown.
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci`start()` requires that `instance` exports a [`WebAssembly.Memory`][] named
1641cb0ef41Sopenharmony_ci`memory`. If `instance` does not have a `memory` export an exception is thrown.
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciIf `start()` is called more than once, an exception is thrown.
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci### `wasi.initialize(instance)`
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci<!-- YAML
1711cb0ef41Sopenharmony_ciadded:
1721cb0ef41Sopenharmony_ci - v14.6.0
1731cb0ef41Sopenharmony_ci - v12.19.0
1741cb0ef41Sopenharmony_ci-->
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci* `instance` {WebAssembly.Instance}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ciAttempt to initialize `instance` as a WASI reactor by invoking its
1791cb0ef41Sopenharmony_ci`_initialize()` export, if it is present. If `instance` contains a `_start()`
1801cb0ef41Sopenharmony_ciexport, then an exception is thrown.
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci`initialize()` requires that `instance` exports a [`WebAssembly.Memory`][] named
1831cb0ef41Sopenharmony_ci`memory`. If `instance` does not have a `memory` export an exception is thrown.
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ciIf `initialize()` is called more than once, an exception is thrown.
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci### `wasi.wasiImport`
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci<!-- YAML
1901cb0ef41Sopenharmony_ciadded:
1911cb0ef41Sopenharmony_ci - v13.3.0
1921cb0ef41Sopenharmony_ci - v12.16.0
1931cb0ef41Sopenharmony_ci-->
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci* {Object}
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci`wasiImport` is an object that implements the WASI system call API. This object
1981cb0ef41Sopenharmony_cishould be passed as the `wasi_snapshot_preview1` import during the instantiation
1991cb0ef41Sopenharmony_ciof a [`WebAssembly.Instance`][].
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci[WebAssembly System Interface]: https://wasi.dev/
2021cb0ef41Sopenharmony_ci[`WebAssembly.Instance`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance
2031cb0ef41Sopenharmony_ci[`WebAssembly.Memory`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory
204