WebAssemblyの仕組み:小さな計算をJavaScriptから呼んでみよう
WATから作り、JavaScriptで呼ぶ
- 身近な課題で役割を説明できる
- 最初の操作と確認方法がわかる
最初のゴール:wasmの関数で2+3=5
JavaScriptから、WebAssemblyの小さな関数を呼びます。CやRustの大きな開発環境を入れる前に、関数を公開して、呼び出し結果が5になる流れを追ってみましょう。
ここではNode.jsとnpm、WATを変換するWABT、ローカル配信用のPythonを使います。作業用の新しいフォルダを用意してください。例は32ビット整数の加算です。
1. WATで関数を書く
add.watを作ります。
(module
(func (export "sum") (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add
)
)
paramは受け取る値、resultは返す値の型です。local.getで2つの値を積み、i32.addで加算します。export "sum"は外から呼べる名前を付けています。
2. wasmファイルへ変換する
WABTはWebAssemblyのための道具集です。npmで配布されるWABTのコマンドを使って変換します。
npx --package=wabt wat2wasm add.wat -o add.wasm
初回はパッケージの取得確認が出る場合があります。実行するパッケージを確認してください。同じフォルダにadd.wasmができたら、次へ進みます。
3. JavaScriptから呼ぶ
index.htmlを作ります。
<!doctype html>
<html lang="ja">
<meta charset="utf-8">
<title>wasmの足し算</title>
<link rel="icon" href="data:,">
<p id="result">読み込み中</p>
<script type="module">
const response = await fetch('./add.wasm');
if (!response.ok) throw new Error('wasmの取得に失敗');
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes);
document.querySelector('#result').textContent =
`2 + 3 = ${instance.exports.sum(2, 3)}`;
</script>
</html>
フォルダでローカルサーバーを起動します。WindowsでPythonのランチャーを使う例は次のとおりです。macOSやLinuxでは、環境に合わせてpython3を使います。
py -m http.server 8000 --bind 127.0.0.1
ブラウザでhttp://127.0.0.1:8000/を開き、「2 + 3 = 5」が表示されれば成功です。終了するときはサーバーを起動したターミナルでCtrl + Cを押します。ファイルを直接ダブルクリックするのではなく、HTTPで配信してfetchが読めるようにします。
処理を分けて見る
- WAT → wasm:人が読める形式をバイナリへ変換します。
- 読み込みとインスタンス化:実行環境がモジュールを検証し、呼べる状態を作ります。
- 関数の呼び出し:JavaScriptが
sumへ値を渡し、結果を受け取ります。 - 画面への表示:JavaScriptがDOMを更新します。
この例は仕組みを確認するもので、性能の比較ではありません。実用では、変換元の言語、必要な入出力、実行環境の対応を選びます。WASIのような外側の機能を使う仕組みもありますが、WebAssemblyだけでどんなOS機能にも直接アクセスできるわけではありません。
よくあるつまずき
- 404になる:
index.htmlとadd.wasmが配信フォルダにあるか確認します。 - sumがない:変換元のexport名と、JavaScript側の名前をそろえます。
- 読み込み中のまま:開発者ツールのConsoleとNetworkでエラーと取得先を確認します。
instantiateStreamingで読み込みながら処理する方法もあります。その場合はサーバーのapplication/wasmというContent-Typeも重要です。上の例はバイト列を読み終えてからインスタンス化します。
次に学ぶなら
呼び出す側を理解するならJavaScript入門、言語からの変換へ進むならRust入門がつながります。
参考資料
- MDN:WebAssemblyの概念 — モジュール・インスタンス・JavaScriptとの関係
- MDN:WATの読み方 — テキスト形式・関数・export・変換
- WebAssembly:Security — 隔離・領域の境界検査と残る不具合
- WABT:公式リポジトリ — WATとバイナリを扱う道具