# 機能設計書 25-@babel/plugin-transform-for-of

## 概要

本ドキュメントは、`@babel/plugin-transform-for-of` プラグインの機能設計を記載したものである。このプラグインは、ES2015（ES6）のfor-of文をES5互換のコードに変換するBabelプラグインである。

### 本機能の処理概要

**業務上の目的・背景**：ES2015で導入されたfor-of文は、イテラブルオブジェクト（配列、Map、Set、文字列など）を簡潔に反復処理するための構文である。古いJavaScript環境ではこの構文がサポートされていないため、従来のforループやイテレータープロトコルを明示的に使用した方法に変換する必要がある。

**機能の利用シーン**：このプラグインは以下のような場面で利用される。
- `for (const item of array) {}` のような配列のfor-of文の変換
- `for (const [key, value] of map) {}` のようなMapのfor-of文の変換
- `for (const char of string) {}` のような文字列のfor-of文の変換
- `for await (const item of asyncIterable) {}` は非対応（async-generator-functionsプラグインで処理）

**主要な処理内容**：
1. `iterableIsArray` assumptionがtrueの場合、単純なforループに変換
2. それ以外の場合、`createForOfIteratorHelper`ヘルパーを使用してイテレーター処理
3. `skipForOfIteratorClosing` assumptionに基づくエラーハンドリングの最適化
4. ラベル付きfor-of文の適切な処理
5. 配列リテラルや配列型の直接検出による最適化

**関連システム・外部連携**：
- `@babel/core`：Babelのコア機能との連携
- `@babel/helper-plugin-utils`：プラグインユーティリティの利用
- `@babel/helper-skip-transparent-expression-wrappers`：透過的なラッパー式のスキップ
- `@babel/types`：ASTノードの検証・構築

**権限による制御**：特になし。ビルド時に実行されるトランスパイル処理のため、権限による制御は不要。

## 関連画面

本プラグインはビルドツールとして動作するため、直接的な関連画面はない。

## 機能種別

コード変換処理（AST変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| assumeArray | boolean | No | イテラブルが配列であると仮定 | looseと同時指定不可、allowArrayLikeと同時指定不可 |
| allowArrayLike | boolean | No | 配列ライクオブジェクトをイテラブルとして扱う | assumeArrayと同時指定不可 |
| loose | boolean | No | looseモードの有効化。`skipForOfIteratorClosing`を有効にする | assumeArrayと同時指定不可 |

### 入力データソース

- JavaScriptソースコード（AST形式）
- Babelの設定ファイル（babel.config.js, .babelrc等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| transformedAST | AST | 変換後のAST |

### 出力先

変換されたASTは@babel/generatorによってJavaScriptコードとして出力される。

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ オプション（assumeArray, allowArrayLike, loose）の読み込み
   └─ assumption設定の解決（iterableIsArray, arrayLikeIsIterable, skipForOfIteratorClosing）
   └─ オプションの競合チェック

2. AST走査開始
   └─ ForOfStatement（for-of文）に対してビジターを実行

3. iterableIsArrayモードの場合
   └─ for await文の場合はスキップ
   └─ 右辺を一時変数に格納（必要な場合）
   └─ インデックスベースのforループに変換

4. 通常モードの場合
   └─ 右辺が配列リテラルまたは配列型の場合
   │  └─ 単純なforループに変換（_ForOfStatementArray）
   └─ それ以外の場合
      └─ イテレーターヘルパーを使用した変換
      └─ skipIteratorClosingに応じてtry-finally構造を生成

5. ラベル付き文の処理
   └─ 親がLabeledStatementの場合、ラベルを保持
```

### フローチャート

```mermaid
flowchart TD
    A[ForOfStatement検出] --> B{iterableIsArray?}
    B -->|Yes| C{for await?}
    C -->|Yes| Z[処理スキップ]
    C -->|No| D[インデックスforループに変換]

    B -->|No| E{右辺が配列?}
    E -->|Yes| F[_ForOfStatementArrayで変換]
    E -->|No| G{skipIteratorClosing?}
    G -->|Yes| H[単純ループ生成]
    G -->|No| I[try-finally構造生成]

    D --> J[AST置換]
    F --> J
    H --> J
    I --> J

    J --> K{親がラベル付き?}
    K -->|Yes| L[ラベル保持]
    K -->|No| M[完了]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 配列最適化 | 右辺が配列リテラルまたは配列型の場合は単純forループに変換 | iterableIsArrayがfalseでも適用 |
| BR-002 | イテレータークローズ | looseモードでない場合、イテレーターの適切なクローズ処理を生成 | skipForOfIteratorClosingがfalse |
| BR-003 | オプション競合 | assumeArrayとloose、assumeArrayとallowArrayLikeは同時指定不可 | オプション検証時 |
| BR-004 | for await除外 | for await文は本プラグインでは処理しない | iterableIsArrayモード |

### 計算ロジック

