# 機能設計書 69-@babel/plugin-bugfix-firefox-class-in-computed-class-key

## 概要

本ドキュメントは、Firefoxの計算プロパティキー内でのクラス式に関するバグを修正するプラグイン `@babel/plugin-bugfix-firefox-class-in-computed-class-key` の機能設計を定義する。

### 本機能の処理概要

本プラグインは、Firefox（SpiderMonkey）に存在するバグ（[bugzilla.mozilla.org/show_bug.cgi?id=1887677](https://bugzilla.mozilla.org/show_bug.cgi?id=1887677)）に対するワークアラウンドを提供する。このバグは、クラスの計算プロパティキー内にクラス式が存在し、かつ外部クラスにプライベート要素がある場合に発生する。

**業務上の目的・背景**：Firefoxの特定バージョンでは、プライベートフィールドを持つクラスの計算プロパティキー内でクラス式を使用すると、スコープ解決のバグが発生する。例えば、`class A { #x; [class {}] = 1 }` のようなパターンで問題が発生する。本プラグインは、このようなパターンを検出し、IIFEまたはジェネレータ関数でラップすることで問題を回避する。

**機能の利用シーン**：
- Firefoxをサポートする必要があるウェブアプリケーション
- @babel/preset-envのtargets設定でFirefoxが含まれる場合
- プライベートフィールドを持つクラスで計算プロパティキーにクラス式を使用するコード

**主要な処理内容**：
1. Classノードを検出し、プライベート要素の存在を確認
2. 計算プロパティキー内にクラス式が含まれているか判定
3. yield/awaitの存在に応じて適切なラッパー（IIFE/ジェネレータ）を生成
4. プロパティキーを安全な形式に変換

**関連システム・外部連携**：`@babel/core`のAST変換機能を利用する。

**権限による制御**：特にロールや権限による制御はない。Babel設定ファイルでのプラグイン有効化により機能する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はCLIツールまたはビルドプロセスで使用され、GUI画面との関連はない |

## 機能種別

バグ修正処理（AST変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | 本プラグインにはオプションパラメータはない | - |

### 入力データソース

- ソースコードからのASTノード（Class、ClassProperty、ClassMethod等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| transformedAST | AST Node | 変換後のAST（ラップされた計算プロパティキー） |

### 出力先

- 変換後のJavaScriptコード（Babelのパイプライン出力）

## 処理フロー

### 処理シーケンス

```
1. Class訪問
   └─ プライベート要素の存在を確認（body.body.some(isPrivate)）
2. プライベート要素がない場合はスキップ
3. クラスボディの各要素を走査
   └─ computed === true のプロパティ/メソッドを検出
4. 計算キー内のクラス式を検出
   └─ containsClassExpression関数で判定
5. yield/awaitの存在を確認
   └─ t.traverseFastでコンテキスト収集
6. 適切なラッパーを生成
   └─ yieldあり: ジェネレータ関数 + yield*
   └─ awaitあり: async アロー関数 + await
   └─ それ以外: 通常のアロー関数
```

### フローチャート

```mermaid
flowchart TD
    A[Class検出] --> B{プライベート要素あり?}
    B -->|No| Z[処理スキップ]
    B -->|Yes| C[クラスボディ走査]
    C --> D{computedプロパティ?}
    D -->|No| E[次の要素へ]
    D -->|Yes| F[containsClassExpression判定]
    F --> G{クラス式含む?}
    G -->|No| E
    G -->|Yes| H[コンテキスト収集]
    H --> I{yield含む?}
    I -->|Yes| J[ジェネレータ関数でラップ]
    I -->|No| K{await含む?}
    K -->|Yes| L[async関数でラップ]
    K -->|No| M[通常の関数でラップ]
    J --> N[path.replaceWith]
    L --> N
    M --> N
    E --> O{最終要素?}
    O -->|No| D
    O -->|Yes| P[終了]
    N --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | プライベート要素判定 | クラスにプライベート要素がある場合のみ処理 | t.isPrivate(node) |
| BR-02 | 計算キー判定 | computed === true のプロパティ/メソッドのみ対象 | elem.node.computed |
| BR-03 | クラス式検出 | 関数内のクラス式はスキップ | t.isFunction → traverseFast.skip |
| BR-04 | yieldコンテキスト | yieldがある場合はジェネレータ関数を使用 | context.yield === true |
| BR-05 | awaitコンテキスト | awaitがある場合はasync関数を使用 | context.await === true |
| BR-06 | thisとarguments | ジェネレータ関数では.call(this, arguments)で呼び出し | yield使用時 |

### 計算ロジック

- 通常ラップ: `[class {}]` → `[(() => class {})()]`
- awaitあり: `[await class {}]` → `[await (async () => class {})()]`
- yieldあり: `[yield class {}]` → `[yield* (function*() { return yield class {} }).call(this, arguments)]`

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | - | 通常のエラー処理はない（変換のみ） |

### リトライ仕様

リトライ処理は不要（コンパイル時のエラーはリトライ対象外）

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

トランザクション管理は不要（ファイル変換処理のため）

## パフォーマンス要件

- クラス式の検出は軽量なtraverseFastを使用
- 影響を受けるパターンのみ変換を実行

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

- ソースコード変換のため、実行時のセキュリティリスクは限定的
- バグ修正により予期しない動作を防止

## 備考

- Firefoxバグ: [bugzilla.mozilla.org/show_bug.cgi?id=1887677](https://bugzilla.mozilla.org/show_bug.cgi?id=1887677)
- @babel/preset-envで自動的に適用される
- プライベートフィールドがない場合は変換不要

---

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

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

### 推奨読解順序

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

Firefoxバグ修正では、Classノードとそのボディ要素（特に計算プロパティ）が主要なデータ構造となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts` | containsClassExpression関数、wrap関数 |

**読解のコツ**: `t.traverseFast`は軽量なAST走査関数で、`traverseFast.stop`と`traverseFast.skip`で走査を制御できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts` | Classのvisitor |

**主要処理フロー**:
1. **76-80行目**: プライベート要素の存在確認
2. **82-93行目**: 計算プロパティキー内のクラス式検出とラップ実行

#### Step 3: クラス式検出とラップ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts` | containsClassExpression関数（7-22行目）、wrap関数（24-70行目） |

**主要処理フロー**:
- **7-22行目**: containsClassExpression - クラス式の存在判定
- **24-38行目**: wrap関数のコンテキスト収集（yield/await）
- **40-61行目**: yieldありの場合のジェネレータ関数生成
- **63-67行目**: await/通常の場合のアロー関数生成

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

```
@babel/core (transform)
    │
    └─ @babel/plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts
           │
           └─ Class visitor
                  │
                  ├─ hasPrivateElement判定
                  │      └─ body.body.some(t.isPrivate)
                  │
                  ├─ for...of ループ（body.body要素走査）
                  │      │
                  │      ├─ computed判定
                  │      │
                  │      ├─ containsClassExpression
                  │      │      └─ t.traverseFast
                  │      │
                  │      └─ wrap関数
                  │             │
                  │             ├─ コンテキスト収集（yield/await）
                  │             │
                  │             ├─ t.functionExpression（yieldあり）
                  │             │
                  │             └─ t.arrowFunctionExpression（それ以外）
                  │
                  └─ path.replaceWith
```

### データフロー図

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

Class                      プライベート要素確認              Class
class A {                  ───▶                              class A {
  #x;                           計算キーのクラス式検出         #x;
  [class {}] = 1                コンテキスト収集               [(() => class {})()]= 1
}                              ラップ生成                   }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/src/index.ts` | ソース | プラグインエントリーポイント、判定・変換ロジック |
| package.json | `packages/babel-plugin-bugfix-firefox-class-in-computed-class-key/package.json` | 設定 | パッケージ定義・依存関係 |
