# 機能設計書 52-式変換（transformExpression）

## 概要

本ドキュメントは、Vue 3テンプレートコンパイラにおける式変換（transformExpression）の処理について記述する。テンプレート内の式のスコープ解析を行い、識別子に適切なプレフィックス（`_ctx.`、`$setup.`等）を付与してアクセス元を明確化する。

### 本機能の処理概要

transformExpressionは、テンプレート内の補間式（`{{ expression }}`）やディレクティブ式を解析し、各識別子が正しいソースからアクセスされるようにプレフィックスの書き換えを行う変換プラグインである。また、各識別子に正確なソースマップ位置情報を付与するために、単一の式を複合式（CompoundExpression）に分解する処理も行う。

**業務上の目的・背景**：Vueテンプレート内の式は、コンポーネントのsetup()関数、props、data()、computed等の様々なソースからバインディングを参照する。ブラウザビルドでは`with(this)`でスコープを解決するが、Node.jsビルドではパフォーマンスと正確なソースマップのために、各識別子に明示的なプレフィックスを付与する必要がある。

**機能の利用シーン**：テンプレートコンパイル時に、`{{ count }}`、`v-if="isActive"`、`:class="dynamicClass"` などの式が検出された際に自動的に実行される。非ブラウザビルド（Node.js環境）でprefixIdentifiersオプションが有効な場合にのみ完全な変換が適用される。

**主要な処理内容**：
1. 補間式（INTERPOLATION）ノードの式変換
2. ディレクティブ式・引数の変換（v-on、v-forを除く）
3. バインディング種別に応じた識別子プレフィックスの書き換え
4. Babelパーサーによる式の構文解析とAST走査
5. 複合式（CompoundExpression）への分解とソースマップ位置情報の付与
6. 定数判定（ConstantTypes）の設定

**関連システム・外部連携**：@babel/parserを使用した式の構文解析。@vue/compiler-coreパッケージのNodeTransformとして動作する。バインディングメタデータ（bindingMetadata）と連携して、各識別子の出自を特定する。

**権限による制御**：該当なし（コンパイル時処理）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | Index（メイン画面） | 補助機能 | テンプレート式のスコープ解析・識別子書き換え結果をリアルタイム確認 |

## 機能種別

テンプレート変換処理（コンパイラ変換プラグイン）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| node | SimpleExpressionNode | Yes | 処理対象の式ノード | contentが空でないこと |
| context | TransformContext | Yes | 変換コンテキスト（バインディングメタデータ、識別子情報等） | - |
| asParams | boolean | No | 関数パラメータとして解析するか（v-slot propsやv-forエイリアス用） | デフォルト: false |
| asRawStatements | boolean | No | 生のステートメントとして解析するか（v-onハンドラ用） | デフォルト: false |
| localVars | Record<string, number> | No | ローカル変数のスコープ情報 | デフォルト: context.identifiers |

### 入力データソース

テンプレート解析（Parser）により生成されたAST内のSimpleExpressionNode。補間式やディレクティブの式・引数が対象。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | ExpressionNode | 変換後の式ノード（SimpleExpressionNodeまたはCompoundExpressionNode） |

### 出力先

変換後の式はASTノードのcontent/exp/argプロパティに直接設定され、後続のコード生成（Codegen）で使用される。

## 処理フロー

### 処理シーケンス

