# 機能設計書 32-@babel/plugin-transform-private-methods

## 概要

本ドキュメントは、Babelの変換プラグイン「@babel/plugin-transform-private-methods」の機能設計を記述する。本プラグインはES2022のプライベートメソッド構文（#接頭辞付きメソッド）を、古いJavaScript環境でも動作する形式に変換する。

### 本機能の処理概要

本プラグインは、クラス内で宣言されたプライベートメソッド（`#methodName()`構文）およびプライベートアクセサ（getter/setter）を、WeakSetやWeakMapを用いた実装に変換する機能を提供する。

**業務上の目的・背景**：ES2022で正式に仕様化されたプライベートメソッド構文により、クラスの内部実装を完全にカプセル化できるようになった。しかし、古いブラウザやNode.jsバージョンではこの構文をサポートしていないため、トランスパイルが必要となる。本プラグインにより、開発者は真のプライベートメソッドを使用しながらも、幅広い環境での互換性を確保できる。

**機能の利用シーン**：
- オブジェクト指向設計でカプセル化を重視するアプリケーション開発
- セキュリティ上の理由で内部メソッドを隠蔽したいライブラリ開発
- `@babel/preset-env`の一部として自動的に適用される場合

**主要な処理内容**：
1. クラス宣言/式内のプライベートメソッド宣言（ClassPrivateMethod）を検出
2. インスタンスプライベートメソッドをWeakSetを用いたブランドチェック実装に変換
3. 静的プライベートメソッドをクラス参照チェック実装に変換
4. プライベートアクセサ（getter/setter）を適切な変換形式に処理
5. 非同期メソッドやジェネレータメソッドも適切に変換

**関連システム・外部連携**：
- `@babel/helper-create-class-features-plugin`: クラス機能の変換ロジックを提供する共有ヘルパー
- `@babel/helper-plugin-utils`: プラグインユーティリティ
- `@babel/core`: Babelコアとの統合

**権限による制御**：特になし。変換はビルド時に実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIまたはビルドツール経由で使用されるため、画面との関連なし |

## 機能種別

コード変換処理 / AST操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loose | boolean | No | trueの場合、仕様準拠よりもパフォーマンスを優先した簡易な変換を行う | boolean型であること |

### 入力データソース

- Babelによってパースされたソースコード（AST形式）
- 特にClassDeclaration、ClassExpression内のClassPrivateMethodノード

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ createClassFeaturePlugin関数を呼び出し、FEATURESにprivateMethodsを指定

2. クラスノード（ClassDeclaration/ClassExpression）の訪問
   └─ helper-create-class-features-plugin内のビジターが処理

3. プライベートメソッドの検出と分類
   ├─ インスタンスプライベートメソッド
   ├─ 静的プライベートメソッド
   ├─ プライベートgetter
   └─ プライベートsetter

4. 変換処理の実行
   ├─ looseモード: 簡易なブランドチェック実装
   └─ 標準モード: WeakSetを使用した完全なカプセル化

5. メソッド本体の抽出と外部関数化
   └─ クラス外部に関数として配置し、参照を保持
```

### フローチャート

```mermaid
flowchart TD
    A[クラスノードの訪問] --> B{プライベートメソッドあり?}
    B -->|No| Z[変換なし]
    B -->|Yes| C{メソッドの種類}
    C -->|インスタンスメソッド| D{looseモード?}
    C -->|静的メソッド| E[クラス参照チェックに変換]
    C -->|getter/setter| F[アクセサ変換処理]
    D -->|Yes| G[簡易ブランドチェック]
    D -->|No| H[WeakSetによるブランドチェック]
    E --> I[変換完了]
    F --> I
    G --> I
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | ブランドチェック | プライベートメソッド呼び出し時に正しいインスタンスかをチェック | 常時 |
| BR-32-02 | looseモード動作 | looseモードではWeakSetを使用せず、プロパティベースのチェックを使用 | loose=true |
| BR-32-03 | 静的メソッドのチェック | 静的プライベートメソッドはクラス自体との等価性でチェック | 静的メソッド使用時 |

### 計算ロジック

特になし（構文変換のため）

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

該当なし（コンパイル時変換のため）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SyntaxError | 不正なプライベートメソッド構文 | パーサーレベルでエラー |
| - | TypeError | 実行時に不正なオブジェクトでプライベートメソッドを呼び出し | ブランドチェックでエラー |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 変換処理は同期的に実行される
- looseモードを使用することでランタイムオーバーヘッドを削減可能

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

- プライベートメソッドの変換では、実行時にも外部からアクセスできない実装を維持
- WeakSetを使用することで、オブジェクトのライフサイクルに影響を与えない

## 備考

- 本プラグインは`@babel/preset-env`に含まれており、ターゲット環境に応じて自動的に適用される
- `@babel/plugin-transform-class-properties`と併用されることが多い

---

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

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

### 推奨読解順序

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

本プラグインはプライベートメソッド関連のASTノード（ClassPrivateMethod）を変換対象とする。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-private-methods/src/index.ts` | プラグインのエントリーポイント。Optionsインターフェースでlooseオプションを定義 |

**読解のコツ**: `createClassFeaturePlugin`関数に委譲する構造のため、実際の変換ロジックは`@babel/helper-create-class-features-plugin`パッケージにある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-private-methods/src/index.ts` | declare関数でプラグインを定義し、createClassFeaturePluginを呼び出す |

**主要処理フロー**:
1. **3-7行目**: 必要なモジュールのインポート（createClassFeaturePlugin, FEATURES）
2. **9-11行目**: Optionsインターフェースの定義（looseオプション）
3. **13-14行目**: APIバージョンの検証（^7.0.0-0 || ^8.0.0）
4. **16-22行目**: createClassFeaturePluginの呼び出し、FEATURES.privateMethodsを指定

#### Step 3: テストケースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | private-method/ | `packages/babel-plugin-transform-private-methods/test/fixtures/private-method/` | インスタンスプライベートメソッドの変換テスト |
| 3-2 | private-static-method/ | `packages/babel-plugin-transform-private-methods/test/fixtures/private-static-method/` | 静的プライベートメソッドの変換テスト |
| 3-3 | accessors/ | `packages/babel-plugin-transform-private-methods/test/fixtures/accessors/` | プライベートアクセサの変換テスト |

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

```
@babel/plugin-transform-private-methods/src/index.ts
    │
    └─ createClassFeaturePlugin (from @babel/helper-create-class-features-plugin)
           │
           ├─ ClassDeclaration/ClassExpression visitor
           │      └─ transformPrivateMethods
           │
           ├─ buildPrivateMethodInitialization
           │      └─ WeakSet.add() 呼び出し生成
           │
           └─ replacePrivateMethodAccess
                  └─ ブランドチェックコード生成
```

### データフロー図

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

プライベートメソッド  ─▶  @babel/helper-create       ─▶  WeakSet/ブランドチェック
付きソースコード(AST)     -class-features-plugin          実装コード(AST)
                                 │
                                 ├─ メソッド検出
                                 ├─ 外部関数化
                                 └─ ブランドチェック挿入
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-transform-private-methods/src/index.ts` | ソース | プラグインエントリーポイント |
| package.json | `packages/babel-plugin-transform-private-methods/package.json` | 設定 | パッケージ依存関係定義 |
| test/index.js | `packages/babel-plugin-transform-private-methods/test/index.js` | テスト | テストランナー設定 |
| fixtures/ | `packages/babel-plugin-transform-private-methods/test/fixtures/` | テスト | テストケース群 |
