# 機能設計書 26-render()

## 概要

本ドキュメントは、Vue 3の`render()`関数の機能設計を記述する。VNodeツリーをブラウザDOMにレンダリング（マウント・更新・アンマウント）するための低レベルAPIであり、`createApp().mount()`の内部実装として使用される。

### 本機能の処理概要

`render()`は`@vue/runtime-dom`パッケージが公開するDOM描画関数であり、VNodeとDOMコンテナ要素を受け取り、VNodeツリーを実際のDOMに変換・反映する。内部的にはレンダラーの`patch`アルゴリズムを使用して差分更新を行い、不要なVNodeについてはDOMから`unmount`する。

**業務上の目的・背景**：Vueアプリケーションのコア描画メカニズムとして、宣言的に定義されたコンポーネントツリー（VNode）を実際のブラウザDOMに変換する必要がある。`render()`はこの変換処理の最上位エントリーポイントであり、`createApp().mount()`から間接的に呼び出されるほか、テスト環境やマイクロフロントエンド等で直接使用されることもある。

**機能の利用シーン**：`createApp().mount()`内部からの呼び出し、テスト環境での直接レンダリング、ポータル/マイクロフロントエンドでの部分的なVueツリーのマウント、カスタムレンダラーの構築。

**主要な処理内容**：
1. `render(vnode, container, namespace?)`の呼び出し
2. vnodeがnullの場合：既存のVNodeが存在すれば`unmount`処理を実行
3. vnodeが存在する場合：`patch(container._vnode, vnode, container, ...)`でDOM差分更新
4. `container._vnode = vnode`で現在のVNodeを記録
5. `flushPreFlushCbs`と`flushPostFlushCbs`で保留中のコールバックをフラッシュ

**関連システム・外部連携**：`createApp()`（アプリケーション作成）、`createRenderer()`（レンダラー生成）、`nodeOps`（DOM操作の抽象化層）、`patchProp`（プロパティパッチング）と連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし。全てのVue画面のDOM描画で内部的に使用される |

## 機能種別

DOM操作 / レンダリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| vnode | VNode \| null | Yes | レンダリングするVNodeツリー。nullの場合はアンマウント処理 | なし |
| container | Element \| ShadowRoot | Yes | DOMの描画先コンテナ要素 | なし |
| namespace | ElementNamespace | No | SVG/MathML名前空間の指定（'svg' \| 'mathml' \| undefined） | なし |

### 入力データソース

`createApp().mount()`内部からの呼び出し、またはユーザーコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | 戻り値なし。副作用としてDOMを操作する |

### 出力先

引数で指定されたDOMコンテナ要素。

## 処理フロー

### 処理シーケンス

```
1. render(vnode, container, namespace) 呼び出し
   └─ ensureRenderer() でレンダラーインスタンスを遅延生成
2. vnode === null の場合
   ├─ container._vnode が存在する場合
   │      └─ unmount(container._vnode, null, null, true)
   └─ container._vnode が存在しない場合は何もしない
3. vnode !== null の場合
   └─ patch(container._vnode || null, vnode, container, null, null, null, namespace)
4. container._vnode = vnode で現在のVNode参照を更新
5. isFlushing フラグ制御
   └─ flushPreFlushCbs() → flushPostFlushCbs() で保留コールバック実行
```

### フローチャート

