# 機能設計書 69-patchFlags / shapeFlags / slotFlags

## 概要

本ドキュメントは、Vue 3の`@vue/shared`パッケージが提供する`PatchFlags`、`ShapeFlags`、`SlotFlags`の3種類のビットフラグ列挙型の設計仕様を記述する。これらのフラグはVNode最適化の基盤として、レンダリングパフォーマンスの向上に寄与する。

### 本機能の処理概要

`PatchFlags`、`ShapeFlags`、`SlotFlags`は、TypeScriptのenum型として定義されたビットフラグセットである。テンプレートコンパイラがVNode生成コードにこれらのフラグを埋め込み、ランタイムレンダラーがdiff/patch処理時にフラグを参照して不要な比較処理をスキップすることで、レンダリングパフォーマンスを最適化する。

**業務上の目的・背景**：仮想DOM（VNode）のdiffアルゴリズムは、ツリー全体を比較する場合にO(n)のコストがかかる。Vue 3ではテンプレートコンパイラの静的解析により、各VNodeの動的な部分を事前に特定し、ビットフラグとしてエンコードする。ランタイムはこのフラグを参照することで、変更の可能性がない部分の比較をスキップし、パフォーマンスを大幅に向上させる。この「コンパイラ支援の最適化」はVue 3のコア設計思想の一つである。

**機能の利用シーン**：
- テンプレートコンパイラがVNode生成コードを出力する際のフラグ指定
- ランタイムレンダラーのpatchElement()でのdiff処理の最適化
- VNode生成時のshapeFlag設定によるノード種別の高速判定
- スロットの更新戦略決定

**主要な処理内容**：
1. `PatchFlags`: VNodeの動的プロパティの種類を示すフラグ（TEXT、CLASS、STYLE、PROPS等）
2. `ShapeFlags`: VNodeの形状（要素、コンポーネント、子の種類等）を示すフラグ
3. `SlotFlags`: スロットの更新戦略を示すフラグ（STABLE、DYNAMIC、FORWARDED）

**関連システム・外部連携**：`@vue/compiler-core`（フラグの設定）、`@vue/runtime-core`（フラグの参照）、`@vue/compiler-ssr`（SSRコンパイル時のフラグ使用）。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | フレームワーク内部の最適化定数。直接的な画面関連なし |

## 機能種別

定数定義（ビットフラグ列挙型）

## 入力仕様

### 入力パラメータ

入力パラメータはなし。定数定義として使用される。

### 入力データソース

テンプレートコンパイラの静的解析結果に基づいてフラグが設定される。

## 出力仕様

### 出力データ

#### PatchFlags

| フラグ名 | 値 | 説明 |
|---------|-----|------|
| TEXT | 1 | 動的なtextContentを持つ要素 |
| CLASS | 2 (1<<1) | 動的なclassバインディング |
| STYLE | 4 (1<<2) | 動的なstyleバインディング |
| PROPS | 8 (1<<3) | class/style以外の動的props（dynamicProps配列と併用） |
| FULL_PROPS | 16 (1<<4) | 動的キーのprops。常にフルdiffが必要 |
| NEED_HYDRATION | 32 (1<<5) | ハイドレーション時にprops処理が必要 |
| STABLE_FRAGMENT | 64 (1<<6) | 子の順序が変わらないフラグメント |
| KEYED_FRAGMENT | 128 (1<<7) | キー付き子要素のフラグメント |
| UNKEYED_FRAGMENT | 256 (1<<8) | キーなし子要素のフラグメント |
| NEED_PATCH | 512 (1<<9) | ref/ディレクティブのみパッチが必要 |
| DYNAMIC_SLOTS | 1024 (1<<10) | 動的スロット |
| DEV_ROOT_FRAGMENT | 2048 (1<<11) | 開発モード用ルートフラグメント（コメント付き） |
| CACHED | -1 | キャッシュ済み静的VNode |
| BAIL | -2 | 最適化モードからのベイルアウト |

#### ShapeFlags

| フラグ名 | 値 | 説明 |
|---------|-----|------|
| ELEMENT | 1 | HTML要素 |
| FUNCTIONAL_COMPONENT | 2 (1<<1) | 関数型コンポーネント |
| STATEFUL_COMPONENT | 4 (1<<2) | ステートフルコンポーネント |
| TEXT_CHILDREN | 8 (1<<3) | テキスト子要素 |
| ARRAY_CHILDREN | 16 (1<<4) | 配列子要素 |
| SLOTS_CHILDREN | 32 (1<<5) | スロット子要素 |
| TELEPORT | 64 (1<<6) | Teleportコンポーネント |
| SUSPENSE | 128 (1<<7) | Suspenseコンポーネント |
| COMPONENT_SHOULD_KEEP_ALIVE | 256 (1<<8) | KeepAlive対象 |
| COMPONENT_KEPT_ALIVE | 512 (1<<9) | KeepAliveキャッシュ済み |
| COMPONENT | 6 | STATEFUL \| FUNCTIONAL |

