# 画面設計書 2-Wasm Browser Advanced Sample

## 概要

本ドキュメントは、.NET WebAssembly の高度なブラウザサンプル画面「Wasm Browser Advanced Sample」の設計内容を記載した画面設計書です。本画面は .NET Runtime リポジトリにおける WebAssembly の高度な機能（CSP、preload/prefetch、カスタムリソースローダー等）をデモンストレーションするサンプルアプリケーションです。

### 本画面の処理概要

本画面は、ブラウザ上で .NET WebAssembly ランタイムの高度な設定と機能を検証するためのサンプルアプリケーションです。Content-Security-Policy（CSP）の設定、リソースのプリロード/プリフェッチ、カスタムモジュール設定、ネイティブ C ライブラリ（Fibonacci）の呼び出し、エラーリトライ機能などの高度な機能を実装しています。

**業務上の目的・背景**：本画面は、.NET WebAssembly ランタイムの高度な設定方法を開発者に示すことを目的としています。セキュリティ要件の厳しい環境（CSP 設定が必要な環境）での WebAssembly 利用方法、パフォーマンス最適化（preload/prefetch）、ネイティブコードとの連携（LibraryImport）、ランタイムの詳細なカスタマイズ方法など、実践的なシナリオで必要となる高度なテクニックを学べるよう設計されています。

**画面へのアクセス方法**：ローカル開発サーバー（通常は `http://localhost:8000/`）にブラウザでアクセスすることで画面を表示できます。ビルドは `dotnet build` コマンドで行います。

**主要な操作・処理内容**：
1. 画面ロード時に CSP ヘッダーによりスクリプト実行が制限される（wasm-unsafe-eval 許可）
2. preload/prefetch によりリソースを事前読み込み
3. JavaScript（main.js）が .NET WebAssembly ランタイムを高度な設定で初期化
4. カスタムフェッチ処理でアセンブリ読み込みのリトライをテスト
5. C# 側でネイティブ C ライブラリ（fibonacci）を呼び出しフィボナッチ数を計算
6. タイムゾーン情報の取得とコンソール出力
7. プロファイラー設定による実行時パフォーマンス計測
8. 結果を DOM に表示

**画面遷移**：本画面は単一画面のサンプルアプリケーションであり、他画面への遷移はありません。

**権限による表示制御**：本画面は認証・認可機能を持たないデモアプリケーションであり、権限による表示制御はありません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Mono | 主機能 | WebAssembly ランタイム上で高度な .NET コードを実行するメイン処理 |
| 59 | WebAssembly Workload | 主機能 | WebAssembly アプリケーションのビルドと実行をサポート |
| 40 | WasmAppBuilder | 補助機能 | WebAssembly アプリケーションのビルドサポート |
| 6 | インタープリター | 補助機能 | JIT が利用できない環境での IL インタープリター実行 |

## 画面種別

デモ表示画面（単一画面）

## URL/ルーティング

- ローカル開発: `http://localhost:8000/index.html`
- 静的ファイルパス: `src/mono/sample/wasm/browser-advanced/wwwroot/index.html`

## 入出力項目

| 項目名 | 入出力 | データ型 | 説明 |
|--------|--------|----------|------|
| - | - | - | 本画面にユーザー入力項目はありません |

## 表示項目

| 項目ID | 項目名 | 要素タイプ | 説明 |
|--------|--------|-----------|------|
| header | 画面タイトル | h3 | 「Wasm Browser Advanced Sample」と表示 |
| out | 計算結果 | span | 計算結果とランタイムバージョンを表示 |

## イベント仕様

### 1-画面ロード完了イベント

画面がロードされると、以下の処理が自動的に実行されます:

