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

## 概要

本ドキュメントは、Vue 3テンプレートコンパイラにおけるv-bindディレクティブのAST変換処理について記述する。v-bindディレクティブを属性バインディングのプロパティに変換し、動的属性・クラス・スタイルの処理を行う。

### 本機能の処理概要

`transformBind` はDirectiveTransformとして実装されており、v-bindディレクティブ（`:attr="expr"` 形式）を検出し、属性名をキー、式を値とするプロパティノードを生成する。`.camel`、`.prop`、`.attr` 修飾子によるプロパティ名の変換と、動的引数のフォールバック処理を行う。

**業務上の目的・背景**：HTMLの属性やDOMプロパティにJavaScriptの値を動的にバインドする機能はVueテンプレートの基本的な機能であり、v-bindは最も頻繁に使用されるディレクティブの一つである。コンパイラ段階で属性名の変換と修飾子の処理を行い、効率的なバインディングコードを生成する。

**機能の利用シーン**：テンプレートコンパイルパイプラインのtransformフェーズで、v-bind（または`:`）ディレクティブを持つ要素/コンポーネントノードに対して実行される。argなしのv-bind（`v-bind="obj"`形式）は別途transformElementで処理される。

**主要な処理内容**：
1. 空式のチェックとエラー処理
2. 動的引数のフォールバック処理（`arg || ""`）
3. `.camel` 修飾子によるキャメルケース変換
4. `.prop` 修飾子による`.`プレフィックス注入
5. `.attr` 修飾子による`^`プレフィックス注入
6. プロパティノード（ObjectProperty）の生成

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | Index（メイン画面） | 補助機能 | v-bind属性バインディングのコンパイル結果をリアルタイム確認 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| dir | DirectiveNode | Yes | v-bindディレクティブ（argは必須） | exp空チェック（非ブラウザ時のみエラー） |
| _node | ElementNode | Yes | v-bindを持つ要素ノード（本変換では未使用） | なし |
| context | TransformContext | Yes | 変換コンテキスト | なし |

### 入力データソース

パーサーが生成したAST内のv-bindディレクティブ付き要素ノード。argなしのv-bindは別途transformElementで処理される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| props | Property[] | 属性名（arg）と値（exp）のペア |

### 出力先

DirectiveTransformResultとして、transformElement処理に合流する。

## 処理フロー

### 処理シーケンス

```
1. 空式のチェック
   └─ 非ブラウザ時: X_V_BIND_NO_EXPRESSION エラー → 空文字列のSimpleExpressionを返却
   └─ ブラウザ時: exp = undefined として続行
2. 動的引数のフォールバック
   └─ CompoundExpression: (arg) || "" を追加
   └─ 非静的SimpleExpression: arg.content || "" に変換
3. .camel 修飾子の処理
   └─ 静的arg: camelize(arg.content) で変換
   └─ 動的arg: CAMELIZE(arg.content) ヘルパー呼び出しに変換
4. .prop 修飾子の処理（非SSR時）
   └─ 静的arg: "." プレフィックス注入
   └─ 動的arg: '.' + (arg) 形式に変換
5. .attr 修飾子の処理（非SSR時）
   └─ 静的arg: "^" プレフィックス注入
   └─ 動的arg: '^' + (arg) 形式に変換
6. プロパティの生成
   └─ createObjectProperty(arg, exp)
```

### フローチャート