```mermaid
flowchart TD
    A[render vnode, container] --> B{vnode === null?}
    B -->|Yes| C{container._vnode 存在?}
    C -->|Yes| D[unmount container._vnode]
    C -->|No| E[何もしない]
    B -->|No| F[patch container._vnode, vnode, container]
    D --> G[container._vnode = vnode]
    E --> G
    F --> G
    G --> H{isFlushing?}
    H -->|No| I[flushPreFlushCbs]
    I --> J[flushPostFlushCbs]
    J --> K[isFlushing = false]
    H -->|Yes| L[スキップ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | 遅延レンダラー生成 | ensureRenderer()によりレンダラーは初回使用時に遅延生成され、ツリーシェイキングを可能にする | 初回render呼び出し時 |
| BR-26-02 | vnull=アンマウント | vnodeにnullを渡すと既存のVNodeツリーをアンマウントする | vnode === null時 |
| BR-26-03 | 差分更新 | patch関数により前回のVNode（container._vnode）と新しいVNodeを比較し、差分のみDOMに反映する | vnode !== null時 |
| BR-26-04 | VNode参照記録 | container._vnodeに現在のVNodeを常に記録し、次回の差分更新に使用する | render呼び出し後 |
| BR-26-05 | フラッシュ制御 | render後にisFlushing未設定の場合のみ、pre/postフラッシュコールバックを実行する | render完了後 |

### 計算ロジック

該当なし。

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| COMPONENT_UPDATE | ランタイムエラー | patch処理中にコンポーネント更新でエラーが発生した場合 | callWithErrorHandlingによりエラーをキャッチし、handleErrorで処理 |

### リトライ仕様

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

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

該当なし。

## パフォーマンス要件

- patchアルゴリズムによる差分更新でDOM操作を最小化
- ensureRenderer()による遅延初期化でツリーシェイキングを実現
- PatchFlagsによるコンパイル時最適化ヒントの活用

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

- VNodeにユーザー入力が直接含まれる場合、XSSリスクがある。テンプレートコンパイラ側でエスケープ処理が行われる

## 備考

- `@vue/runtime-dom`の`render`は`ensureRenderer().render(...args)`を呼び出すラッパー関数
- 内部レンダラーの`render`関数は`baseCreateRenderer`内で定義される（renderer.ts 2393-2418行目）
- `createApp().mount()`は最終的にこの`render()`を呼び出してDOMにマウントする

---

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

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

### 推奨読解順序

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

RootRenderFunction型とRendererインターフェースを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | renderer.ts | `packages/runtime-core/src/renderer.ts` | `RootRenderFunction`型（102-106行目）。`(vnode: VNode \| null, container, namespace?) => void` |
| 1-2 | renderer.ts | `packages/runtime-core/src/renderer.ts` | `Renderer`インターフェース（91-94行目）。render関数とcreateApp関数を持つ |

**読解のコツ**: `RootRenderFunction`はレンダラーの最上位レンダリング関数の型を定義している。container._vnodeは非公式プロパティとして使用される。

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

`@vue/runtime-dom`のrender関数がレンダラーを遅延生成する仕組みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/runtime-dom/src/index.ts` | render関数のエクスポート（90-92行目）。ensureRenderer().render(...args) |
| 2-2 | index.ts | `packages/runtime-dom/src/index.ts` | ensureRenderer関数（74-79行目）。createRenderer(rendererOptions)で遅延生成 |

**主要処理フロー**:
1. **66行目**: `rendererOptions`をpatchPropとnodeOpsから構成
2. **74-79行目**: `ensureRenderer()`でレンダラーが未生成の場合に`createRenderer(rendererOptions)`を呼ぶ
3. **90-92行目**: `render`はensureRenderer().render(...args)を呼び出すラッパー

#### Step 3: 内部render関数の実装を理解する

baseCreateRenderer内で定義される実際のrender処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | renderer.ts | `packages/runtime-core/src/renderer.ts` | 内部render関数（2393-2418行目） |

**主要処理フロー**:
- **2393行目**: `const render: RootRenderFunction = (vnode, container, namespace) => {`
- **2395-2399行目**: vnode === nullの場合、container._vnodeが存在すればunmount処理
- **2401-2409行目**: vnode !== nullの場合、patch(container._vnode || null, vnode, container, ...)
- **2411行目**: `container._vnode = vnode`で参照更新
- **2412-2417行目**: isFlushing制御下でflushPreFlushCbs/flushPostFlushCbs実行

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

```
render(vnode, container, namespace)  [runtime-dom/src/index.ts:90]
    │
    └─ ensureRenderer().render(...)
           │
           └─ baseCreateRenderer内のrender関数  [renderer.ts:2393]
                  │
                  ├─ vnode === null
                  │      └─ unmount(container._vnode, ...)
                  │
                  ├─ vnode !== null
                  │      └─ patch(container._vnode, vnode, container, ...)
                  │             ├─ processElement / processComponent / ...
                  │             └─ mountComponent / updateComponent
                  │
                  ├─ container._vnode = vnode
                  │
                  └─ flushPreFlushCbs() → flushPostFlushCbs()
```

### データフロー図

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

VNode (or null)  ───▶ render()                     ───▶ DOM操作
container        ───▶   │                                │
                         ├─ patch(oldVNode, newVNode)     ├─ createElement
                         │     └─ 差分検出・更新           ├─ patchProp
                         │                                ├─ insert
                         └─ unmount(oldVNode)              └─ remove
                               └─ DOM要素削除
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/runtime-dom/src/index.ts` | ソース | render関数エクスポート、ensureRenderer |
| renderer.ts | `packages/runtime-core/src/renderer.ts` | ソース | baseCreateRenderer、内部render関数、patch/unmount |
| nodeOps.ts | `packages/runtime-dom/src/nodeOps.ts` | ソース | DOM操作の抽象化層（createElement, insert, remove等） |
| patchProp.ts | `packages/runtime-dom/src/patchProp.ts` | ソース | DOMプロパティのパッチ処理 |
| scheduler.ts | `packages/runtime-core/src/scheduler.ts` | ソース | flushPreFlushCbs/flushPostFlushCbs |
| vnode.ts | `packages/runtime-core/src/vnode.ts` | ソース | VNode型定義、createVNode |