1. CSP ポリシーにより `wasm-unsafe-eval` のみ許可されたスクリプト実行環境を確立
2. preload/prefetch によりランタイムファイルを事前取得
3. `main.js` がモジュールとして読み込まれる
4. カスタムフェッチでアセンブリ読み込みリトライをテスト
5. `dotnet.download()` でリソースをダウンロード
6. `dotnet.create()` で WebAssembly ランタイムを高度な設定で初期化
7. `onConfigLoaded` コールバックで環境変数とプロファイラーを設定
8. C# の `TestMeaning()` を呼び出しフィボナッチ計算を実行
9. 素数判定と結果の DOM 表示
10. `runMain()` で Main メソッドを実行

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面はデータベースを使用しません |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | デバッグ | fetching {url} | 各リソース取得時にコンソール出力 |
| MSG-002 | 情報 | Hello, World! | Main メソッド実行時 |
| MSG-003 | 情報 | Today's lucky number is {n} and {guid} | ランダム数と GUID 生成時 |
| MSG-004 | 情報 | Found {n} timezones in the TZ database | タイムゾーン取得完了時 |
| MSG-005 | エラー | Could not find Asia/Tokyo: {message} | タイムゾーン検索失敗時 |
| MSG-006 | デバッグ | Module.onConfigLoaded/preInit/preRun/onRuntimeInitialized/onDotnetReady/postRun | 各ライフサイクルフック実行時 |

## 例外処理

| 例外種別 | 発生条件 | 対応処理 |
|---------|---------|---------|
| JavaScript エラー | WebAssembly ランタイム初期化失敗時 | `exit(2, err)` を呼び出してエラーコード2で終了 |
| TimeZoneNotFoundException | タイムゾーン検索失敗時 | catch ブロックでエラーメッセージをコンソール出力 |
| GL オブジェクト未検出 | Module.GL が見つからない場合 | `exit(-10, "Can't find GL")` で終了 |
| IDBFS 未検出 | Module.FS.filesystems.IDBFS が見つからない場合 | `exit(-10, "Can't find FS.filesystems.IDBFS")` で終了 |

## 備考

- Content-Security-Policy により `wasm-unsafe-eval` のみ許可（セキュアな環境でのWasm実行例）
- `maxParallelDownloads: 1` で並列ダウンロードを制限（テスト目的）
- カスタムフェッチでリトライ機能をテスト（testAbort, testError パラメータ）
- browserProfilerOptions で実行時プロファイリングを設定
- ネイティブ C ライブラリ（fibonacci）との連携をデモ

---

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

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

### 推奨読解順序

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

まず、JavaScript と C# 間で受け渡されるデータとネイティブライブラリのインターフェースを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Program.cs | `src/mono/sample/wasm/browser-advanced/Program.cs` | JSImport/JSExport/LibraryImport 属性によるインターフェース定義を確認 |

**読解のコツ**: `[LibraryImport("fibonacci")]` はネイティブ C ライブラリを呼び出すマーカーです。P/Invoke の現代的な書き方です。

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

処理の起点となるファイル・関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html | `src/mono/sample/wasm/browser-advanced/wwwroot/index.html` | CSP設定、preload/prefetch、HTML構造を確認 |
| 2-2 | main.js | `src/mono/sample/wasm/browser-advanced/wwwroot/main.js` | 高度なランタイム初期化処理を確認 |

**主要処理フロー (index.html)**:
1. **11行目**: CSP メタタグで `wasm-unsafe-eval` を許可
2. **14-17行目**: preload/prefetch でリソースを事前取得

**主要処理フロー (main.js)**:
1. **14-33行目**: カスタムフェッチでリトライをテスト
2. **34-75行目**: `dotnet.withConfig()` と `withModuleConfig()` で詳細設定
3. **48-56行目**: `onConfigLoaded` で環境変数とプロファイラー設定
4. **72-75行目**: `withResourceLoader` でリソースURLにバージョンパラメータ追加
5. **77行目**: `dotnet.download()` でリソースダウンロード
6. **79行目**: `dotnet.create()` でランタイム作成
7. **93-103行目**: C# メソッド呼び出しと結果表示