```
1. ノード種別の判定
   └─ INTERPOLATION: 補間式の変換を実行
   └─ ELEMENT: ディレクティブ式・引数の変換を実行

2. 事前チェック
   └─ ブラウザビルドの場合: ブラウザ用バリデーションのみ実行して返却
   └─ prefixIdentifiersが無効: そのまま返却
   └─ 式が空: そのまま返却

3. 識別子の書き換えルール決定（rewriteIdentifier）
   └─ インラインモード判定
   └─ バインディング種別に応じたプレフィックス決定
      - SETUP_CONST / LITERAL_CONST: そのまま
      - SETUP_REF: `raw.value`
      - SETUP_MAYBE_REF: unref(raw) または raw.value
      - SETUP_LET: isRef判定付き書き換え
      - SETUP_REACTIVE_CONST: そのまま
      - PROPS: `__props.raw`
      - PROPS_ALIASED: `__props['alias']`
      - 非インライン: `$setup.raw` / `$props.raw` / `$data.raw`
      - フォールバック: `_ctx.raw`

4. 単純識別子の高速パス
   └─ 式がリテラルまたはグローバル許可リストに含まれる場合
   └─ 定数タイプの設定（CAN_STRINGIFY/CAN_CACHE/CAN_SKIP_PATCH）

5. 複雑な式の処理
   └─ Babelパーサーで式を解析
   └─ walkIdentifiersで全識別子を走査
   └─ 各識別子にプレフィックスを付与
   └─ 複合式（CompoundExpression）に分解

6. 結果の構築
   └─ ids配列をソートし、テキストとSimpleExpressionNodeを交互に配置
   └─ CompoundExpressionNodeとして返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始: processExpression] --> B{ブラウザビルド?}
    B -->|Yes| C[バリデーションのみ実行]
    B -->|No| D{prefixIdentifiers有効?}
    D -->|No| E[そのまま返却]
    D -->|Yes| F{単純識別子?}
    F -->|Yes| G[rewriteIdentifier適用]
    G --> H[定数タイプ設定]
    H --> I[返却]
    F -->|No| J[Babelで式を解析]
    J --> K[walkIdentifiersで走査]
    K --> L[各識別子にプレフィックス付与]
    L --> M[CompoundExpression構築]
    M --> N[返却]
    C --> O[終了]
    E --> O
    I --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | グローバル許可 | Math、Date、console等のグローバル変数はプレフィックスを付与しない | isGloballyAllowed(rawExp)がtrueの場合 |
| BR-52-02 | リテラル許可 | true、false、null、thisはプレフィックスを付与しない | isLiteralWhitelisted(rawExp)がtrueの場合 |
| BR-52-03 | v-on/v-for除外 | v-onとv-forの式は本変換の対象外（専用の変換がある） | dir.name === 'on' && arg、dir.name === 'for' |
| BR-52-04 | スコープ変数優先 | ローカルスコープ変数（v-forエイリアス等）はプレフィックスを付与しない | context.identifiers[rawExp]が存在する場合 |
| BR-52-05 | Ref自動アンラップ | SETUP_REFバインディングは自動的に.valueアクセスに変換 | type === BindingTypes.SETUP_REF |
| BR-52-06 | requireスキップ | webpack互換のため、requireはプレフィックスを付与しない | id.name === 'require' |

### 計算ロジック

定数タイプの判定:
- バインディングがSETUP_CONSTまたはLITERAL_CONST: `CAN_SKIP_PATCH`
- リテラル値（true/false/null/this）: `CAN_STRINGIFY`
- グローバル許可変数: `CAN_CACHE`
- スコープ変数参照: `NOT_CONSTANT`

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

該当なし（コンパイル時処理のため、データベース操作は発生しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| X_INVALID_EXPRESSION | コンパイルエラー | Babelパーサーで式の解析に失敗 | テンプレート式の構文を修正する |

### リトライ仕様

該当なし（コンパイルエラーは即座に報告される）

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

該当なし（コンパイル時処理）

## パフォーマンス要件

- 単純識別子の場合はBabelパーサーを使用せず高速パスで処理
- ast === falseの場合（解析フェーズでエラー済み）は早期リターン
- 定数タイプの設定により、ランタイムでのパッチ処理を最適化

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

該当なし（コンパイル時処理であり、ユーザー入力の直接処理は行わない）

## 備考

- 本変換はNode.jsビルド専用であり、ブラウザビルドではソースマップサポートがないため、`with(this)`によるスコープ解決が使用される
- SETUP_LETバインディングの代入式は、isRef判定を挟む複雑な書き換えが行われる
- TypeScriptモードではisRefチェック時に`//@ts-ignore`コメントが挿入される

---

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

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

### 推奨読解順序

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

まず、式ノードの型と定数タイプの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ast.ts | `packages/compiler-core/src/ast.ts` | SimpleExpressionNode、CompoundExpressionNode、ConstantTypesの型定義 |
| 1-2 | options.ts | `packages/compiler-core/src/options.ts` | BindingTypes列挙型（SETUP_CONST, SETUP_REF, PROPS等） |

**読解のコツ**: ConstantTypesは4段階（NOT_CONSTANT=0, CAN_SKIP_PATCH=1, CAN_CACHE=2, CAN_STRINGIFY=3）の定数レベルを定義しており、値が大きいほど「より静的」であることを示す。

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

