# 機能設計書 46-v-forディレクティブ変換

## 概要

本ドキュメントは、Vue 3テンプレートコンパイラにおけるv-forディレクティブのAST変換処理について記述する。v-forディレクティブをリストレンダリングのcodegenNodeに変換する。

### 本機能の処理概要

`transformFor` は構造ディレクティブ変換（StructuralDirectiveTransform）として実装されており、v-forディレクティブを検出してForNode ASTノードを生成し、`renderList()` ヘルパーを使用するcodegenNodeを組み立てる。`(item, key, index) in source` 形式の式をパースし、ループ変数のスコープ管理とフラグメントVNodeの生成を行う。

**業務上の目的・背景**：リスト表示はWebアプリケーションの基本的なUIパターンであり、v-forディレクティブはVueテンプレート内でデータ駆動のリスト表示を実現する中核機能である。コンパイラ段階で効率的なレンダリングコードに変換することで、ランタイムの処理コストを最小化する。

**機能の利用シーン**：テンプレートコンパイルパイプラインのtransformフェーズで、v-forディレクティブを持つ要素ノードに対して自動的に実行される。

**主要な処理内容**：
1. v-for式のパース結果（source, value, key, index）の取得と検証
2. ForNodeの生成とノード置換
3. スコープ管理（vForスコープカウンタ、識別子の追加/削除）
4. renderList()呼び出し式の生成
5. フラグメントフラグ（STABLE/KEYED/UNKEYED）の決定
6. 子ブロックの生成（slot outlet, fragment wrapper, 単一要素）
7. v-memoとの連携処理

**関連システム・外部連携**：@vue/runtime-coreのrenderList()、FRAGMENTヘルパー

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | Index（メイン画面） | 補助機能 | v-forテンプレートのコンパイル変換結果をリアルタイム確認 |

## 機能種別

テンプレートコンパイル（ディレクティブ変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| node | ElementNode | Yes | v-forディレクティブを持つ要素ノード | なし |
| dir | DirectiveNode | Yes | v-forディレクティブノード | exp必須チェック、forParseResult必須チェック |
| context | TransformContext | Yes | 変換コンテキスト | なし |

### v-for式のForParseResult

| フィールド | 型 | 説明 |
|-----------|-----|------|
| source | ExpressionNode | ループ対象のソース式 |
| value | ExpressionNode \| undefined | 値変数（item） |
| key | ExpressionNode \| undefined | キー変数 |
| index | ExpressionNode \| undefined | インデックス変数 |

### 入力データソース

パーサーが生成したAST内のv-forディレクティブ付き要素ノード。式のパース結果（forParseResult）はパーサー段階で事前解析されている。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ForNode | ForNode | v-for用のASTノード（元のElementNodeを置換） |
| codegenNode | ForCodegenNode | FRAGMENT + renderList() のVNodeCall |

### 出力先

ASTツリー内で元のElementNodeがForNodeに置換される。

## 処理フロー

### 処理シーケンス

```
1. 式の検証
   └─ dir.exp が存在しない場合: X_V_FOR_NO_EXPRESSION エラー
   └─ dir.forParseResult が存在しない場合: X_V_FOR_MALFORMED_EXPRESSION エラー
2. ForParseResult のファイナライズ
   └─ finalizeForParseResult: 式の変換とバリデーション
3. ForNode の生成
   └─ source, valueAlias, keyAlias, objectIndexAlias を設定
   └─ context.replaceNode(forNode) で元ノードを置換
4. スコープ管理
   └─ scopes.vFor++ でvForスコープを増加
   └─ prefixIdentifiers時: value, key, indexを識別子に追加
5. renderList() 呼び出し式の生成
   └─ createCallExpression(helper(RENDER_LIST), [forNode.source])
6. フラグメントフラグの決定
   └─ STABLE_FRAGMENT: ソースが定数の場合
   └─ KEYED_FRAGMENT: keyプロップがある場合
   └─ UNKEYED_FRAGMENT: それ以外
7. ForCodegenNode の生成
   └─ createVNodeCall(FRAGMENT, undefined, renderExp, fragmentFlag, ...)
8. 子ブロック生成（exit時コールバック）
   └─ slot outlet / fragment wrapper / 単一要素 に応じて分岐
9. スコープ復元
   └─ scopes.vFor-- で元に戻す
```

### フローチャート

