Node.js v16.20.2 文档


WebAssembly 系统接口 (WASI)#>

🌐 WebAssembly System Interface (WASI)

稳定性: 1 - 实验性

源代码: lib/wasi.js

WASI API 提供了 WebAssembly 系统接口 规范的实现。WASI 通过一组类 POSIX 的函数,为沙盒化的 WebAssembly 应用提供对底层操作系统的访问。

🌐 The WASI API provides an implementation of the WebAssembly System Interface specification. WASI gives sandboxed WebAssembly applications access to the underlying operating system via a collection of POSIX-like functions.

import { readFile } from 'node:fs/promises';
import { WASI } from 'wasi';
import { argv, env } from 'node:process';

const wasi = new WASI({
  args: argv,
  env,
  preopens: {
    '/sandbox': '/some/real/path/that/wasm/can/access'
  }
});

// Some WASI binaries require:
//   const importObject = { wasi_unstable: wasi.wasiImport };
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };

const wasm = await WebAssembly.compile(
  await readFile(new URL('./demo.wasm', import.meta.url))
);
const instance = await WebAssembly.instantiate(wasm, importObject);

wasi.start(instance);'use strict';
const { readFile } = require('node:fs/promises');
const { WASI } = require('wasi');
const { argv, env } = require('node:process');
const { join } = require('node:path');

const wasi = new WASI({
  args: argv,
  env,
  preopens: {
    '/sandbox': '/some/real/path/that/wasm/can/access'
  }
});

// Some WASI binaries require:
//   const importObject = { wasi_unstable: wasi.wasiImport };
const importObject = { wasi_snapshot_preview1: wasi.wasiImport };

(async () => {
  const wasm = await WebAssembly.compile(
    await readFile(join(__dirname, 'demo.wasm'))
  );
  const instance = await WebAssembly.instantiate(wasm, importObject);

  wasi.start(instance);
})();

要运行上述示例,请创建一个名为 demo.wat 的新 WebAssembly 文本格式文件:

🌐 To run the above example, create a new WebAssembly text format file named demo.wat:

(module
    ;; Import the required fd_write WASI function which will write the given io vectors to stdout
    ;; The function signature for fd_write is:
    ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written
    (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

    (memory 1)
    (export "memory" (memory 0))

    ;; Write 'hello world\n' to memory at an offset of 8 bytes
    ;; Note the trailing newline which is required for the text to appear
    (data (i32.const 8) "hello world\n")

    (func $main (export "_start")
        ;; Creating a new io vector within linear memory
        (i32.store (i32.const 0) (i32.const 8))  ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string
        (i32.store (i32.const 4) (i32.const 12))  ;; iov.iov_len - The length of the 'hello world\n' string

        (call $fd_write
            (i32.const 1) ;; file_descriptor - 1 for stdout
            (i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0
            (i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one.
            (i32.const 20) ;; nwritten - A place in memory to store the number of bytes written
        )
        drop ;; Discard the number of bytes written from the top of the stack
    )
) 

使用 wabt.wat 编译为 .wasm

🌐 Use wabt to compile .wat to .wasm

$ wat2wasm demo.wat 

运行此示例需要使用 --experimental-wasi-unstable-preview1 命令行参数。

🌐 The --experimental-wasi-unstable-preview1 CLI argument is needed for this example to run.

类:WASI#>

🌐 Class: WASI

WASI 类提供了 WASI 系统调用 API 以及用于处理基于 WASI 的应用的额外便捷方法。每个 WASI 实例代表一个独立的沙箱环境。出于安全考虑,每个 WASI 实例必须显式配置其命令行参数、环境变量和沙箱目录结构。

🌐 The WASI class provides the WASI system call API and additional convenience methods for working with WASI-based applications. Each WASI instance represents a distinct sandbox environment. For security purposes, each WASI instance must have its command-line arguments, environment variables, and sandbox directory structure configured explicitly.

new WASI([options])#>

  • options <Object>
    • args <Array> 一个字符串数组,WebAssembly 应用将把它们视为命令行参数。第一个参数是 WASI 命令本身的虚拟路径。默认值: []
    • env <Object> 一个类似于 process.env 的对象,WebAssembly 应用将其视作环境变量。默认值: {}
    • preopens <Object> 该对象表示 WebAssembly 应用的沙箱目录结构。preopens 的字符串键被视为沙箱中的目录。preopens 中对应的值是主机上这些目录的实际路径。
    • returnOnExit <boolean> 默认情况下,WASI 应用通过 __wasi_proc_exit() 函数终止 Node.js 进程。将此选项设置为 true 会使 wasi.start() 返回退出代码,而不是终止进程。默认值: false
    • stdin <integer> 在 WebAssembly 应用中用作标准输入的文件描述符。默认值: 0
    • stdout <integer> 在 WebAssembly 应用中用作标准输出的文件描述符。默认值: 1
    • stderr <integer> 在 WebAssembly 应用中用作标准错误的文件描述符。默认值:2

wasi.start(instance)#>

尝试通过调用其 _start() 导出将 instance 作为 WASI 命令开始执行。如果 instance 不包含 _start() 导出,或者 instance 包含 _initialize() 导出,则会抛出异常。

🌐 Attempt to begin execution of instance as a WASI command by invoking its _start() export. If instance does not contain a _start() export, or if instance contains an _initialize() export, then an exception is thrown.

start() 要求 instance 导出一个名为 memoryWebAssembly.Memory。如果 instance 没有 memory 导出,将抛出异常。

如果多次调用 start(),将抛出异常。

🌐 If start() is called more than once, an exception is thrown.

wasi.initialize(instance)#>

尝试通过调用其 _initialize() 导出将 instance 初始化为 WASI 反应器(如果存在)。如果 instance 包含 _start() 导出,则会抛出异常。

🌐 Attempt to initialize instance as a WASI reactor by invoking its _initialize() export, if it is present. If instance contains a _start() export, then an exception is thrown.

initialize() 要求 instance 导出一个名为 memoryWebAssembly.Memory。如果 instance 没有 memory 导出,将抛出异常。

如果多次调用 initialize(),将抛出异常。

🌐 If initialize() is called more than once, an exception is thrown.

wasi.wasiImport#>

wasiImport 是一个实现了 WASI 系统调用 API 的对象。这个对象应在实例化 WebAssembly.Instance 时作为 wasi_snapshot_preview1 导入传入。

Node.js 中文网 - 粤ICP备13048890号