# 機能設計書 22-onErrorCaptured()

## 概要

本ドキュメントは、Vue 3の`onErrorCaptured()`ライフサイクルフックの機能設計を記述する。子コンポーネントから伝搬するエラーをキャプチャし、エラーバウンダリとして機能するためのComposition APIフックである。

### 本機能の処理概要

`onErrorCaptured()`は、子孫コンポーネントで発生したエラーを親コンポーネントでキャプチャするためのライフサイクルフックである。Reactのエラーバウンダリに類似した機能をVueで実現するための中核的なAPIである。

**業務上の目的・背景**：アプリケーション開発において、子コンポーネントで発生するエラーがアプリケーション全体をクラッシュさせることを防ぐ必要がある。エラーバウンダリパターンにより、エラーを局所的にキャッチし、フォールバックUIの表示やエラーログの送信を行い、アプリケーションの堅牢性を確保する。

**機能の利用シーン**：エラーバウンダリコンポーネントの実装、エラーログの外部送信サービスへの転送、子コンポーネントのエラーに対するフォールバックUI表示、グローバルエラーハンドリングの補完。

**主要な処理内容**：
1. `onErrorCaptured(hook)`でエラーキャプチャフックをコンポーネントインスタンスの`ec`（error captured）配列に登録
2. 子孫コンポーネントでエラー発生時、`handleError`関数が親チェーンを辿り`ec`配列のフックを順次実行
3. フックが`false`を返した場合、エラー伝搬を停止
4. フックが`false`以外を返した場合、エラーは親に向かって伝搬を継続

**関連システム・外部連携**：`handleError`関数（エラー処理のエントリーポイント）、`app.config.errorHandler`（アプリケーションレベルのエラーハンドラ）と連携する。

**権限による制御**：権限による制御は存在しない。Composition APIのsetup()関数内でのみ使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし。エラーバウンダリとして任意のコンポーネントで使用される |

## 機能種別

ライフサイクルフック登録 / エラーハンドリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| hook | ErrorCapturedHook\<TError\> | Yes | エラーキャプチャ時に実行されるコールバック。(err, instance, info) => boolean \| void 型 | なし |
| target | ComponentInternalInstance \| null | No | フックを登録する対象コンポーネントインスタンス（省略時はcurrentInstance） | なし |

### 入力データソース

Composition APIのsetup()関数内からのプログラム呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | 戻り値なし。副作用としてコンポーネントインスタンスにフック関数を登録する |

### 出力先

コンポーネントインスタンス内部の`ec`（error captured hooks配列）プロパティ。

## 処理フロー

### 処理シーケンス

```
1. onErrorCaptured(hook) 呼び出し
   └─ injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target) を実行
2. injectHook内でエラーハンドリングラッパー(__weh)を生成
   └─ target.ec配列にフック関数を追加
3. 子孫コンポーネントでエラー発生
   └─ handleError(err, instance, type) が呼ばれる
4. handleError内で親チェーンを辿る
   └─ 各親コンポーネントのec配列のフックを順次実行
5. フックがfalseを返した場合
   └─ エラー伝搬を停止（return）
6. 全フック実行後もfalseが返されなかった場合
   └─ app.config.errorHandlerまたはconsole.errorにフォールスルー
```

### フローチャート

