# 機能設計書 27-@babel/plugin-transform-async-to-generator

## 概要

本ドキュメントは、`@babel/plugin-transform-async-to-generator` プラグインの機能設計を記載したものである。このプラグインは、ES2017のasync/await構文をES2015のジェネレーター関数に変換するBabelプラグインである。

### 本機能の処理概要

**業務上の目的・背景**：ES2017で導入されたasync/await構文は、非同期処理を同期的なコードのように記述できる強力な機能である。ES2015環境ではこの構文がサポートされていないため、ジェネレーター関数とヘルパー関数を組み合わせて同等の動作を再現する必要がある。

**機能の利用シーン**：このプラグインは以下のような場面で利用される。
- `async function fn() {}` のようなasync関数の変換
- `const fn = async () => {}` のようなasyncアロー関数の変換
- `await promise` のようなawait式の変換
- `class { async method() {} }` のようなasyncメソッドの変換

**主要な処理内容**：
1. async関数の検出（async generatorは除外）
2. `@babel/helper-remap-async-to-generator`を使用した変換
3. 関数をジェネレーター関数にリマップ
4. `asyncToGenerator`ヘルパーまたはカスタムラッパーでラップ
5. `noNewArrows`と`ignoreFunctionLength` assumptionの処理

**関連システム・外部連携**：
- `@babel/core`：Babelのコア機能との連携
- `@babel/helper-plugin-utils`：プラグインユーティリティの利用
- `@babel/helper-remap-async-to-generator`：async関数のジェネレーター変換
- `@babel/helper-module-imports`：カスタムラッパーのインポート

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

## 関連画面

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

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| method | string | No | カスタムラッパー関数名 | moduleと同時に指定が必要 |
| module | string | No | カスタムラッパーモジュールパス | methodと同時に指定が必要 |

### 入力データソース

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

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ オプション（method, module）の読み込み
   └─ assumption設定の解決（noNewArrows, ignoreFunctionLength）

2. AST走査開始
   └─ Function（関数）ノードに対してビジターを実行

3. async関数の処理
   └─ asyncかつgeneratorでない関数を検出
   └─ カスタムラッパー指定の場合
   │  └─ addNamedでラッパーをインポート
   │  └─ remapAsyncToGeneratorを適用
   └─ デフォルトの場合
      └─ asyncToGeneratorヘルパーを使用
      └─ remapAsyncToGeneratorを適用

4. 関数変換
   └─ async関数をジェネレーター関数に変換
   └─ awaitをyieldに変換
   └─ ヘルパー関数でラップ
```

### フローチャート

```mermaid
flowchart TD
    A[Function検出] --> B{async関数?}
    B -->|No| Z[処理スキップ]
    B -->|Yes| C{generator?}
    C -->|Yes| Z
    C -->|No| D{カスタムラッパー指定?}

    D -->|Yes| E[addNamedでインポート]
    E --> F[remapAsyncToGenerator適用]

    D -->|No| G[asyncToGeneratorヘルパー取得]
    G --> F

    F --> H[async関数をgeneratorに変換]
    H --> I[awaitをyieldに変換]
    I --> J[ヘルパーでラップ]
    J --> K[AST置換]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | async generator除外 | async generatorは本プラグインでは処理しない | node.async && node.generator |
| BR-002 | カスタムラッパー | method/module指定時はカスタムラッパーを使用 | method && module |
| BR-003 | ヘルパーキャッシュ | カスタムラッパーは一度インポートしたらキャッシュ | カスタムラッパー使用時 |
| BR-004 | noNewArrows | アロー関数を通常関数に変換する際の設定 | デフォルト: true |

### 計算ロジック

**基本的な変換例**：
```javascript
// 入力
async function fn() {
  const result = await promise;
  return result;
}

// 出力
function fn() {
  return _asyncToGenerator(function* () {
    const result = yield promise;
    return result;
  })();
}
```

**asyncアロー関数の変換例**：
```javascript
// 入力
const fn = async () => {
  await promise;
};

// 出力
const fn = /*#__PURE__*/_asyncToGenerator(function* () {
  yield promise;
});
```

