# 画面設計書 4-Wasm Browser Shutdown Sample

## 概要

本ドキュメントは、.NET WebAssembly のシャットダウン処理サンプル画面「Wasm Browser Shutdown Sample」の設計内容を記載した画面設計書です。本画面は .NET Runtime リポジトリにおける WebAssembly の各種終了処理・例外処理をテストするサンプルアプリケーションです。

### 本画面の処理概要

本画面は、ブラウザ上で .NET WebAssembly ランタイムの様々な終了シナリオ（マネージド例外、ネイティブアサート、FailFast、明示的 exit 呼び出し）をテストするためのサンプルアプリケーションです。各ボタンをクリックすることで異なる終了・例外パターンを実行できます。

**業務上の目的・背景**：本画面は、.NET WebAssembly アプリケーションの例外処理とシャットダウン動作を検証・デモンストレーションするために作成されました。実運用アプリケーションでは、エラー発生時の適切な終了処理が重要です。本サンプルでは、マネージド例外のスロー、Environment.FailFast による強制終了、ネイティブコード層でのアサート、正常な exit 呼び出しなど、様々なシナリオでの動作を確認できます。また、タイマーによる継続実行中の状態管理や、URL パラメータによる起動時エラーテストなども含まれています。

**画面へのアクセス方法**：ローカル開発サーバー（通常は `http://localhost:8000/`）にブラウザでアクセスすることで画面を表示できます。`?throwError=true` パラメータで起動時エラーをテストできます。

**主要な操作・処理内容**：
1. 「Throw Managed Exception」ボタン: C# のマネージド例外をスローしアラート表示
2. 「Trigger Native Assert」ボタン: ネイティブコードでアサートを発生
3. 「Trigger Environment.FailFast」ボタン: FailFast で強制終了
4. 「Call Harmless JSExport」ボタン: 正常な JSExport メソッド呼び出し
5. 「Call exit」ボタン: exit(7) でアプリケーション終了
6. 「Start Timer」ボタン: 1秒間隔のタイマーを開始し値を表示

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

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Mono | 主機能 | WebAssembly ランタイム上でシャットダウン処理を実行 |
| 59 | WebAssembly Workload | 主機能 | WebAssembly アプリケーションのビルドと実行をサポート |
| 40 | WasmAppBuilder | 補助機能 | WebAssembly アプリケーションのビルドサポート |

## 画面種別

インタラクティブテスト画面（単一画面）

## URL/ルーティング

- ローカル開発: `http://localhost:8000/index.html`
- エラーテスト: `http://localhost:8000/index.html?throwError=true`
- 静的ファイルパス: `src/mono/sample/wasm/browser-shutdown/wwwroot/index.html`

## 入出力項目

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

## 表示項目

| 項目ID | 項目名 | 要素タイプ | 説明 |
|--------|--------|-----------|------|
| header | 画面タイトル | h3 | 「Wasm Browser Shutdown Sample」と表示 |
| throw-managed-exc | マネージド例外ボタン | button | マネージド例外をスロー |
| trigger-native-assert | ネイティブアサートボタン | button | ネイティブアサートを発生 |
| trigger-failfast | FailFast ボタン | button | Environment.FailFast を呼び出し |
| call-jsexport | 正常呼び出しボタン | button | 正常な JSExport を呼び出し |
| call-exit | Exit ボタン | button | exit(7) を呼び出し |
| start-timer | タイマー開始ボタン | button | タイマーを開始 |
| timer-value | タイマー値 | span | タイマーのカウント値を表示 |

## イベント仕様

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

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

1. `main.js` がモジュールとして読み込まれる
2. URL パラメータ `?throwError=true` がある場合、onConfigLoaded で例外スロー
3. `dotnet.create()` で WebAssembly ランタイムを初期化
4. `setModuleImports` で timerTick 関数を C# から呼び出せるように登録
5. `getAssemblyExports` で C# の公開メソッドを取得
6. window.load イベントで各ボタンにクリックイベントを登録

### 2-Throw Managed Exception ボタンクリック

1. `exports.Sample.Test.ThrowManagedException()` を呼び出し
2. C# で `throw new Exception()` が実行される
3. JavaScript の try-catch で捕捉
4. `alert(exc)` で例外内容を表示

### 3-Trigger Native Assert ボタンクリック

1. `setenv(null, null)` を呼び出し
2. ネイティブコードで null パラメータによりアサートが発生
3. JavaScript の try-catch で捕捉
4. `alert(exc)` で例外内容を表示

### 4-Trigger Environment.FailFast ボタンクリック

1. `exports.Sample.Test.CallFailFast()` を呼び出し
2. C# で `Environment.FailFast("User requested FailFast")` が実行される
3. ランタイムが強制終了

### 5-Call Harmless JSExport ボタンクリック

1. `exports.Sample.Test.DoNothing()` を呼び出し
2. C# で `Console.WriteLine("You got it, boss! Doing nothing!")` が実行される
3. 正常に処理が完了

### 6-Call exit ボタンクリック

1. `exit(7, "User clicked exit")` を呼び出し
2. 終了コード 7 でアプリケーションが終了

### 7-Start Timer ボタンクリック

1. `exports.Sample.Test.StartTimer()` を呼び出し
2. C# で 1 秒間隔のタイマーが開始
3. タイマー発火ごとに `TimerTick(i)` で JavaScript に通知
4. DOM の timer-value 要素が更新される

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

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

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

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG-001 | エラー | I'll make an exception to the rules just this once... and throw one. | マネージド例外スロー時 |
| MSG-002 | 情報 | You got it, boss! Doing nothing! | DoNothing 呼び出し時にコンソール出力 |
| MSG-003 | エラー | User requested FailFast | FailFast 呼び出し時 |
| MSG-004 | アラート | No JS exception was thrown! | 例外が発生しなかった場合 |
| MSG-005 | エラー | Error thrown from OnConfigLoaded | ?throwError=true パラメータ時 |

