# 機能設計書 26-@babel/plugin-transform-block-scoping

## 概要

本ドキュメントは、`@babel/plugin-transform-block-scoping` プラグインの機能設計を記載したものである。このプラグインは、ES2015（ES6）のブロックスコープ変数宣言（`let`、`const`）をES5互換のコードに変換するBabelプラグインである。

### 本機能の処理概要

**業務上の目的・背景**：ES2015で導入された`let`と`const`は、ブロックスコープの変数宣言を可能にする。従来の`var`とは異なり、宣言されたブロック内でのみ有効となる。古いJavaScript環境ではこれらのキーワードがサポートされていないため、`var`を使用しつつスコープの挙動を再現する必要がある。

**機能の利用シーン**：このプラグインは以下のような場面で利用される。
- `let x = 1;` や `const y = 2;` のようなブロックスコープ変数の変換
- ループ内でのクロージャキャプチャの処理
- TDZ（Temporal Dead Zone）エミュレーション（オプション）
- クラス宣言のブロックスコープ処理

**主要な処理内容**：
1. `let`/`const`宣言を`var`宣言に変換
2. ブロックスコープ内で外部スコープと同名の変数がある場合、変数名をリネーム
3. ループ内でクロージャにキャプチャされる変数の処理（IIFEラッパー生成）
4. TDZチェックの生成（オプション有効時）
5. クラス宣言のブロックスコープ処理

**関連システム・外部連携**：
- `@babel/core`：Babelのコア機能との連携
- `@babel/helper-plugin-utils`：プラグインユーティリティの利用
- `@babel/types`：ASTノードの検証・構築
- `@babel/plugin-transform-explicit-resource-management`：`using`/`await using`の前処理

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tdz | boolean | No | TDZ（Temporal Dead Zone）チェックの生成 | デフォルト: false |
| throwIfClosureRequired | boolean | No | クロージャが必要な場合にエラーを投げる | デフォルト: false |

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ オプション（tdz, throwIfClosureRequired）の読み込み
   └─ オプションの型検証

2. AST走査開始
   └─ Loop、VariableDeclaration、ClassDeclarationに対してビジターを実行

3. Loop処理
   └─ ループ本体内のブロックスコープバインディングを収集
   └─ クロージャキャプチャの検出
   └─ throwIfClosureRequired有効時: エラー発生
   └─ それ以外: wrapLoopBodyでIIFEラッパー生成

4. VariableDeclaration処理
   └─ let/const宣言かどうかを判定
   └─ using/await usingの場合はエラー（前処理必要）
   └─ TDZ検証の実行
   └─ kind を "var" に変更
   └─ 外部スコープとの名前衝突時にリネーム
   └─ バインディングを関数/プログラムスコープに移動

5. ClassDeclaration処理
   └─ 外部スコープと同名のクラスがある場合にリネーム