**カスタムラッパーの変換例**：
```javascript
// オプション: { method: "wrap", module: "my-async-lib" }

// 入力
async function fn() {
  await promise;
}

// 出力
import { wrap as _wrap } from "my-async-lib";

function fn() {
  return _wrap(function* () {
    yield promise;
  })();
}
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | - |

本プラグインは通常のasync関数に対してエラーを発生させない。

### リトライ仕様

ビルドプロセスのため、リトライは不要。

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

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

## パフォーマンス要件

- AST走査は1パスで完了すること
- ヘルパー関数のインポートは必要最小限

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

- ソースコードの変換のみを行い、外部リソースへのアクセスは行わない
- Promiseチェーンのエラーハンドリングは適切に保持される

## 備考

- ES2017のasync/awaitはTC39によって標準化されている
- async generatorは@babel/plugin-transform-async-generator-functionsで処理
- ランタイムでのPromiseサポートが必要

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-async-to-generator/src/index.ts` | Options型定義（6-9行目）とState型（11-13行目） |

**読解のコツ**: `methodWrapper`は一度インポートしたカスタムラッパーをキャッシュするために使用。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-async-to-generator/src/index.ts` | visitorオブジェクト（27-46行目および52-63行目） |

**主要処理フロー**:
1. **29行目**: async関数かつgeneratorでないことを確認
2. **31-35行目**: カスタムラッパーのキャッシュとインポート
3. **37-43行目**: remapAsyncToGenerator呼び出し
4. **53-54行目**: デフォルトモードのasync/generator判定
5. **56-61行目**: asyncToGeneratorヘルパーを使用した変換

#### Step 3: remapAsyncToGeneratorを理解する

実際の変換ロジックは`@babel/helper-remap-async-to-generator`パッケージで実装されている。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | - | `@babel/helper-remap-async-to-generator` | async関数からジェネレーターへの変換ロジック |

**主要処理**:
- async関数をジェネレーター関数に変換
- awaitをyieldに変換
- wrapAsync関数でラップ
- noNewArrowsとignoreFunctionLengthの処理

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

```
index.ts (エントリーポイント)
    │
    ├─ カスタムラッパーモード
    │      └─ visitor.Function
    │             ├─ addNamed (helper-module-imports)
    │             │    └─ カスタムラッパーをインポート
    │             └─ remapAsyncToGenerator (helper-remap-async-to-generator)
    │                    ├─ async → generator変換
    │                    ├─ await → yield変換
    │                    └─ wrapAsyncでラップ
    │
    └─ デフォルトモード
           └─ visitor.Function
                  └─ remapAsyncToGenerator
                         ├─ state.addHelper("asyncToGenerator")
                         ├─ async → generator変換
                         ├─ await → yield変換
                         └─ asyncToGeneratorでラップ
```

### データフロー図

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

JavaScriptソース ───▶ @babel/parser ───▶ AST
                                           │
                                           ▼
                              ┌─────────────────────────┐
                              │  transform-async-to-generator │
                              │  ビジター               │
                              │    │                    │
                              │    ├─ async関数検出     │
                              │    │                    │
                              │    ├─ カスタム/デフォルト│
                              │    │   ├─ ラッパー取得  │
                              │    │   └─ remap呼び出し │
                              │    │                    │
                              │    └─ 変換適用          │
                              │        ├─ generator化   │
                              │        ├─ yield化       │
                              │        └─ ラップ        │
                              └─────────────────────────┘
                                           │
                                           ▼
                              変換後AST ───▶ @babel/generator ───▶ ES2015コード
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-async-to-generator/src/index.ts` | ソース | プラグインエントリーポイント |
| package.json | `packages/babel-plugin-transform-async-to-generator/package.json` | 設定 | パッケージ定義、依存関係 |
| test/fixtures/ | `packages/babel-plugin-transform-async-to-generator/test/fixtures/` | テスト | テストフィクスチャ |
| @babel/helper-remap-async-to-generator | `packages/babel-helper-remap-async-to-generator/` | ヘルパー | async→generator変換ロジック |