#### SlotFlags

| フラグ名 | 値 | 説明 |
|---------|-----|------|
| STABLE | 1 | 安定スロット（スロットpropsまたはコンテキスト状態のみ参照） |
| DYNAMIC | 2 | 動的スロット（v-forやv-if等のスコープ変数を参照） |
| FORWARDED | 3 | 転送スロット（親から子へスロットを転送） |

### 出力先

VNodeの`patchFlag`プロパティ、`shapeFlag`プロパティ、スロットの`_`プロパティに設定される。

## 処理フロー

### 処理シーケンス

```
1. テンプレートコンパイル時
   └─ コンパイラが静的解析で動的要素を特定し、PatchFlagsを設定
      例: <div :class="cls">{{ msg }}</div> → PatchFlags.CLASS | PatchFlags.TEXT
2. VNode生成時
   └─ createVNode()でShapeFlagsを設定
      例: h('div', ...) → ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN
3. ランタイムパッチ時
   └─ patchElement()でpatchFlagをビット演算(&)でチェック
      例: if (patchFlag & PatchFlags.TEXT) { /* textContentのみ更新 */ }
4. スロット更新時
   └─ SlotFlagsに基づいて親から子への更新伝播を決定
```

### フローチャート

```mermaid
flowchart TD
    A[テンプレート] --> B[コンパイラ: 静的解析]
    B --> C[PatchFlags設定]
    B --> D[ShapeFlags設定]
    B --> E[SlotFlags設定]
    C --> F[VNode生成コード出力]
    D --> F
    E --> F
    F --> G[ランタイム: VNode生成]
    G --> H[ランタイム: patch/diff]
    H --> I{patchFlag & FLAG?}
    I -->|Yes| J[該当プロパティのみ更新]
    I -->|No| K[スキップ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-01 | ビット論理和で合成 | 複数のPatchFlagsは`\|`演算子で合成できる | 複数の動的プロパティがある場合 |
| BR-69-02 | ビット論理積でチェック | PatchFlagsのチェックは`&`演算子で行う（patchFlag > 0の場合のみ） | patchElement内 |
| BR-69-03 | 特殊フラグは負値 | CACHED(-1)とBAIL(-2)は負値であり、ビット演算ではなく等価比較で判定する | 特殊フラグ判定時 |
| BR-69-04 | FULL_PROPSの排他性 | FULL_PROPSはCLASS、STYLE、PROPSと相互排他。設定されている場合は常にフルdiff | 動的キーprops |
| BR-69-05 | COMPONENTの合成値 | ShapeFlags.COMPONENTはSTATEFUL_COMPONENT \| FUNCTIONAL_COMPONENTの合成値 | コンポーネント判定時 |
| BR-69-06 | FORWARDED実行時解決 | SlotFlags.FORWARDEDはランタイム時にnormalizeChildrenで正確なフラグに解決される | スロット転送時 |

### 計算ロジック

ビットシフト演算による値の定義:
- `1 << n` で2のn乗を計算
- 各フラグは異なるビット位置を占めるため、`|`で合成しても情報が失われない

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

該当なし。

## エラー処理

該当なし。定数定義であり、エラーは発生しない。

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ビット演算はCPU命令レベルで最も高速な演算の一つ
- PatchFlagsにより、diff処理で不要なプロパティ比較をスキップし、O(n)のコストを削減
- ShapeFlagsにより、VNodeの種別判定をinstanceof等より高速に行える

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

該当なし。

## 備考

- `PatchFlagNames`はdev-onlyのデバッグ用マッピング。開発ツールでPatchFlagの名前を表示するために使用
- `slotFlagsText`もdev-onlyのデバッグ用マッピング
- DEV_ROOT_FRAGMENT (1<<11) は開発モードのみで使用され、プロダクションビルドでは除去される
- PatchFlagsの特殊フラグ（CACHED=-1, BAIL=-2）はビット演算の対象外。`patchFlag > 0`の場合のみビット演算が使用される

---

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

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

### 推奨読解順序

#### Step 1: PatchFlagsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | patchFlags.ts | `packages/shared/src/patchFlags.ts` | PatchFlags enum定義（19-124行目）。各フラグの値とJSDocコメントによる用途説明 |
| 1-2 | patchFlags.ts | `packages/shared/src/patchFlags.ts` | PatchFlagNames（129-144行目）: dev-onlyのフラグ名マッピング |

**読解のコツ**: PatchFlagsは「テンプレートコンパイラがヒントとして生成する」ものであり、手動で設定するものではない。コンパイラがテンプレートを解析して動的な部分を特定し、対応するフラグを設定する。

**主要処理フロー**:
- **23行目**: TEXT = 1 - 動的textContent
- **28行目**: CLASS = 1 << 1 - 動的class
- **41行目**: STYLE = 1 << 2 - 動的style
- **50行目**: PROPS = 1 << 3 - 動的props（class/style以外）
- **57行目**: FULL_PROPS = 1 << 4 - 動的キーprops（フルdiff必要）
- **64行目**: NEED_HYDRATION = 1 << 5 - ハイドレーション必要
- **69行目**: STABLE_FRAGMENT = 1 << 6 - 安定フラグメント
- **94行目**: DYNAMIC_SLOTS = 1 << 10 - 動的スロット
- **115行目**: CACHED = -1 - キャッシュ済み（特殊フラグ）
- **123行目**: BAIL = -2 - 最適化ベイルアウト（特殊フラグ）

#### Step 2: ShapeFlagsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | shapeFlags.ts | `packages/shared/src/shapeFlags.ts` | ShapeFlags enum定義（1-13行目） |

**主要処理フロー**:
- **2行目**: ELEMENT = 1
- **3行目**: FUNCTIONAL_COMPONENT = 1 << 1
- **4行目**: STATEFUL_COMPONENT = 1 << 2
- **5行目**: TEXT_CHILDREN = 1 << 3
- **6行目**: ARRAY_CHILDREN = 1 << 4
- **7行目**: SLOTS_CHILDREN = 1 << 5
- **8行目**: TELEPORT = 1 << 6
- **9行目**: SUSPENSE = 1 << 7
- **12行目**: COMPONENT = STATEFUL_COMPONENT | FUNCTIONAL_COMPONENT（合成値）

**読解のコツ**: ShapeFlagsは実行時にVNodeに設定される。renderVNode()でshapeFlagをビットチェックしてノードの種類を判定し、適切なレンダリングパスを選択する。

#### Step 3: SlotFlagsを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | slotFlags.ts | `packages/shared/src/slotFlags.ts` | SlotFlags enum定義（1-21行目） |
| 3-2 | slotFlags.ts | `packages/shared/src/slotFlags.ts` | slotFlagsText（26-30行目）: dev-onlyの名前マッピング |

**主要処理フロー**:
- **7行目**: STABLE = 1 - 親からの更新強制不要
- **13行目**: DYNAMIC = 2 - 親からの更新強制が必要
- **20行目**: FORWARDED = 3 - ランタイム解決が必要

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

```
[コンパイル時]
テンプレートコンパイラ
    │
    ├─ PatchFlags.TEXT | PatchFlags.CLASS  [VNode生成コードに埋め込み]
    ├─ ShapeFlags.ELEMENT                  [createVNode呼び出しに埋め込み]
    └─ SlotFlags.STABLE                    [スロット定義に埋め込み]

[ランタイム]
patchElement(n1, n2, ...)
    │
    └─ if (patchFlag & PatchFlags.TEXT)    [ビット演算で高速チェック]
           └─ hostSetElementText()         [textContentのみ更新]

renderVNode(push, vnode, ...)
    │
    └─ if (shapeFlag & ShapeFlags.ELEMENT) [ノード種別判定]
           └─ renderElementVNode()
```

### データフロー図

```
[コンパイル時]                [ランタイム]

テンプレート                  VNode
    │                           │
    └─ 静的解析 ──▶ PatchFlags ──▶ patchElement()
                                     │
                   ShapeFlags ──────▶ renderVNode()
                                     │
                   SlotFlags ───────▶ normalizeChildren()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| patchFlags.ts | `packages/shared/src/patchFlags.ts` | ソース | PatchFlags enum、PatchFlagNamesの定義 |
| shapeFlags.ts | `packages/shared/src/shapeFlags.ts` | ソース | ShapeFlags enumの定義 |
| slotFlags.ts | `packages/shared/src/slotFlags.ts` | ソース | SlotFlags enum、slotFlagsTextの定義 |
| index.ts | `packages/shared/src/index.ts` | ソース | パッケージエクスポート |