```mermaid
flowchart TD
    A[子孫コンポーネントでエラー発生] --> B[handleError呼び出し]
    B --> C[親コンポーネントへ遡行]
    C --> D{ec配列あり?}
    D -->|Yes| E[errorCapturedフック実行]
    D -->|No| F[次の親へ]
    E --> G{falseを返した?}
    G -->|Yes| H[エラー伝搬停止]
    G -->|No| F
    F --> I{親が存在?}
    I -->|Yes| C
    I -->|No| J{app.errorHandler設定あり?}
    J -->|Yes| K[app.errorHandler実行]
    J -->|No| L[console.errorに出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-22-01 | エラー伝搬停止 | フック関数がfalseを返すとエラーの上方伝搬を停止する | onErrorCapturedフック実行時 |
| BR-22-02 | 親チェーン走査 | handleErrorは発生元コンポーネントの親チェーンを順次辿り、各コンポーネントのecフックを実行する | エラー発生時 |
| BR-22-03 | 最終フォールバック | ecフックで処理されなかったエラーはapp.config.errorHandler、それもなければconsole.errorに到達する | エラー伝搬完了時 |
| BR-22-04 | SSR時無効 | SSRコンポーネントセットアップ中のフック登録は通常スキップされるが、onErrorCapturedはcreateHookではなく直接injectHookを呼ぶため、SSR中も登録される | SSR時 |

### 計算ロジック

該当なし。

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

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

該当なし（クライアントサイドフレームワーク機能）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 開発警告 | setup()関数外でonErrorCapturedを呼び出した場合 | activeなコンポーネントインスタンスが存在しない旨の警告を出力 |
| APP_ERROR_HANDLER | ランタイムエラー | app.config.errorHandler自体がエラーを投げた場合 | callWithErrorHandlingによりエラーをキャッチ |

### リトライ仕様

リトライ機構は存在しない。

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

該当なし。

## パフォーマンス要件

- エラー発生時の親チェーン走査はコンポーネントツリーの深さに比例するが、エラーは例外的状況であるため通常のパフォーマンスへの影響はない

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

- エラー情報にはコンポーネントの内部状態が含まれる可能性があるため、外部サービスへのエラーログ送信時には適切なサニタイズが必要

## 備考

- `onErrorCaptured`は`LifecycleHooks.ERROR_CAPTURED`（内部キー: `'ec'`）に対応
- `handleError`内で`cur.ec`として参照される（`injectHook`の`__weh`ラッパーではなく、直接`ec`配列として参照）
- Options APIの`errorCaptured`オプションに対応するComposition API

---

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

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

### 推奨読解順序

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

エラーキャプチャフックの型定義と、コンポーネントインスタンスでの格納先を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | `ErrorCapturedHook`型定義。`(err, instance, info) => boolean \| void`のシグネチャ |
| 1-2 | enums.ts | `packages/runtime-core/src/enums.ts` | `LifecycleHooks.ERROR_CAPTURED = 'ec'` |

**読解のコツ**: `ErrorCapturedHook`の戻り値`boolean | void`が重要。`false`を返すとエラー伝搬が停止し、`void`（undefinedを含む）の場合は伝搬が継続する。

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

`onErrorCaptured`関数の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | `onErrorCaptured`関数（111-116行目）。直接`injectHook`を呼び出す（`createHook`を使用しない） |

**主要処理フロー**:
1. **111-116行目**: `onErrorCaptured`関数。`injectHook(LifecycleHooks.ERROR_CAPTURED, hook, target)`を直接呼び出す
2. **20-64行目**: `injectHook`関数。`target[type]`（= `target.ec`）配列にラッパー関数を登録

#### Step 3: エラー伝搬メカニズムを理解する

`handleError`関数でエラーが親チェーンを辿る仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | `handleError`関数（112-155行目）。parentチェーン走査とecフック呼び出し |

**主要処理フロー**:
- **122行目**: `let cur = instance.parent`で親コンポーネントから走査開始
- **129-141行目**: `while(cur)`ループで各親の`cur.ec`（errorCapturedHooks）配列を走査
- **132-136行目**: 各フックを実行し、`=== false`の場合はreturnでエラー伝搬停止
- **143-151行目**: 全フック通過後、`app.config.errorHandler`が存在すれば呼び出し

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

```
onErrorCaptured(hook)
    │
    └─ injectHook(ERROR_CAPTURED, hook, target)
           └─ target.ec[] にフック追加

[エラー発生時]
handleError(err, instance, type)
    │
    ├─ 親チェーン走査
    │      └─ cur.ec[] の各フックを実行
    │             └─ false返却でエラー伝搬停止
    │
    ├─ app.config.errorHandler（フォールバック）
    │      └─ callWithErrorHandling(errorHandler, ...)
    │
    └─ logError（最終フォールバック）
           └─ console.error(err)
```

### データフロー図

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

hook (ErrorCapturedHook) ─▶ injectHook              ───▶ instance.ec[]
                                                          （フック配列に追加）

[エラー発生時]
Error発生               ─▶ handleError              ───▶ エラー処理結果
                              │                          ├─ 伝搬停止（false返却時）
                              ├─ 親チェーン走査           ├─ errorHandler呼び出し
                              └─ ec[]フック実行           └─ console.error出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apiLifecycle.ts | `packages/runtime-core/src/apiLifecycle.ts` | ソース | onErrorCaptured定義、ErrorCapturedHook型定義、injectHook関数 |
| errorHandling.ts | `packages/runtime-core/src/errorHandling.ts` | ソース | handleError関数（エラー伝搬ロジック）、callWithAsyncErrorHandling |
| enums.ts | `packages/runtime-core/src/enums.ts` | ソース | LifecycleHooks.ERROR_CAPTURED定義 |
| component.ts | `packages/runtime-core/src/component.ts` | ソース | ComponentInternalInstanceの定義（ecプロパティ含む） |
