# 機能設計書 33-非同期WASMモジュール

## 概要

本ドキュメントは、webpackにおけるWebAssemblyモジュールの非同期的な解析・コンパイル・ランタイム読み込み機能について記述する。lib/wasm-async/配下のモジュール群が、.wasmファイルの非同期読み込みとインスタンス化を担当する。

### 本機能の処理概要

非同期WASMモジュール機能は、WebAssembly（.wasm）ファイルを非同期モジュールとしてwebpackのモジュールシステムに統合する。同期版（wasm-sync）と異なり、Top Level Awaitを活用して非同期的にWASMモジュールをコンパイル・インスタンス化する。

**業務上の目的・背景**：WebAssembly仕様ではモジュールのコンパイルとインスタンス化は非同期APIを使用することが推奨されている。非同期方式を採用することで、ストリーミングコンパイル（WebAssembly.compileStreaming）が利用可能となり、大規模なWASMモジュールのロード性能が向上する。初期チャンクでの利用制限もない。

**機能の利用シーン**：experiments.asyncWebAssemblyが有効な場合（webpack 5のデフォルト推奨設定）に使用される。動的インポートやTop Level Awaitと組み合わせて、パフォーマンスクリティカルな処理をWASMで実装する場面で利用される。

**主要な処理内容**：
1. .wasmバイナリの解析（@webassemblyjs/wasm-parserによるデコード）
2. import/export情報の抽出と非同期モジュールとしてのフラグ設定
3. JavaScriptグルーコード（インポートオブジェクト構築・非同期初期化コード）の生成
4. AsyncWasmLoadingRuntimeModuleによるストリーミングコンパイル対応のランタイムコード生成
5. SyncWaterfallHookによるレンダリングカスタマイズ

**関連システム・外部連携**：@webassemblyjs/astおよび@webassemblyjs/wasm-parserライブラリに依存。ブラウザのWebAssembly.compileStreaming/WebAssembly.instantiate APIを利用する。

**権限による制御**：experiments.asyncWebAssembly設定により機能の有効/無効が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 非同期WASMモジュール処理はビルド時のインフラ機能であり、特定の画面に直接関連しない |

## 機能種別

モジュール解析・変換・コード生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | Buffer | Yes | .wasmファイルのバイナリデータ | Buffer.isBuffer()で検証 |
| mangleImports | boolean | No | インポート名をマングリングするかどうか | AsyncWebAssemblyModulesPluginOptions |
| generateLoadBinaryCode | function | Yes | WASMバイナリ読み込みコードを生成する関数 | AsyncWasmLoadingRuntimeModuleのコンストラクタに必須 |
| supportsStreaming | boolean | Yes | ストリーミングコンパイル対応かどうか | AsyncWasmLoadingRuntimeModuleのコンストラクタに必須 |

### 入力データソース

- ファイルシステムから読み込まれた.wasmバイナリファイル（Buffer形式）
- webpack設定のexperiments.asyncWebAssembly

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JavaScript glue code | Source | WASMモジュールの非同期初期化コード |
| WebAssembly binary | Source | 変換後のWASMバイナリ |
| ランタイムコード | string | WebAssembly.instantiateWasm関数のランタイム実装 |

### 出力先

バンドルファイル内にJavaScriptグルーコードとして出力。WASMバイナリは別ファイルとして出力。

## 処理フロー

### 処理シーケンス

```
1. WASMバイナリの解析
   └─ AsyncWebAssemblyParser.parseで@webassemblyjs/wasm-parserを使用してデコード
2. 非同期モジュールフラグ設定
   └─ buildMeta.async = trueを設定（Top Level Await対応）
3. 環境サポート確認
   └─ EnvironmentNotSupportAsyncWarningでasync未対応環境を警告
4. import/export情報の抽出
   └─ WebAssemblyImportDependencyとStaticExportsDependencyを生成
5. JavaScriptグルーコード生成
   └─ AsyncWebAssemblyJavascriptGeneratorがインポートオブジェクト構築コードを出力
6. WASMバイナリ変換
   └─ AsyncWebAssemblyGeneratorが変換を適用
7. ランタイムコード生成
   └─ AsyncWasmLoadingRuntimeModuleがinstantiateWasm関数を生成
```