```mermaid
flowchart TD
    A[v-for要素検出] --> B{dir.exp存在?}
    B -->|No| C[エラー: X_V_FOR_NO_EXPRESSION]
    B -->|Yes| D{forParseResult存在?}
    D -->|No| E[エラー: X_V_FOR_MALFORMED_EXPRESSION]
    D -->|Yes| F[finalizeForParseResult]
    F --> G[ForNode生成 + replaceNode]
    G --> H[スコープ管理: vFor++]
    H --> I[renderList呼び出し式生成]
    I --> J{ソースが定数?}
    J -->|Yes| K[STABLE_FRAGMENT]
    J -->|No| L{keyあり?}
    L -->|Yes| M[KEYED_FRAGMENT]
    L -->|No| N[UNKEYED_FRAGMENT]
    K --> O[ForCodegenNode生成]
    M --> O
    N --> O
    O --> P[子ブロック生成: exit callback]
    P --> Q[スコープ復元: vFor--]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | フラグメントフラグ | ソース定数→STABLE、keyあり→KEYED、それ以外→UNKEYED | 常時 |
| BR-46-02 | template v-for | `<template v-for>`の場合、子要素がForNodeのchildrenになる | isTemplateNode(node)時 |
| BR-46-03 | key配置チェック | `<template v-for>`内の子要素にkeyがある場合は警告 | DEVモードかつisTemplate時 |
| BR-46-04 | slot outlet | slotOutletの場合はrenderSlotCallをそのまま使用 | isSlotOutlet(node)時 |
| BR-46-05 | v-memo連携 | v-memoがある場合はIS_MEMO_SAMEによるキャッシュロジックを生成 | memo存在時 |

### 計算ロジック

フラグメントフラグの決定: `isStableFragment` = source.constType > ConstantTypes.NOT_CONSTANT

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

データベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| X_V_FOR_NO_EXPRESSION | コンパイルエラー | v-for式が空の場合 | v-for式を指定 |
| X_V_FOR_MALFORMED_EXPRESSION | コンパイルエラー | v-for式が不正な場合 | `item in items`形式で記述 |
| X_V_FOR_TEMPLATE_KEY_PLACEMENT | コンパイルエラー | template v-for内の子要素にkeyがある場合 | keyをtemplateに移動 |

### リトライ仕様

リトライ仕様は存在しない。

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

トランザクション処理は存在しない。

## パフォーマンス要件

- STABLE_FRAGMENTフラグにより、定数ソースのv-forではブロックトラッキングが有効化
- v-memoと連携することで、不要な再レンダリングを防止

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

特別なセキュリティ考慮事項はない。

## 備考

- `createStructuralDirectiveTransform('for', ...)` で構造ディレクティブとして登録
- `processFor()` はClient/SSR共通のターゲット非依存変換
- `finalizeForParseResult()` は式の変換（prefixIdentifiers）とバリデーション（ブラウザ時）を行う
- `createForLoopParams()` は `[value, key, index]` のパラメータリストを生成

---

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

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

### 推奨読解順序

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

ForNodeとForParseResultの型定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ast.ts | `packages/compiler-core/src/ast.ts` | ForNode型定義: source, valueAlias, keyAlias, objectIndexAlias |
| 1-2 | ast.ts | `packages/compiler-core/src/ast.ts` | ForParseResult型: source, value, key, index, finalized |

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

transformForの登録と実行を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | vFor.ts | `packages/compiler-core/src/transforms/vFor.ts` | transformFor定義（52-253行目）: createStructuralDirectiveTransformによる登録 |
| 2-2 | compile.ts | `packages/compiler-core/src/compile.ts` | getBaseTransformPreset（32-63行目）: transformForの登録順序 |

**主要処理フロー**:
1. **52-53行目**: createStructuralDirectiveTransform('for', ...)で構造変換として登録
2. **56行目**: processFor()を呼び出し
3. **59-61行目**: renderList()呼び出し式の作成
4. **104-125行目**: フラグメントフラグの決定とForCodegenNodeの生成
5. **127-252行目**: exit時コールバックで子ブロック生成

#### Step 3: processFor処理を理解する

ForNodeの生成とスコープ管理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | vFor.ts | `packages/compiler-core/src/transforms/vFor.ts` | processFor関数（256-317行目）: ForNode生成とスコープ管理 |
| 3-2 | vFor.ts | `packages/compiler-core/src/transforms/vFor.ts` | finalizeForParseResult関数（319-377行目）: 式の変換とバリデーション |

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

```
transformFor (構造ディレクティブ変換)
    │
    └─ processFor(node, dir, context, processCodegen)
           │
           ├─ finalizeForParseResult(parseResult, context)
           │      ├─ processExpression(source)
           │      ├─ processExpression(key)
           │      ├─ processExpression(index)
           │      └─ processExpression(value)
           │
           ├─ ForNode生成 + replaceNode
           │
           ├─ スコープ管理 (addIdentifiers/removeIdentifiers)
           │
           └─ processCodegen(forNode)  → exit callback
                  │
                  ├─ renderList() 呼び出し式
                  │
                  ├─ フラグメントフラグ決定
                  │
                  └─ 子ブロック生成
                         ├─ [slotOutlet] renderSlotCall
                         ├─ [fragment] createVNodeCall(FRAGMENT)
                         └─ [単一要素] childBlock.isBlock設定
```

### データフロー図

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

v-for="(item, key) in items"                                  ForNode
        │                                                       │
        ├─ source: "items"   ──▶ processExpression        ──▶ sourceExpr
        ├─ value: "item"     ──▶ processExpression        ──▶ valueExpr
        └─ key: "key"        ──▶ processExpression        ──▶ keyExpr
                                                                │
                                                                ▼
                                                           codegenNode
                                                     (FRAGMENT + renderList)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| vFor.ts | `packages/compiler-core/src/transforms/vFor.ts` | ソース | transformFor, processFor, finalizeForParseResultの実装 |
| transform.ts | `packages/compiler-core/src/transform.ts` | ソース | createStructuralDirectiveTransformの定義 |
| compile.ts | `packages/compiler-core/src/compile.ts` | ソース | transformForの登録 |
| ast.ts | `packages/compiler-core/src/ast.ts` | ソース | ForNode, ForParseResult型定義 |
| runtimeHelpers.ts | `packages/compiler-core/src/runtimeHelpers.ts` | ソース | RENDER_LIST, FRAGMENTシンボル |
| parser.ts | `packages/compiler-core/src/parser.ts` | ソース | parseForExpression（パーサー段階でのv-for式解析） |
