Интерфейс систем WebAssembly (WASI)
Стабильность: 1 — Экспериментальный
Модуль node:wasi в настоящее время не обеспечивает комплексные свойства безопасности файловой системы, предоставляемые некоторыми средами выполнения WASI. Полная поддержка изолированной программной среды файловой системы с защитой может быть реализована в будущем, а может и нет. До тех пор не полагайтесь на неё при запуске ненадёжного кода.
API WASI предоставляет реализацию спецификации интерфейса систем WebAssembly. WASI предоставляет приложениям WebAssembly доступ к базовой операционной системе с помощью набора функций, подобных POSIX.
Модули JavaScript
import { readFile } from 'node:fs/promises';
import { WASI } from 'node:wasi';
import { argv, env } from 'node:process';
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
});
const wasm = await WebAssembly.compile(
await readFile(new URL('./demo.wasm', import.meta.url)),
);
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject());
wasi.start(instance);
CommonJS
const { readFile } = require('node:fs/promises');
const { WASI } = require('node:wasi');
const { argv, env } = require('node:process');
const { join } = require('node:path');
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
});
(async () => {
const wasm = await WebAssembly.compile(
await readFile(join(__dirname, 'demo.wasm')),
);
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject());
wasi.start(instance);
})();
Чтобы запустить приведённый выше пример, создайте новый файл текстового формата WebAssembly с именем 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
)
)
textcopy
Используйте wabt, чтобы скомпилировать .wat в .wasm
wat2wasm demo.wat bashcopy
Безопасность
WASI предоставляет модель на основе возможностей, в рамках которой приложениям доступны собственные возможности для env, preopens, stdin, stdout, stderr и exit.
Текущая модель угроз Node.js не обеспечивает безопасную изолированную программную среду, имеющуюся в некоторых средах выполнения WASI.
Хотя функции на основе возможностей поддерживаются, они не образуют модель безопасности в Node.js. Например, из изолированной программной среды файловой системы можно выйти с помощью различных методов. Проект изучает возможность добавления таких гарантий безопасности в будущем.
Класс: WASI
Класс WASI предоставляет API системных вызовов WASI и дополнительные вспомогательные методы для работы с приложениями на основе WASI. Каждый экземпляр WASI представляет отдельную среду.
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(),wasi.start()возвращает управление с указанным кодом выхода, а не завершает процесс. Если установить для этого параметра значениеfalse, процесс Node.js завершится с указанным кодом выхода. По умолчанию:true. -
stdin<integer>Дескриптор файла, используемый в качестве стандартного ввода в приложении WebAssembly. По умолчанию:0. -
stdout<integer>Дескриптор файла, используемый в качестве стандартного вывода в приложении WebAssembly. По умолчанию:1. -
stderr<integer>Дескриптор файла, используемый в качестве стандартного вывода ошибок в приложении WebAssembly. По умолчанию:2. -
version<string>Запрашиваемая версия WASI. В настоящее время поддерживаются только версииunstableиpreview1. Этот параметр обязателен.
-
wasi.getImportObject()
Возвращает объект импорта, который можно передать в WebAssembly.instantiate(), если помимо предоставляемых WASI импортов не требуются другие импорты WASM.
Если в конструктор была передана версия unstable, будет возвращено:
{ wasi_unstable: wasi.wasiImport }
jsoncopy
Если в конструктор была передана версия preview1 или версия не была указана, будет возвращено:
{ wasi_snapshot_preview1: wasi.wasiImport }
jsoncopy
wasi.start(instance)
-
instance<WebAssembly.Instance>
Пытается начать выполнение instance в качестве команды WASI, вызывая его экспорт _start(). Если instance не содержит экспорт _start() или если instance содержит экспорт _initialize(), возникает исключение.
Для start() требуется, чтобы instance экспортировал WebAssembly.Memory с именем memory. Если у instance нет экспорта memory, возникает исключение.
Если start() вызывается более одного раза, возникает исключение.
wasi.initialize(instance)
-
instance<WebAssembly.Instance>
Пытается инициализировать instance в качестве WASI-реактора, вызывая его экспорт _initialize(), если он присутствует. Если instance содержит экспорт _start(), возникает исключение.
Для initialize() требуется, чтобы instance экспортировал WebAssembly.Memory с именем memory. Если у instance нет экспорта memory, возникает исключение.
Если initialize() вызывается более одного раза, возникает исключение.
wasi.finalizeBindings(instance[, options])
-
instance<WebAssembly.Instance> -
options<Object>-
memory<WebAssembly.Memory>По умолчанию:instance.exports.memory.
-
Настраивает привязки хоста WASI для instance без вызова initialize() или start(). Этот метод полезен, когда модуль WASI создаётся в дочерних потоках для совместного использования памяти между потоками.
Для finalizeBindings() требуется, чтобы либо instance экспортировал WebAssembly.Memory с именем memory, либо пользователь указал объект WebAssembly.Memory в options.memory. Если memory недействителен, возникает исключение.
start() и initialize() будут вызывать finalizeBindings() внутри себя. Если finalizeBindings() вызывается более одного раза, возникает исключение.
wasi.wasiImport
- Тип:
<Object>
wasiImport — это объект, реализующий API системных вызовов WASI. Этот объект следует передать в качестве импорта wasi_snapshot_preview1 при создании экземпляра WebAssembly.Instance.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/api/wasi.html