### フローチャート

```mermaid
flowchart TD
    A[.wasmファイル読み込み] --> B[AsyncWebAssemblyParser.parse]
    B --> C[buildMeta.async = true]
    C --> D[EnvironmentNotSupportAsyncWarning.check]
    D --> E[WASMバイナリデコード]
    E --> F[import/export情報抽出]
    F --> G[AsyncWebAssemblyJavascriptGenerator]
    G --> H[非同期初期化コード生成]
    H --> I{supportsStreaming?}
    I -->|Yes| J[WebAssembly.compileStreaming使用]
    I -->|No| K[fetch + arrayBuffer + WebAssembly.instantiate使用]
    J --> L[ランタイムコード出力]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 非同期モジュール設定 | buildMeta.async=trueが設定され、Top Level Awaitとして扱われる | パース時 |
| BR-02 | 環境警告 | 非同期モジュールをサポートしない環境では警告を出力 | パース時 |
| BR-03 | ストリーミング優先 | supportsStreaming=trueの場合、WebAssembly.compileStreamingを優先使用 | ランタイムコード生成時 |
| BR-04 | フォールバック | ストリーミング失敗時はarrayBuffer + WebAssembly.instantiateにフォールバック | ランタイム実行時 |

### 計算ロジック

AsyncWasmLoadingRuntimeModule.generate()でwasmModuleSrcPathを計算する。compilation.getPathを使用してwebassemblyModuleFilenameテンプレートにハッシュ値とモジュールID/ハッシュを埋め込む。

## データベース操作仕様

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | AsyncWebAssemblyParser入力がBufferでない場合 | エラーをスロー |
| - | EnvironmentNotSupportAsyncWarning | async未対応のターゲット環境 | 警告を出力 |
| - | TypeError | compilationがCompilationインスタンスでない場合 | getCompilationHooksでTypeErrorをスロー |

### リトライ仕様

ストリーミングコンパイル失敗時はarrayBuffer方式へのフォールバックが自動的に行われる。

## トランザクション仕様

該当なし

## パフォーマンス要件

- WebAssembly.compileStreamingによるストリーミングコンパイルで大規模WASMモジュールのロード性能を最適化
- ignoreCodeSection, ignoreDataSectionによるパース高速化

## セキュリティ考慮事項

- WASMバイナリの解析はサードパーティライブラリに依存
- ストリーミングコンパイルはCORS制約の影響を受ける

## 備考

- webpack 5での推奨方式（experiments.asyncWebAssembly）
- SyncWaterfallHookのrenderModuleContentにより、WASMモジュールのレンダリングをカスタマイズ可能
- UniversalCompileAsyncWasmPluginはNode.js/ブラウザ両対応のWASM読み込みを提供

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

非同期WASMモジュールのデータ構造とオプションを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AsyncWebAssemblyModulesPlugin.js | `lib/wasm-async/AsyncWebAssemblyModulesPlugin.js` | 39-51行目: WebAssemblyRenderContext, CompilationHooks, AsyncWebAssemblyModulesPluginOptionsの型定義 |
| 1-2 | AsyncWasmLoadingRuntimeModule.js | `lib/wasm-async/AsyncWasmLoadingRuntimeModule.js` | 19-25行目: AsyncWasmLoadingRuntimeModuleOptionsの型定義 |

**読解のコツ**: 同期版（wasm-sync）との主な違いは、buildMeta.async=trueの設定とストリーミングコンパイル対応のランタイムコード生成にある。

#### Step 2: エントリーポイントを理解する

AsyncWebAssemblyModulesPluginが統合ポイントとなる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AsyncWebAssemblyModulesPlugin.js | `lib/wasm-async/AsyncWebAssemblyModulesPlugin.js` | 63-80行目: クラス定義・getCompilationHooks・apply() |

**主要処理フロー**:
1. **68-80行目**: getCompilationHooksでrenderModuleContentフックを初期化
2. apply()でWEBASSEMBLY_MODULE_TYPE_ASYNC用パーサ・ジェネレータを登録

#### Step 3: パーサ処理を理解する

AsyncWebAssemblyParserがWASMバイナリを非同期モジュールとして解析する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AsyncWebAssemblyParser.js | `lib/wasm-async/AsyncWebAssemblyParser.js` | 34-60行目: parse()メソッド |

**主要処理フロー**:
- **40-44行目**: buildInfo.strict=true, buildMeta.exportsType="namespace", buildMeta.async=trueの設定
- **45-48行目**: EnvironmentNotSupportAsyncWarning.checkで環境チェック
- **52-59行目**: WASMバイナリのデコードとModuleExportのトラバース

#### Step 4: ランタイムコード生成を理解する

AsyncWasmLoadingRuntimeModuleがインスタンス化コードを生成する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AsyncWasmLoadingRuntimeModule.js | `lib/wasm-async/AsyncWasmLoadingRuntimeModule.js` | 27-80行目: コンストラクタとgenerate()メソッド |

**主要処理フロー**:
- **31-46行目**: コンストラクタでgenerateLoadBinaryCode, supportsStreamingを保持
- **52-80行目**: generate()でwasmModuleSrcPathを計算しinstantiateWasm関数を生成
- **75-80行目**: フォールバックパス（arrayBuffer + WebAssembly.instantiate）

### プログラム呼び出し階層図

```
AsyncWebAssemblyModulesPlugin.apply()
    |
    +-- normalModuleFactory.hooks.createParser (WEBASSEMBLY_MODULE_TYPE_ASYNC)
    |      +-- AsyncWebAssemblyParser
    |             +-- @webassemblyjs/wasm-parser.decode()
    |             +-- EnvironmentNotSupportAsyncWarning.check()
    |             +-- WebAssemblyImportDependency (生成)
    |             +-- StaticExportsDependency (生成)
    |
    +-- normalModuleFactory.hooks.createGenerator (WEBASSEMBLY_MODULE_TYPE_ASYNC)
    |      +-- AsyncWebAssemblyJavascriptGenerator
    |      +-- AsyncWebAssemblyGenerator
    |
    +-- compilation.hooks.renderManifest
    |      +-- WASMバイナリアセット出力
    |
    +-- AsyncWasmLoadingRuntimeModule
           +-- generate() → instantiateWasm関数
