WebAssembly システムインターフェース (WASI)
node:wasi
モジュールは、現在、一部の WASI ランタイムによって提供される包括的なファイルシステムセキュリティプロパティを提供していません。安全なファイルシステムサンドボックスの完全なサポートは、将来実装される場合とされない場合があります。当面の間、信頼できないコードの実行には使用しないでください。
ソースコード: lib/wasi.js
WASI API は、WebAssembly システムインターフェース仕様の実装を提供します。WASI は、POSIX に似た関数のコレクションを介して、WebAssembly アプリケーションに基礎となるオペレーティングシステムへのアクセスを提供します。
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)
'use strict'
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)
})()
上記の例を実行するには、demo.wat
という名前の新しい WebAssembly テキストフォーマットファイルを作成します。
(module
;; 与えられた io vectors を stdout に書き込むために必要な fd_write WASI 関数をインポートします
;; fd_write の関数シグネチャは次のとおりです。
;; (ファイル記述子, *iovs, iovs_len, nwritten) -> 書き込まれたバイト数を返します
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; 8 バイトのオフセットにあるメモリに 'hello world\n' を書き込みます
;; テキストが表示されるためには、末尾の改行文字が必要です
(data (i32.const 8) "hello world\n")
(func $main (export "_start")
;; 線形メモリ内に新しい io vector を作成します
(i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - これは 'hello world\n' 文字列の先頭へのポインタです
(i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - 'hello world\n' 文字列の長さです
(call $fd_write
(i32.const 1) ;; file_descriptor - stdout は 1
(i32.const 0) ;; *iovs - メモリ位置 0 に格納されている iov 配列へのポインタです
(i32.const 1) ;; iovs_len - iov に格納されている文字列を 1 つ出力しています - したがって 1 です。
(i32.const 20) ;; nwritten - 書き込まれたバイト数を格納するメモリ内の場所です
)
drop ;; スタックの一番上から書き込まれたバイト数を破棄します
)
)
wabt を使用して .wat
を .wasm
にコンパイルします。
wat2wasm demo.wat
セキュリティ
[履歴]
バージョン | 変更点 |
---|---|
v21.2.0, v20.11.0 | WASI のセキュリティ特性を明確化しました。 |
v21.2.0, v20.11.0 | 追加:v21.2.0, v20.11.0 |
WASI は、アプリケーションに独自のenv
、preopens
、stdin
、stdout
、stderr
、exit
機能を提供する、機能ベースのモデルを提供します。
現在の Node.js の脅威モデルは、一部の WASI ランタイムにあるような安全なサンドボックスを提供していません。
機能はサポートされていますが、Node.js ではセキュリティモデルを形成していません。たとえば、ファイルシステムのサンドボックスは様々な手法で回避できます。このプロジェクトでは、将来これらのセキュリティ保証を追加できるかどうかを検討しています。
クラス: WASI
追加: v13.3.0, v12.16.0
WASI
クラスは、WASI システムコール API と、WASI ベースのアプリケーションを操作するための追加の便利なメソッドを提供します。各WASI
インスタンスは、異なる環境を表します。
new WASI([options])
[履歴]
バージョン | 変更点 |
---|---|
v20.1.0 | returnOnExit のデフォルト値が true に変更されました。 |
v20.0.0 | version オプションが必須となり、デフォルト値はなくなりました。 |
v19.8.0 | options に version フィールドが追加されました。 |
v13.3.0, v12.16.0 | 追加: v13.3.0, v12.16.0 |
options
<Object>args
<Array> WebAssembly アプリケーションがコマンドライン引数として認識する文字列の配列。最初の引数は、WASI コマンド自体の仮想パスです。デフォルト:[]
。env
<Object> WebAssembly アプリケーションがその環境として認識するprocess.env
に似たオブジェクト。デフォルト:{}
。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()
追加: v19.8.0
WASI によって提供されるもの以外に WASM インポートが不要な場合、WebAssembly.instantiate()
に渡すことができるインポートオブジェクトを返します。
バージョンunstable
がコンストラクタに渡された場合、以下を返します。
{ wasi_unstable: wasi.wasiImport }
バージョンpreview1
がコンストラクタに渡された場合、またはバージョンが指定されなかった場合、以下を返します。
{ wasi_snapshot_preview1: wasi.wasiImport }
wasi.start(instance)
追加: v13.3.0, v12.16.0
instance
<WebAssembly.Instance>
_start()
エクスポートを呼び出すことによって、instance
を WASI コマンドとして実行を開始しようとします。instance
に_start()
エクスポートが含まれていない場合、またはinstance
に_initialize()
エクスポートが含まれている場合、例外がスローされます。
start()
には、instance
がmemory
という名前のWebAssembly.Memory
をエクスポートすることが必要です。instance
にmemory
エクスポートがない場合、例外がスローされます。
start()
が複数回呼び出された場合、例外がスローされます。
wasi.initialize(instance)
追加: v14.6.0, v12.19.0
instance
<WebAssembly.Instance>
存在する場合、その_initialize()
エクスポートを呼び出すことによって、instance
を WASI リアクターとして初期化しようとします。instance
に_start()
エクスポートが含まれている場合、例外がスローされます。
initialize()
には、instance
がmemory
という名前のWebAssembly.Memory
をエクスポートすることが必要です。instance
にmemory
エクスポートがない場合、例外がスローされます。
initialize()
が複数回呼び出された場合、例外がスローされます。
wasi.wasiImport
追加: v13.3.0, v12.16.0
wasiImport
は、WASI システムコール API を実装するオブジェクトです。このオブジェクトは、WebAssembly.Instance
のインスタンス化時にwasi_snapshot_preview1
インポートとして渡される必要があります。