```mermaid
flowchart TD
    A[v-bind検出] --> B{式が空?}
    B -->|Yes & 非ブラウザ| C[X_V_BIND_NO_EXPRESSION + 空文字返却]
    B -->|Yes & ブラウザ| D[exp = undefined]
    B -->|No| E[動的引数フォールバック]
    C --> F{修飾子チェック}
    D --> F
    E --> F
    F --> G{.camel?}
    G -->|Yes| H[キャメルケース変換]
    G -->|No| I[スキップ]
    H --> J{.prop?}
    I --> J
    J -->|Yes & !SSR| K[. プレフィックス注入]
    J -->|No| L{.attr?}
    K --> M[createObjectProperty]
    L -->|Yes & !SSR| N[^ プレフィックス注入]
    L -->|No| M
    N --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | 空式処理の差異 | ブラウザビルドでは空式を許容（`:foo`がDOMで`:foo=""`に解析されるため） | __BROWSER__環境 |
| BR-50-02 | 動的引数フォールバック | 動的引数は`arg || ""`形式でフォールバック | arg.isStatic === false時 |
| BR-50-03 | camelケース変換 | `.camel`修飾子で属性名をcamelCaseに変換 | modifiers含む'camel'時 |
| BR-50-04 | propプレフィックス | `.prop`修飾子で`.`プレフィックスを注入（DOMプロパティとして設定） | 非SSR時 |
| BR-50-05 | attrプレフィックス | `.attr`修飾子で`^`プレフィックスを注入（HTML属性として設定） | 非SSR時 |
| BR-50-06 | SSR除外 | .propと.attrのプレフィックス注入はSSRモードでは行わない | SSR時 |

### 計算ロジック

- 静的引数のcamelケース変換: `camelize(arg.content)` （@vue/shared）
- 動的引数のcamelケース変換: `${context.helperString(CAMELIZE)}(${arg.content})` （ランタイムヘルパー）

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| X_V_BIND_NO_EXPRESSION | コンパイルエラー | v-bind式が空（非ブラウザビルドのみ） | バインドする式を指定 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 軽量な文字列処理のみで構成されるため、特別なパフォーマンス要件はない
- 静的引数の場合はコンパイル時に変換が完了し、ランタイムコストなし

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

- `.prop`修飾子はDOMプロパティに直接設定するため、XSS脆弱性の入口となる可能性がある
- 動的引数の値はユーザー入力に由来する可能性があるため、適切なサニタイズが重要

## 備考

- argなしのv-bind（`v-bind="obj"`形式）はtransformElement.tsで処理され、本変換は呼ばれない
- `.prop`の`.`プレフィックスと`.attr`の`^`プレフィックスはランタイム（patchProp）で特別に処理される
- compiler-coreのtransformBindはプラットフォーム非依存であり、compiler-domでの上書きは行われない
- `transformVBindShorthand` はv-bindの短縮記法（同名属性バインディング）の変換を担当する別のtransform

---

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

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

### 推奨読解順序

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

DirectiveTransform/DirectiveTransformResultの構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transform.ts | `packages/compiler-core/src/transform.ts` | DirectiveTransform型（56-63行目）: dir, node, context, augmentorパラメータ |
| 1-2 | transform.ts | `packages/compiler-core/src/transform.ts` | DirectiveTransformResult型（65-69行目）: props, needRuntime |

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

transformBindの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | vBind.ts | `packages/compiler-core/src/transforms/vBind.ts` | transformBind（15-73行目）: 全体の実装 |
| 2-2 | vBind.ts | `packages/compiler-core/src/transforms/vBind.ts` | injectPrefix関数（75-86行目）: .prop/.attr用のプレフィックス注入ユーティリティ |

**主要処理フロー**:
1. **22-38行目**: 空式のチェック。非ブラウザ時はエラー、ブラウザ時はexp=undefined
2. **40-45行目**: 動的引数のフォールバック処理（`|| ""`追加）
3. **48-59行目**: `.camel`修飾子の処理（静的/動的の分岐）
4. **61-68行目**: `.prop`と`.attr`修飾子の処理（非SSR時のみ）
5. **70-72行目**: createObjectProperty(arg, exp)でプロパティ生成

#### Step 3: プレフィックス注入を理解する

injectPrefix関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | vBind.ts | `packages/compiler-core/src/transforms/vBind.ts` | injectPrefix（75-86行目）: 静的/動的/CompoundExpression対応のプレフィックス注入 |

**主要処理フロー**:
- **77-78行目**: 静的arg: `prefix + arg.content` で直接連結
- **79-80行目**: 動的SimpleExpression: テンプレートリテラルで連結
- **82-84行目**: CompoundExpression: 子ノードの先頭/末尾に追加

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

```
transformBind(dir, _node, context)
    │
    ├─ 空式チェック
    │      └─ [非ブラウザ] createCompilerError(X_V_BIND_NO_EXPRESSION)
    │
    ├─ 動的引数フォールバック
    │      ├─ CompoundExpression: children追加
    │      └─ SimpleExpression: content変更
    │
    ├─ .camel修飾子
    │      ├─ [静的] camelize(content)
    │      └─ [動的] CAMELIZE ヘルパー呼び出し
    │
    ├─ .prop修飾子（非SSR）
    │      └─ injectPrefix(arg, '.')
    │
    ├─ .attr修飾子（非SSR）
    │      └─ injectPrefix(arg, '^')
    │
    └─ createObjectProperty(arg, exp)
```

### データフロー図

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

:my-attr.camel="value"    ──▶ arg: "my-attr"                 ──▶ { myAttr: value }
                               .camel → camelize("my-attr")
                               → "myAttr"

:data-id.prop="value"     ──▶ arg: "data-id"                 ──▶ { .data-id: value }
                               .prop → injectPrefix(".")

:[dynamicAttr]="value"    ──▶ arg: dynamicAttr               ──▶ { (dynamicAttr || ""): value }
                               動的フォールバック追加
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| vBind.ts | `packages/compiler-core/src/transforms/vBind.ts` | ソース | transformBind, injectPrefixの実装（87行） |
| transformVBindShorthand.ts | `packages/compiler-core/src/transforms/transformVBindShorthand.ts` | ソース | v-bind短縮記法の変換 |
| compile.ts | `packages/compiler-core/src/compile.ts` | ソース | transformBindの登録 |
| runtimeHelpers.ts | `packages/compiler-core/src/runtimeHelpers.ts` | ソース | CAMELIZEシンボル |