```

### データフロー図

```
[入力]                      [処理]                              [出力]

.wasmバイナリ -----------> AsyncWebAssemblyParser          ---> 依存関係情報
  (Buffer)                   |                                  (async=true)
                             v
                       AsyncWebAssemblyJavascriptGenerator  ---> JSグルーコード
                             |
                             v
                       AsyncWebAssemblyGenerator            ---> 変換済みWASM
                             |
                             v
                       AsyncWasmLoadingRuntimeModule         ---> instantiateWasm
                                                                 (streaming対応)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AsyncWebAssemblyModulesPlugin.js | `lib/wasm-async/AsyncWebAssemblyModulesPlugin.js` | ソース | 非同期WASMモジュール機能の統合プラグイン |
| AsyncWebAssemblyParser.js | `lib/wasm-async/AsyncWebAssemblyParser.js` | ソース | WASMバイナリの非同期モジュールとしての解析 |
| AsyncWebAssemblyJavascriptGenerator.js | `lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js` | ソース | 非同期初期化用JSグルーコード生成 |
| AsyncWebAssemblyGenerator.js | `lib/wasm-async/AsyncWebAssemblyGenerator.js` | ソース | WASMバイナリの変換処理 |
| AsyncWasmLoadingRuntimeModule.js | `lib/wasm-async/AsyncWasmLoadingRuntimeModule.js` | ソース | 非同期WASMランタイム読み込みコード生成 |
| UniversalCompileAsyncWasmPlugin.js | `lib/wasm-async/UniversalCompileAsyncWasmPlugin.js` | ソース | Node.js/ブラウザ両対応のWASM読み込み |