NodeTransformとしてのtransformExpressionを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | transformExpression.ts | `packages/compiler-core/src/transforms/transformExpression.ts` | 変換エントリーポイント |

**主要処理フロー**:
1. **49-54行目**: INTERPOLATION（補間式）の場合、processExpressionを呼び出してnode.contentを書き換え
2. **55-91行目**: ELEMENT（要素）の場合、各ディレクティブの式と引数を処理（v-on+arg、v-forは除外）

#### Step 3: processExpression関数の詳細

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transformExpression.ts | `packages/compiler-core/src/transforms/transformExpression.ts` | processExpression関数 |

**主要処理フロー**:
- **104-120行目**: ブラウザビルドの場合のバリデーションのみ処理と早期リターン
- **122-124行目**: prefixIdentifiersが無効または式が空の場合の早期リターン
- **127-233行目**: rewriteIdentifier内部関数 - バインディング種別に応じたプレフィックス決定
- **236-269行目**: 単純識別子の高速パス処理
- **271-296行目**: 複雑な式のBabelパーサーによる解析
- **303-343行目**: walkIdentifiersによる全識別子の走査とプレフィックス付与
- **349-389行目**: CompoundExpressionへの分解と結果構築

#### Step 4: 識別子書き換えロジックの詳細

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | transformExpression.ts | `packages/compiler-core/src/transforms/transformExpression.ts` | rewriteIdentifier関数 |

**主要処理フロー**:
- **149-154行目**: SETUP_CONST / SETUP_REACTIVE_CONST / ローカル変数はそのまま
- **155-156行目**: SETUP_REF → `raw.value` に変換
- **157-164行目**: SETUP_MAYBE_REF → 代入時は `.value`、参照時は `unref(raw)`
- **165-208行目**: SETUP_LET → isRef判定付きの複雑な書き換え
- **209-212行目**: PROPS → `__props.raw` に変換
- **217-228行目**: 非インラインモードでのプレフィックス付与（`$setup.`、`$props.`等）
- **232行目**: フォールバック → `_ctx.raw` に変換

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

```
transformExpression (NodeTransform)
    │
    └─ processExpression
           │
           ├─ validateBrowserExpression (ブラウザビルド時)
           │
           ├─ rewriteIdentifier (内部関数)
           │      ├─ genPropsAccessExp (PROPS)
           │      └─ context.helperString(UNREF/IS_REF)
           │
           ├─ parseExpression (@babel/parser)
           │
           ├─ walkIdentifiers (babelUtils)
           │      └─ isStaticPropertyKey
           │      └─ isStaticProperty
           │      └─ isInDestructureAssignment
           │      └─ isInNewExpression
           │
           └─ createCompoundExpression
                  └─ createSimpleExpression (各識別子)
                  └─ advancePositionWithClone (位置情報)
```

### データフロー図

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

SimpleExpression   ───▶ processExpression        ───▶ ExpressionNode
("count")                │                            (CompoundExpression
                         ├─ rewriteIdentifier          or SimpleExpression)
                         │   "count" → "_ctx.count"
                         │   or "$setup.count"
                         │   or "count.value"
                         │
                         ├─ Babel AST解析
                         │
                         └─ CompoundExpression構築
                             [{_ctx.}, {count}]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transformExpression.ts | `packages/compiler-core/src/transforms/transformExpression.ts` | ソース | 式変換のメイン実装 |
| ast.ts | `packages/compiler-core/src/ast.ts` | ソース | SimpleExpressionNode、CompoundExpressionNode等の型定義 |
| babelUtils.ts | `packages/compiler-core/src/babelUtils.ts` | ソース | walkIdentifiers、isStaticProperty等のBabel AST操作ユーティリティ |
| options.ts | `packages/compiler-core/src/options.ts` | ソース | BindingTypes列挙型の定義 |
| validateExpression.ts | `packages/compiler-core/src/validateExpression.ts` | ソース | ブラウザビルド用の式バリデーション |
| runtimeHelpers.ts | `packages/compiler-core/src/runtimeHelpers.ts` | ソース | UNREF、IS_REFヘルパーシンボル定義 |
| utils.ts | `packages/compiler-core/src/utils.ts` | ソース | isSimpleIdentifier、advancePositionWithClone等のユーティリティ |
| errors.ts | `packages/compiler-core/src/errors.ts` | ソース | X_INVALID_EXPRESSIONエラーコード定義 |