#### Step 3: C# 側の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Program.cs | `src/mono/sample/wasm/browser-advanced/Program.cs` | Main メソッドとネイティブ連携、タイムゾーン処理を確認 |

**主要処理フロー (Program.cs)**:
- **14-42行目**: `Main` メソッド - タイムゾーン情報取得と表示
- **44-45行目**: `Fibonacci` - ネイティブ C 関数呼び出し
- **47-52行目**: `Add`, `Delay` - JSImport による JavaScript 関数呼び出し
- **61-67行目**: `TestMeaning` - Fibonacci と Add を組み合わせた計算
- **69-97行目**: `SillyLoop` - プロファイラー用のサンプルコード
- **99-113行目**: `IsPrime` - 素数判定ロジック

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

```
[Browser] index.html 読み込み
    |
    +-- CSP ポリシー適用
    |
    +-- preload/prefetch リソース取得
    |
    +-- [JavaScript] main.js 実行
            |
            +-- カスタムフェッチ設定（リトライテスト）
            |
            +-- dotnet.withConfig() / withModuleConfig()
            |       |
            |       +-- onConfigLoaded() - 環境変数設定
            |       +-- browserProfilerOptions 設定
            |
            +-- dotnet.download() - リソースダウンロード
            |
            +-- dotnet.create() - ランタイム初期化
            |       |
            |       +-- preInit / preRun / onRuntimeInitialized
            |       +-- onDotnetReady / postRun
            |
            +-- setModuleImports() - add, delay 関数を C# に公開
            |
            +-- getAssemblyExports() - C# メソッドを取得
            |
            +-- exports.Sample.Test.TestMeaning()
            |       |
            |       +-- [C#] TestMeaning() 実行
            |               |
            |               +-- [Native C] Fibonacci(8) - フィボナッチ計算
            |               +-- [JavaScript] Add(half, half) - 加算
            |
            +-- exports.Sample.Test.IsPrime(meaning)
            |       |
            |       +-- [C#] IsPrime() - 素数判定
            |
            +-- DOM 更新（結果表示）
            |
            +-- exports.Sample.Test.PrintMeaning(promise)
            |
            +-- exports.Sample.Test.SillyLoop()
            |
            +-- runMain() - C# Main 実行
                    |
                    +-- [C#] Main() - タイムゾーン処理
```

### データフロー図

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

URL パラメータ             カスタムフェッチ
(?testAbort, ?testError) --> (リトライテスト) -------> コンソールログ

                     +-- dotnet.create() ----+
                     |   (高度な初期化)       |
                     +----------------------+
                              |
                              v
                     +-- TestMeaning() ----+
                     |                     |
                     v                     v
              Fibonacci(8)            Add(half, half)
              [Native C]              [JavaScript]
                     |                     |
                     +-----> 42 <----------+
                              |
                              v
                     +-- IsPrime(42) ----+
                     |   (素数判定)       |
                     +---------+---------+
                               |
                               v
                     document.getElementById("out")
                        .innerHTML = "42 as computed..."
                         (DOM 表示更新)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html | `src/mono/sample/wasm/browser-advanced/wwwroot/index.html` | テンプレート | HTML エントリーポイント、CSP/preload 設定 |
| main.js | `src/mono/sample/wasm/browser-advanced/wwwroot/main.js` | ソース | JavaScript エントリーポイント、高度なランタイム初期化 |
| Program.cs | `src/mono/sample/wasm/browser-advanced/Program.cs` | ソース | C# メインロジック、ネイティブ連携、タイムゾーン処理 |
| dotnet.js | `wwwroot/dotnet.js` | ランタイム | .NET WebAssembly ランタイムローダー |
| advanced-sample.lib.module.js | `wwwroot/advanced-sample.lib.module.js` | 設定 | 追加モジュール設定（ビルド時生成） |
| dotnet.boot.js | `wwwroot/dotnet.boot.js` | ランタイム | ブートストラップ設定（preload 対象） |
