# 機能設計書 28-h()

## 概要

本ドキュメントは、Vue 3の`h()`関数の機能設計を記述する。レンダリング関数内でVNode（仮想DOMノード）を生成するためのヘルパー関数であり、テンプレートを使わずにプログラマティックにUIを構築する際に使用される。

### 本機能の処理概要

`h()`は`createVNode()`のユーザーフレンドリーなラッパー関数であり、HTML要素・コンポーネント・Fragment・Teleport・Suspense等のVNodeを生成する。propsの省略やchildrenの柔軟な指定が可能で、JSX/TSXと組み合わせて使用できる。

**業務上の目的・背景**：テンプレート構文では表現しにくい動的なUIの構築（動的コンポーネントの切り替え、プログラマティックなリスト生成、条件に応じた複雑なVNodeツリー構築等）が必要な場合に、レンダリング関数による直接的なVNode生成が求められる。`h()`はその標準APIとして提供される。

**機能の利用シーン**：レンダリング関数（`render()`オプション）内でのVNode生成、JSX/TSXでのコンポーネント記述、動的コンポーネントの条件分岐レンダリング、Options Panelのような動的UI構築（画面No.5で使用）。

**主要な処理内容**：
1. 引数の数と型を判定して適切な`createVNode`呼び出しパターンを決定
2. 2引数の場合：props/children/単一VNodeの判別
3. 3引数以上の場合：childrenの配列化処理
4. `setBlockTracking(-1)`でブロックトラッキングを一時無効化し、`createVNode`を呼び出し
5. `finally`ブロックで`setBlockTracking(1)`によりトラッキングを復元

**関連システム・外部連携**：`createVNode()`（VNode生成のコア関数）、テンプレートコンパイラ（コンパイラは`createVNode`を直接使用し`h()`は使用しない）、JSX/TSXトランスパイラと連携する。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | Options Panel（コンパイルオプション） | 主機能 | レンダリング関数によるラジオボタン・チェックボックス群のUI構築 |

## 機能種別

VNode生成 / UI構築

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | string \| Component \| typeof Fragment \| typeof Text \| typeof Comment \| typeof Teleport \| typeof Suspense | Yes | VNodeのタイプ（HTML要素名、コンポーネント、組み込みシンボル等） | なし |
| propsOrChildren | RawProps \| null \| RawChildren | No | プロパティオブジェクト、またはprops省略時の子要素 | なし |
| children | RawChildren \| RawSlots | No | 子要素（文字列、VNode、VNode配列、スロットオブジェクト、関数等） | なし |

### 入力データソース

レンダリング関数（`render()`オプション、`setup()`の戻り値関数）内からのプログラム呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| vnode | VNode | 生成されたVNode（仮想DOMノード） |

### 出力先

呼び出し元への戻り値。レンダリングパイプラインで処理され、最終的にDOM要素に変換される。

## 処理フロー

### 処理シーケンス

```
1. h(type, propsOrChildren?, children?) 呼び出し
   └─ setBlockTracking(-1) でブロックトラッキング無効化
2. arguments.length による分岐
   ├─ l === 2（2引数）
   │      ├─ isObject(propsOrChildren) && !isArray(propsOrChildren)
   │      │      ├─ isVNode(propsOrChildren) → createVNode(type, null, [propsOrChildren])
   │      │      └─ !isVNode → createVNode(type, propsOrChildren)  [props指定]
   │      └─ else → createVNode(type, null, propsOrChildren)  [children指定]
   └─ l >= 3
          ├─ l > 3 → children = Array.prototype.slice.call(arguments, 2)
          ├─ l === 3 && isVNode(children) → children = [children]
          └─ createVNode(type, propsOrChildren, children)
3. finally: setBlockTracking(1) でトラッキング復元
4. VNode を返却
```

### フローチャート