```

### フローチャート

```mermaid
flowchart TD
    A[AST走査開始] --> B{ノードタイプ判定}
    B -->|Loop| C[ブロックスコープバインディング収集]
    C --> D{クロージャキャプチャあり?}
    D -->|Yes| E{throwIfClosureRequired?}
    E -->|Yes| F[エラー発生]
    E -->|No| G[wrapLoopBodyでIIFE生成]
    D -->|No| H[処理継続]

    B -->|VariableDeclaration| I{let/const?}
    I -->|No| Z[処理スキップ]
    I -->|Yes| J{using/await using?}
    J -->|Yes| K[エラー: 前処理必要]
    J -->|No| L[TDZ検証]
    L --> M[kind を var に変更]
    M --> N{名前衝突あり?}
    N -->|Yes| O[変数リネーム]
    N -->|No| P[スコープ移動]
    O --> P

    B -->|ClassDeclaration| Q{名前衝突あり?}
    Q -->|Yes| R[クラスリネーム]
    Q -->|No| Z

    G --> S[AST置換]
    P --> S
    R --> S
    S --> T[次のノードへ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | TDZエミュレーション | 宣言前の参照をランタイムでチェック | tdzオプション有効時 |
| BR-002 | クロージャラップ | ループ内でキャプチャされる変数をIIFEでラップ | ループ内クロージャ検出時 |
| BR-003 | 変数リネーム | 外部スコープと衝突する変数名を一意にリネーム | 名前衝突検出時 |
| BR-004 | using前処理必須 | using/await using宣言は先に変換が必要 | using/await using検出時 |

### 計算ロジック

**基本的な変換例**：
```javascript
// 入力
{
  let x = 1;
  const y = 2;
}

// 出力
{
  var x = 1;
  var y = 2;
}
```

**名前衝突時の変換例**：
```javascript
// 入力
let x = 1;
{
  let x = 2;
}

// 出力
var x = 1;
{
  var _x = 2;
}
```

**ループクロージャの変換例**：
```javascript
// 入力
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i));
}

// 出力
var _loop = function (i) {
  setTimeout(function () {
    return console.log(i);
  });
};
for (var i = 0; i < 3; i++) {
  _loop(i);
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | BuildCodeFrameError | throwIfClosureRequired有効時にクロージャが必要 | オプションを無効化するか、コードを修正 |
| - | BuildCodeFrameError | using/await using宣言の検出 | @babel/plugin-transform-explicit-resource-managementを先に適用 |
| - | Error | tdzオプションがboolean以外 | オプションを修正 |
| - | Error | throwIfClosureRequiredオプションがboolean以外 | オプションを修正 |

### リトライ仕様

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

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

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

## パフォーマンス要件

- AST走査は1パスで完了すること
- IIFEラッパーの生成は必要最小限に抑えること

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

- ソースコードの変換のみを行い、外部リソースへのアクセスは行わない
- TDZエミュレーションにより宣言前参照のセキュリティ問題を検出可能

## 備考

- ES2015のlet/constはTC39によって標準化されている
- TDZオプションを有効にするとランタイムオーバーヘッドが増加する
- throwIfClosureRequiredはパフォーマンス重視のビルド設定で使用

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-block-scoping/src/index.ts` | Options型定義（13-16行目）とオプション検証（21-27行目） |

**読解のコツ**: `throwIfClosureRequired`はIIFE生成を禁止するオプション。パフォーマンス重視時に使用。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-block-scoping/src/index.ts` | visitorオブジェクト（32-158行目） |

**主要処理フロー**:
1. **33-135行目**: Loopビジター - ループ内ブロックスコープの処理
2. **137-139行目**: VariableDeclarationビジター
3. **145-156行目**: ClassDeclarationビジター

#### Step 3: transformBlockScopedVariable関数を理解する

let/constからvarへの変換ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/babel-plugin-transform-block-scoping/src/index.ts` | transformBlockScopedVariable関数（175-239行目） |

**主要処理フロー**:
- **180行目**: isBlockScoped判定
- **182行目**: validateUsage呼び出し（TDZ検証）
- **184行目**: kindを"var"に変更
- **193-204行目**: ループ内変数の初期化
- **210-227行目**: スコープ移動とリネーム

#### Step 4: ループラッパー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | loop.ts | `packages/babel-plugin-transform-block-scoping/src/loop.ts` | wrapLoopBody関数（165-374行目）、getLoopBodyBindings関数（29-33行目） |

**主要処理フロー**:
- **29-33行目**: ブロックスコープバインディングの収集
- **35-74行目**: getUsageInBody - クロージャキャプチャの検出
- **165-374行目**: wrapLoopBody - IIFE生成とbreak/continue/return処理

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

```
index.ts (エントリーポイント)
    │
    ├─ visitor.Loop
    │      ├─ getLoopBodyBindings (loop.ts)
    │      ├─ getUsageInBody (loop.ts)
    │      │    └─ relativeLoopLocation
    │      ├─ markNeedsBodyWrap
    │      └─ wrapLoopBody (loop.ts)
    │             ├─ collectCompletionsAndVarsVisitor
    │             ├─ 関数式生成
    │             └─ break/continue/return処理
    │
    ├─ visitor.VariableDeclaration
    │      └─ transformBlockScopedVariable
    │             ├─ isBlockScoped
    │             ├─ validateUsage (validation.ts)
    │             ├─ scope.rename
    │             ├─ scope.moveBindingTo
    │             └─ conflictingFunctionsVisitor
    │
    └─ visitor.ClassDeclaration
           └─ scope.rename
```

### データフロー図

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

JavaScriptソース ───▶ @babel/parser ───▶ AST
                                           │
                                           ▼
                              ┌─────────────────────────┐
                              │  transform-block-scoping │
                              │  ビジター               │
                              │    │                    │
                              │    ├─ Loop処理          │
                              │    │   ├─ バインディング収集│
                              │    │   ├─ クロージャ検出 │
                              │    │   └─ IIFE生成      │
                              │    │                    │
                              │    ├─ VariableDeclaration│
                              │    │   ├─ TDZ検証       │
                              │    │   ├─ kind変更      │
                              │    │   └─ リネーム/移動  │
                              │    │                    │
                              │    └─ ClassDeclaration  │
                              │        └─ リネーム       │
                              └─────────────────────────┘
                                           │
                                           ▼
                              変換後AST ───▶ @babel/generator ───▶ ES5コード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-block-scoping/src/index.ts` | ソース | プラグインエントリーポイント、メインビジター |
| loop.ts | `packages/babel-plugin-transform-block-scoping/src/loop.ts` | ソース | ループ処理、IIFE生成 |
| validation.ts | `packages/babel-plugin-transform-block-scoping/src/validation.ts` | ソース | TDZ検証 |
| package.json | `packages/babel-plugin-transform-block-scoping/package.json` | 設定 | パッケージ定義、依存関係 |
| test/fixtures/ | `packages/babel-plugin-transform-block-scoping/test/fixtures/` | テスト | テストフィクスチャ |
