はじめに
この資料は社内LTイベント用の資料です
WebAssembly (WASM) とは?
WebAssemblyは、ウェブブラウザのクライアントサイドスクリプトとして動作するプログラミング言語(低水準言語)である。wasmとも称されており、ブラウザ上でバイナリフォーマットの形で実行可能であることを特徴とする
WebAssemblyサポートの初期実装は、既存のasm.js(英語版)とPNaClをベースとしている
フォーマット
- WASM ... バイナリフォーマット
- WAT/(WAST) ... テキスト表現
1+2を計算するwatの例
(module
;; ---- export main function ---
(export "exported_main" (func $main))
(func $main (result i32)
(i32.add
(i32.const 1)
(i32.const 2)
)
)
)
実装方式
- スタックマシン ... WASM
- レジスタマシン ... LLVM
WebAssembly 以前のブラウザプラグイン

他のプラグインと比べた特徴
- 制約を設ける ... サンドボックス、直接描画無し
- 制約を取り払う ... バイトコード+JITコンパイラ→プラットフォーム独立
- 拡張性
- JavaScriptとの相互呼び出しが可能
- JavaScriptと両方アクセスできるメモリー領域(バイト列)の読み書きが可能
WASMへの移行の流れ
独自プラグインはサポート終了の動き
- FlashはiOSで使えない。2020年いっぱいでサポート終了予定
- Active Xは 32bit IEでしか動かない
- Silverlight は 32bit/64bit IE のみ
- NaCl, PNaCl は2019年Q2にサポート終了
ブラウザの高速な拡張機能としてWASMが推奨されている
- Chrome, Firefox, Safari, (Edge) がそれぞれサポートを表明
WASMの生成
- 手書き
- C/C++ + Emscripten
- Rust
- Go
- TypeScript + AssemblyScript
- Walt ... 型付きJavaScriptライク言語
- Node.js + ミニNode.js WASMトランスレーター(by massie_g) mganeko/node_wasm
WASMを手書き
- WAT を手書き
- WASM(バイナリに変換)
- binaryen に含まれる wasm-as で変換
- WASMを実行
- ブラウザで
- Node.js で
sample.wat
(module
;; ---- builtin func imports ---
(func $putn (import "imports" "imported_putn") (param i32))
;; ---- export main function ---
(export "exported_main" (func $main))
(func $main (result i32)
(call $putn
(i32.add
(i32.const 1)
(i32.const 2)
)
)
(i32.const 111) ;; return code
)
)
ブラウザで実行
const imports = {
imported_putn: function(arg) { // for i32
console.log(arg);
}
};
fetch('sample.wasm').then(response =>
response.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes, { imports: imports })
).then(result => {
let ret = result.instance.exports.exported_main();
console.log('ret=' + ret);
});
Node.jsで実行
const fs = require('fs');
let source = fs.readFileSync(filename);
let typedArray = new Uint8Array(source);
const imports = {
imported_putn: function(arg) { // for put i32
console.log(arg);
}
};
WebAssembly.instantiate(typedArray,
{ imports: imports }
).then(result => {
let ret = result.instance.exports.exported_main();
console.warn('ret code=' + ret);
process.exit(ret);
}).catch(e => {
console.log(e);
});
デモ
- fizzbuzz
- ミニnode.js --> WASM 化した例
事例
- ブラウザでWindows 2000 ... x86 PCエミュレーター
- Vim を WebAssembly に移植した
- CDNのエッジでWASMを実行 ... Cloudflare
- Ethereumのスマートコントラクト ... 次世代のEVM 「eWASM VM」について
おわりに
- WASMはFlashに替わって、色々使われそう
- Go, Rust, C++ をWASM化して使えると嬉しいかも