```mermaid
flowchart TD
    A[h type, propsOrChildren, children] --> B[setBlockTracking -1]
    B --> C{引数の数?}
    C -->|2| D{propsOrChildrenはオブジェクト かつ 非配列?}
    D -->|Yes| E{isVNode?}
    E -->|Yes| F[createVNode type, null, propsOrChildren]
    E -->|No| G[createVNode type, propsOrChildren]
    D -->|No| H[createVNode type, null, propsOrChildren]
    C -->|3| I{l > 3?}
    I -->|Yes| J[children = arguments 2..n]
    I -->|No| K{isVNode children?}
    K -->|Yes| L[children = children配列化]
    K -->|No| M[そのまま]
    J --> N[createVNode type, propsOrChildren, children]
    L --> N
    M --> N
    F --> O[setBlockTracking 1]
    G --> O
    H --> O
    N --> O
    O --> P[VNode返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | ブロックトラッキング無効化 | h()内ではsetBlockTracking(-1)でブロックトラッキングを無効化し、コンパイラ最適化との干渉を回避する（#6913） | h()呼び出し時 |
| BR-28-02 | 引数柔軟性 | 2引数の場合、第2引数がオブジェクト（非配列）かつVNodeでない場合はpropsとして扱い、それ以外はchildrenとして扱う | 2引数呼び出し時 |
| BR-28-03 | VNode配列化 | 3引数でchildrenが単一VNodeの場合は配列に変換する | 3引数呼び出し時 |
| BR-28-04 | 可変長引数対応 | 4引数以上の場合はarguments[2]以降を配列としてchildren扱い | 4引数以上 |
| BR-28-05 | コンパイラとの差異 | コンパイラは`createVNode`を直接使用し`h()`は使用しない。これはモノモーフィック性と追加呼び出しオーバーヘッド回避のため | コンパイル時 |

### 計算ロジック

該当なし。

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | TypeScript型エラー | 不正なprops型の指定 | 多数のオーバーロード定義により型安全性を確保 |

### リトライ仕様

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

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

該当なし。

## パフォーマンス要件

- `h()`は`createVNode`のラッパーであるため、わずかなオーバーヘッドがある。大量のVNode生成では`createVNode`の直接使用が推奨される
- `setBlockTracking(-1/1)`の切り替えはtry-finallyで確実に復元される

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

- `h()`で直接HTMLを挿入する場合（innerHTML）、XSSリスクがある。ユーザー入力は適切にエスケープすること

## 備考

- `h()`は24個のオーバーロード定義を持ち、HTML要素、コンポーネント、Fragment、Text、Comment、Teleport、Suspense等の様々なVNodeタイプに対応
- コンパイラ生成コードは`createVNode`を直接使用するため、`h()`は手書きのレンダリング関数専用
- JSX/TSXでは`h()`ではなくJSXファクトリ（通常は自動設定）を通じてVNodeが生成される

---

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

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

### 推奨読解順序

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

h()の引数型定義とVNode型を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | h.ts | `packages/runtime-core/src/h.ts` | `RawProps`型（56-61行目）、`RawChildren`型（63-69行目）。h()の入力型を定義 |

**読解のコツ**: `RawProps`はVNodePropsを拡張し、`__v_isVNode`と`[Symbol.iterator]`を`never`で除外している。これによりVNodeやArrayとpropsの型を区別可能にしている。

#### Step 2: オーバーロード定義を理解する

多数のオーバーロード定義による型安全性を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | h.ts | `packages/runtime-core/src/h.ts` | 24個のオーバーロード定義（89-201行目）。HTML要素、カスタム要素、Text/Comment、Fragment、Teleport、Suspense、関数型コンポーネント、クラスコンポーネント等 |

**主要処理フロー**:
1. **89-97行目**: HTML要素用オーバーロード（HTMLElementTagNameMap対応）
2. **100-105行目**: カスタム要素用オーバーロード（string型）
3. **108-123行目**: Text/Comment/Fragment用オーバーロード
4. **126-130行目**: Teleport用オーバーロード（target propが必須）
5. **141-149行目**: 関数型コンポーネント用オーバーロード

#### Step 3: 実装を理解する

実際の引数判別ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | h.ts | `packages/runtime-core/src/h.ts` | 実装関数（204-232行目） |

**主要処理フロー**:
- **206-207行目**: `setBlockTracking(-1)`でブロックトラッキング無効化、`const l = arguments.length`
- **209-220行目**: 2引数分岐。isObject/isArray/isVNodeの判定
- **221-228行目**: 3引数以上分岐。l>3での配列化、isVNodeの配列ラップ
- **229-231行目**: finally内で`setBlockTracking(1)`復元

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

```
h(type, propsOrChildren?, children?)
    │
    ├─ setBlockTracking(-1)
    │
    ├─ 引数判別
    │      ├─ 2引数 + Object + VNode → createVNode(type, null, [propsOrChildren])
    │      ├─ 2引数 + Object + !VNode → createVNode(type, propsOrChildren)
    │      ├─ 2引数 + 非Object → createVNode(type, null, propsOrChildren)
    │      └─ 3引数以上 → createVNode(type, propsOrChildren, children)
    │
    ├─ createVNode(type, props, children)
    │      └─ VNode生成（vnode.ts）
    │
    └─ setBlockTracking(1)  [finally]
```

### データフロー図

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

type (string/Component) ───▶ h()                    ───▶ VNode
props? (Object)          ───▶   │
children? (various)      ───▶   ├─ 引数判別
                                 ├─ createVNode(type, props, children)
                                 └─ VNode生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| h.ts | `packages/runtime-core/src/h.ts` | ソース | h()関数の全オーバーロード定義と実装 |
| vnode.ts | `packages/runtime-core/src/vnode.ts` | ソース | createVNode関数、VNode型定義 |
| index.ts | `packages/runtime-core/src/index.ts` | ソース | h関数のre-export |