**iterableIsArrayモードの変換例**：
```javascript
// 入力
for (const item of arr) {
  console.log(item);
}

// 出力
for (var _i = 0, _arr = arr; _i < _arr.length; _i++) {
  const item = _arr[_i];
  console.log(item);
}
```

**通常モードの変換例（skipIteratorClosing = false）**：
```javascript
// 入力
for (const item of iterable) {
  console.log(item);
}

// 出力
var _iterator = _createForOfIteratorHelper(iterable), _step;
try {
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
    const item = _step.value;
    console.log(item);
  }
} catch (err) {
  _iterator.e(err);
} finally {
  _iterator.f();
}
```

**looseモードの変換例**：
```javascript
// 入力
for (const item of iterable) {
  console.log(item);
}

// 出力
for (var _iterator = _createForOfIteratorHelperLoose(iterable), _step;
     !(_step = _iterator()).done;) {
  const item = _step.value;
  console.log(item);
}
```

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

本プラグインはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | looseとassumeArrayの同時指定 | オプションの見直し |
| - | Error | assumeArrayとallowArrayLikeの同時指定 | オプションの見直し |
| - | Error | iterableIsArrayとarrayLikeIsIterableの同時指定 | assumptionの見直し |

### リトライ仕様

ビルドプロセスのため、リトライは不要。エラー発生時はビルドが中断される。

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

該当なし。ビルドプロセスはトランザクション管理を行わない。

## パフォーマンス要件

- AST走査は1パスで完了すること
- iterableIsArrayモードでは最小限のランタイムオーバーヘッド

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

- ソースコードの変換のみを行い、外部リソースへのアクセスは行わない
- イテレーター処理のエラーハンドリングは適切に生成される

## 備考

- ES2015のfor-of文はTC39によって標準化されている
- for await文は@babel/plugin-transform-async-generator-functionsで処理される
- looseモードではイテレーターのクローズ処理が省略されるため、リソースリークの可能性がある

---

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

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

### 推奨読解順序

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

まず、プラグインのオプションとassumption設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-for-of/src/index.ts` | Options型定義（6-10行目）とオプション競合チェック（37-51行目） |

**読解のコツ**: `assumeArray`はBabel 7で追加された明示的な配列仮定オプション。`loose`のサブセット。

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

処理の起点となるビジターパターンを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-for-of/src/index.ts` | iterableIsArrayモードのビジター（72-131行目）と通常モードのビジター（205-263行目） |

**主要処理フロー**:
1. **76-81行目**: for await文のスキップ
2. **83-100行目**: 一時変数の生成と初期化
3. **117-128行目**: forループへの変換

#### Step 3: ヘルパー関数を理解する

変換に使用されるテンプレートとヘルパーを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/babel-plugin-transform-for-of/src/index.ts` | buildForOfArray（134-136行目）、buildForOfNoIteratorClosing（138-141行目）、buildForOf（143-152行目） |
| 3-2 | index.ts | `packages/babel-plugin-transform-for-of/src/index.ts` | buildLoopBody関数（12-32行目）、_ForOfStatementArray関数（168-203行目） |

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

```
index.ts (エントリーポイント)
    │
    ├─ iterableIsArrayモード
    │      └─ visitor.ForOfStatement
    │             ├─ for awaitチェック
    │             ├─ 一時変数生成
    │             └─ forループ生成
    │
    └─ 通常モード
           └─ visitor.ForOfStatement
                  ├─ 配列判定
                  │    └─ _ForOfStatementArray
                  │           ├─ buildForOfArray
                  │           └─ buildLoopBody
                  │
                  └─ イテレーター処理
                         ├─ builder.build
                         │    ├─ buildForOfNoIteratorClosing（loose）
                         │    └─ buildForOf（strict）
                         ├─ builder.getContainer
                         └─ ラベル付き文処理
```

### データフロー図

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

JavaScriptソース ───▶ @babel/parser ───▶ AST
                                           │
                                           ▼
                              ┌─────────────────────────┐
                              │  transform-for-of        │
                              │  ビジター               │
                              │    │                    │
                              │    ├─ iterableIsArray?  │
                              │    │    ├─ Yes: 単純forループ│
                              │    │    └─ No: 配列判定  │
                              │    │         ├─ 配列: 最適化│
                              │    │         └─ 他: ヘルパー│
                              │    │                    │
                              │    └─ ラベル保持        │
                              └─────────────────────────┘
                                           │
                                           ▼
                              変換後AST ───▶ @babel/generator ───▶ ES5コード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-for-of/src/index.ts` | ソース | プラグインエントリーポイント、ビジター・ヘルパー定義 |
| package.json | `packages/babel-plugin-transform-for-of/package.json` | 設定 | パッケージ定義、依存関係 |
| test/fixtures/ | `packages/babel-plugin-transform-for-of/test/fixtures/` | テスト | テストフィクスチャ |