## 例外処理

| 例外種別 | 発生条件 | 対応処理 |
|---------|---------|---------|
| マネージド例外 | ThrowManagedException 呼び出し時 | alert() で例外内容を表示 |
| ネイティブアサート | setenv(null, null) 呼び出し時 | alert() で例外内容を表示 |
| FailFast | CallFailFast 呼び出し時 | ランタイム強制終了 |
| OnConfigLoaded エラー | ?throwError=true パラメータ時 | `exit(2, err)` で終了 |

## 備考

- `appendElementOnExit: true` 設定により、終了時に状態が DOM に表示される
- `exitOnUnhandledError: true` 設定により、未処理例外発生時にアプリケーションが終了
- `logExitCode: true` 設定により、終了コードがログ出力される
- タイマーは `System.Timers.Timer` を使用し AutoReset で繰り返し実行

---

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

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

### 推奨読解順序

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

まず、JavaScript と C# 間で受け渡されるデータとイベントの流れを理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Program.cs | `src/mono/sample/wasm/browser-shutdown/Program.cs` | JSImport/JSExport 属性と例外処理メソッドを確認 |

**読解のコツ**: `[JSExport]` 属性付きメソッドが JavaScript から呼び出せる公開 API です。各メソッドの例外パターンを確認してください。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.html | `src/mono/sample/wasm/browser-shutdown/wwwroot/index.html` | HTML 構造と各ボタン要素を確認 |
| 2-2 | main.js | `src/mono/sample/wasm/browser-shutdown/wwwroot/main.js` | ランタイム初期化とイベントハンドラ登録を確認 |

**主要処理フロー (main.js)**:
1. **9行目**: window.load イベントで onLoad 関数を登録
2. **11-38行目**: dotnet.create() でランタイム初期化
3. **16-22行目**: onConfigLoaded で URL パラメータチェック
4. **26-31行目**: setModuleImports で timerTick 関数を公開
5. **40-86行目**: onLoad で各ボタンにクリックイベントを登録

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Program.cs | `src/mono/sample/wasm/browser-shutdown/Program.cs` | 各終了パターンの実装を確認 |

**主要処理フロー (Program.cs)**:
- **17-21行目**: `DoNothing` - 正常な JSExport メソッド
- **23-27行目**: `ThrowManagedException` - マネージド例外スロー
- **29-33行目**: `CallFailFast` - Environment.FailFast 呼び出し
- **35-36行目**: `TimerTick` - JSImport でタイマー値を JavaScript に通知
- **38-49行目**: `StartTimer` - 1秒間隔タイマーの開始

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

```
[Browser] index.html 読み込み
    |
    +-- [JavaScript] main.js 実行
            |
            +-- dotnet.create() - WebAssembly ランタイム初期化
            |       |
            |       +-- onConfigLoaded() - URL パラメータチェック
            |               |
            |               +-- (?throwError=true の場合) throw new Error()
            |
            +-- setModuleImports() - timerTick 関数を公開
            |
            +-- getAssemblyExports() - C# メソッドを取得
            |
            +-- window.onload -> onLoad()
                    |
                    +-- ボタンイベント登録
                            |
                            +-- #throw-managed-exc.click
                            |       |
                            |       +-- exports.Sample.Test.ThrowManagedException()
                            |               |
                            |               +-- [C#] throw new Exception()
                            |               +-- [JavaScript] catch -> alert()
                            |
                            +-- #trigger-failfast.click
                            |       |
                            |       +-- exports.Sample.Test.CallFailFast()
                            |               |
                            |               +-- [C#] Environment.FailFast()
                            |
                            +-- #start-timer.click
                            |       |
                            |       +-- exports.Sample.Test.StartTimer()
                            |               |
                            |               +-- [C#] new Timer(1000)
                            |                       |
                            |                       +-- Elapsed イベント
                            |                               |
                            |                               +-- TimerTick(i)
                            |                                       |
                            |                                       +-- [JavaScript] timerTick(i)
                            |                                               |
                            |                                               +-- DOM 更新
                            |
                            +-- #call-exit.click
                                    |
                                    +-- exit(7, "User clicked exit")
```

### データフロー図

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

ボタンクリック
    |
    +-- #throw-managed-exc --> ThrowManagedException() --> alert(例外メッセージ)
    |
    +-- #trigger-native-assert --> setenv(null, null) --> alert(アサートエラー)
    |
    +-- #trigger-failfast --> CallFailFast() --> ランタイム強制終了
    |
    +-- #call-jsexport --> DoNothing() --> Console.WriteLine()
    |
    +-- #call-exit --> exit(7) --> アプリケーション終了
    |
    +-- #start-timer --> StartTimer()
                              |
                              v
                        Timer.Elapsed (1秒ごと)
                              |
                              v
                        TimerTick(i)
                              |
                              v
                        timerTick(i) [JavaScript]
                              |
                              v
                        #timer-value.textContent = i
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.html | `src/mono/sample/wasm/browser-shutdown/wwwroot/index.html` | テンプレート | HTML エントリーポイント、ボタン定義 |
| main.js | `src/mono/sample/wasm/browser-shutdown/wwwroot/main.js` | ソース | JavaScript エントリーポイント、イベントハンドラ |
| Program.cs | `src/mono/sample/wasm/browser-shutdown/Program.cs` | ソース | C# メインロジック、例外処理、タイマー |
| dotnet.js | `_framework/dotnet.js` | ランタイム | .NET WebAssembly ランタイムローダー（ビルド時生成） |
