# 機能設計書 67-@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining

## 概要

本ドキュメントは、V8エンジンのオプショナルチェイニングとスプレッドパラメータに関するバグを修正するプラグイン `@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining` の機能設計を定義する。

### 本機能の処理概要

本プラグインは、V8 JavaScript エンジン（Chrome/Node.js）に存在するバグ（[crbug.com/v8/11558](https://crbug.com/v8/11558)）に対するワークアラウンドを提供する。このバグは、オプショナルチェイニング演算子（`?.`）と組み合わせてスプレッドパラメータを使用した場合に発生する。

**業務上の目的・背景**：V8エンジンでは、`f?.(...args, 0)` や `o?.m(...args, 0)` のようなパターンで誤った動作が発生する。このバグは特定のV8バージョンで修正されているが、古いブラウザやNode.jsバージョンをサポートする場合に問題となる。本プラグインは影響を受けるパターンを検出し、安全なコードに変換する。

**機能の利用シーン**：
- 古いChrome/Node.jsバージョンをサポートする必要があるアプリケーション
- @babel/preset-envのtargets設定で影響を受けるブラウザが含まれる場合
- オプショナルチェイニングとスプレッド演算子を組み合わせて使用するコード

**主要な処理内容**：
1. OptionalCallExpressionまたはOptionalMemberExpressionを検出
2. スプレッド要素の後に他の引数があるパターンを判定
3. 影響を受けるパターンに対して`@babel/plugin-transform-optional-chaining`の変換を適用

**関連システム・外部連携**：`@babel/plugin-transform-optional-chaining`のtransform関数を使用してオプショナルチェイニングを変換する。

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

## 関連画面

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

## 機能種別

バグ修正処理（AST変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | オプションパラメータはない（assumptionは内部使用） | - |

### assumptions

| assumption名 | 型 | デフォルト | 説明 |
|-------------|-----|---------|------|
| noDocumentAll | boolean | false | document.allをnullとして扱う |
| pureGetters | boolean | false | ゲッターに副作用がないと仮定 |

### 入力データソース

- ソースコードからのASTノード（OptionalCallExpression、OptionalMemberExpression）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| transformedAST | AST Node | 変換後のAST（条件式に変換されたオプショナルチェイン） |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. OptionalCallExpression/OptionalMemberExpression訪問
   └─ shouldTransform関数で変換が必要か判定
2. オプショナルチェインの走査
   └─ skipTransparentExprWrappersでラッパーをスキップ
   └─ チェーン内の全ノードを収集
3. 影響パターンの判定
   └─ matchAffectedArgumentsでスプレッド+後続引数を検出
   └─ optional属性または親のoptional MemberExpressionを確認
4. 変換実行
   └─ shouldTransformがtrueの場合のみ変換
   └─ @babel/plugin-transform-optional-chainingのtransformを呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[Optional式検出] --> B[shouldTransform判定]
    B --> C[オプショナルチェーン走査]
    C --> D[チェーン内ノード収集]
    D --> E{OptionalCallExpression?}
    E -->|No| F[次のノードへ]
    E -->|Yes| G[matchAffectedArguments]
    G --> H{スプレッド後に引数あり?}
    H -->|No| F
    H -->|Yes| I{node.optional === true?}
    I -->|Yes| J[変換が必要]
    I -->|No| K{親がoptional MemberExpression?}
    K -->|Yes| J
    K -->|No| F
    F --> L{チェーン終了?}
    L -->|No| E
    L -->|Yes| M{変換が必要?}
    M -->|Yes| N[transform実行]
    M -->|No| O[スキップ]
    J --> M
    N --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | スプレッド位置判定 | スプレッド要素の後に他の引数がある場合のみ影響 | arguments配列内 |
| BR-02 | optional判定 | node.optionalがtrueまたは親がoptional MemberExpression | OptionalCallExpression |
| BR-03 | チェーン走査 | オプショナルチェーン全体を走査して影響パターンを検出 | OptionalExpression |
| BR-04 | 変換委譲 | 変換処理は@babel/plugin-transform-optional-chainingに委譲 | shouldTransform === true |

### 計算ロジック

- 影響パターン: `f?.(...args, 0)` → スプレッドのインデックスが最後でない
- 非影響パターン: `f?.(...args)` → スプレッドが最後の引数
- 連鎖パターン: `o?.m(...args, 0)` → 親がoptional MemberExpression

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

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

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

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

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

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

## パフォーマンス要件

- オプショナルチェーンの走査は軽量
- 影響を受けるパターンのみ変換を実行

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

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

## 備考

- V8バグ: [crbug.com/v8/11558](https://crbug.com/v8/11558)
- @babel/preset-envで自動的に適用される
- 新しいV8バージョンでは修正済み

---

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

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

### 推奨読解順序

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

バグ修正プラグインでは、OptionalCallExpressionとOptionalMemberExpressionの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | util.ts | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/util.ts` | shouldTransform関数、matchAffectedArguments関数 |

**読解のコツ**: `matchAffectedArguments`関数でスプレッド要素の位置を判定するロジックを理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/index.ts` | visitor定義とtransform呼び出し |

**主要処理フロー**:
1. **9-10行目**: assumptions（noDocumentAll、pureGetters）の取得
2. **15-17行目**: OptionalCallExpression|OptionalMemberExpressionのvisitor
3. **18-20行目**: shouldTransform判定とtransform呼び出し

#### Step 3: 判定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | util.ts | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/util.ts` | オプショナルチェーン走査とパターンマッチング |

**主要処理フロー**:
- **8-11行目**: matchAffectedArguments - スプレッド位置の判定
- **21-56行目**: shouldTransform - 変換が必要かの総合判定
- **26-36行目**: チェーン走査ループ
- **37-53行目**: 影響パターンの判定

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

```
@babel/core (transform)
    │
    └─ @babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/index.ts
           │
           ├─ OptionalCallExpression|OptionalMemberExpression visitor
           │      │
           │      ├─ shouldTransform (util.ts)
           │      │      │
           │      │      ├─ skipTransparentExprWrappers
           │      │      │
           │      │      ├─ チェーン走査ループ
           │      │      │
           │      │      └─ matchAffectedArguments
           │      │
           │      └─ transform (@babel/plugin-transform-optional-chaining)
           │
           └─ assumptions (noDocumentAll, pureGetters)
```

### データフロー図

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

OptionalCallExpression     shouldTransform判定              条件式
f?.(...args, 0)     ───▶   matchAffectedArguments    ───▶  (_f = f) == null
                           チェーン走査                      ? void 0
                           transform呼び出し                 : _f.apply(...)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/index.ts` | ソース | プラグインエントリーポイント |
| util.ts | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/src/util.ts` | ソース | 判定ロジック |
| package.json | `packages/babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining/package.json` | 設定 | パッケージ定義・依存関係 |
