WebAssembly をざっくり紹介

# はじめに

この資料は社内LTイベント用の資料です

---

# WebAssembly (WASM) とは？

[Wikipediaより](https://ja.wikipedia.org/wiki/WebAssembly)

> 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

![stack.png](https://qiita-image-store.s3.amazonaws.com/0/19403/021a6345-171b-ba92-231d-ec78c0475161.png)

![register.png](https://qiita-image-store.s3.amazonaws.com/0/19403/3020da40-afb0-60d7-6e52-d9e71ff0a37e.png)

---

# WebAssembly 以前のブラウザプラグイン

<!--
- Flash ... 中間コード(バイトコード)を実行
- Java applet ... JVMでJavaバイトコードを実行
- Active X ... ネイティブコードのDLLを実行
- Silverlight ... .NETのバイトコードをJITコンパイラでネイティブに変換して実行
- Chrome Native Client (NaCl) ... サンドボックス内でネイティブコードを実行
- Chrome Portable Native Client (PNaCl) ... LLVMバイトコードを、ネイティブコードに変換して実行
- asm.js ... JavaScriptのサブセットを、JITコンパイラでネイティブに変換して実行
-->

<img width="819" alt="browser_plugin.png" src="https://qiita-image-store.s3.amazonaws.com/0/19403/cd4a9dbd-eb1e-3e4a-f1e8-4ee9ff40641e.png">

他のプラグインと比べた特徴

- 制約を設ける ... サンドボックス、直接描画無し
- 制約を取り払う ... バイトコード+JITコンパイラ→プラットフォーム独立
- 拡張性
    - JavaScriptとの相互呼び出しが可能
    - JavaScriptと両方アクセスできるメモリー領域（バイト列）の読み書きが可能

<!--
||コード|インタープリター実行|JITコンパイラ|ネイティブ実行|サンドボックス|描画|
|---|---|---|---|---|---|---|
|Flash|独自バイトコード|〇||||〇|
|Java Applet|Javaバイトコード|〇|〇||〇|〇|
|Active X|ネイティブコード|||〇||〇|
|Silverlight|.NET中間コード(CLR)||〇||〇|〇|
|NaCl (Chrome Native Client)|ネイティブコード|||〇|〇|〇|
|PNaCl (Chrome Portable Native Client)|LLVMバイトコード||〇||〇|〇|
|asm.js|JavaScriptサブセット||〇||〇||
|WASM|.wasm||〇||〇||
-->

---

# WASMへの移行の流れ

独自プラグインはサポート終了の動き

- FlashはiOSで使えない。[2020年いっぱいでサポート終了予定](https://theblog.adobe.com/adobe-flash-update/)
- Active Xは 32bit IEでしか動かない
- Silverlight は 32bit/64bit IE のみ
- NaCl, PNaCl は[2019年Q2にサポート終了](https://developer.chrome.com/native-client/migration)

ブラウザの高速な拡張機能としてWASMが推奨されている

- Chrome, Firefox, Safari, (Edge) がそれぞれサポートを表明


---

# WASMの生成

- 手書き
- C/C++ ＋ [Emscripten](https://github.com/emscripten-core/emscripten)
- Rust
- Go
- TypeScript + [AssemblyScript]()
- [Walt](https://github.com/ballercat/walt) ... 型付きJavaScriptライク言語
- Node.js + ミニNode.js WASMトランスレーター(by massie_g) [mganeko/node_wasm](https://github.com/mganeko/node_wasm)

---

# WASMを手書き

- WAT を手書き
- WASM（バイナリに変換）
    - [binaryen]( https://github.com/WebAssembly/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
  )
)
```
```js:ブラウザで実行
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);
});
```

```js: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](https://bellard.org/jslinux/vm.html?url=https://bellard.org/jslinux/win2k.cfg&mem=192&graphic=1&w=1024&h=768) ... x86 PCエミュレーター
- [Vim を WebAssembly に移植した](https://rhysd.hatenablog.com/entry/2018/07/09/090115)
- CDNのエッジでWASMを実行 ... [Cloudflare](https://blog.cloudflare.com/webassembly-on-cloudflare-workers/)
- Ethereumのスマートコントラクト ... [次世代のEVM 「eWASM VM」について](https://blockchain.gunosy.io/entry/2018/06/20/155726)

---

# おわりに

- WASMはFlashに替わって、色々使われそう
- Go, Rust, C++ をWASM化して使えると嬉しいかも