# 機能設計書 37-@babel/plugin-transform-logical-assignment-operators

## 概要

本ドキュメントは、Babelの変換プラグイン「@babel/plugin-transform-logical-assignment-operators」の機能設計を記述する。本プラグインはES2021の論理代入演算子（`&&=`、`||=`、`??=`）を、古いJavaScript環境でも動作する形式に変換する。

### 本機能の処理概要

本プラグインは、論理代入演算子（`&&=`、`||=`、`??=`）を検出し、論理式と代入式の組み合わせに変換する機能を提供する。これにより、ES2021以前の環境でも論理代入の短絡評価セマンティクスを実現できる。

**業務上の目的・背景**：ES2021で導入された論理代入演算子は、条件付き代入を簡潔に記述できる機能である。`a ||= b`は「aがfalsyならbを代入」、`a &&= b`は「aがtruthyならbを代入」、`a ??= b`は「aがnull/undefinedならbを代入」という意味を持つ。古いブラウザやNode.jsバージョンではこの演算子をサポートしていないため、トランスパイルが必要となる。

**機能の利用シーン**：
- デフォルト値の設定
- 条件付きプロパティの更新
- `@babel/preset-env`の一部として自動的に適用される場合

**主要な処理内容**：
1. AssignmentExpression（operator: "&&=", "||=", "??="）を検出
2. 論理式（LogicalExpression）と代入式の組み合わせに変換
3. MemberExpression左辺の場合、オブジェクトとプロパティをメモ化して二重評価を防止
4. 短絡評価のセマンティクスを維持

**関連システム・外部連携**：
- `@babel/helper-plugin-utils`: プラグインユーティリティ
- `@babel/core`: Babelコアとの統合

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

## 関連画面

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

## 機能種別

コード変換処理 / AST操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| - | - | - | オプションなし | - |

### 入力データソース

- Babelによってパースされたソースコード（AST形式）
- AssignmentExpression（operator: "&&=", "||=", "??="）

## 出力仕様

### 出力データ

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

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化

2. AssignmentExpressionの処理
   ├─ operatorから論理演算子部分を抽出（"&&=", "||=", "??=" → "&&", "||", "??"）
   ├─ LOGICAL_OPERATORSに含まれるかチェック
   ├─ 左辺をクローン
   ├─ MemberExpressionの場合
   │      ├─ オブジェクトのメモ化
   │      └─ 計算プロパティの場合はプロパティもメモ化
   └─ LogicalExpression(operator, lhs, AssignmentExpression("=", left, right))に変換
```

### フローチャート

```mermaid
flowchart TD
    A[AssignmentExpressionの訪問] --> B{論理代入演算子?}
    B -->|No| Z[変換なし]
    B -->|Yes| C[演算子から論理演算子を抽出]
    C --> D{左辺がMemberExpression?}
    D -->|Yes| E{計算プロパティ?}
    D -->|No| F[単純に変換]
    E -->|Yes| G[オブジェクトとプロパティをメモ化]
    E -->|No| H[オブジェクトのみメモ化]
    G --> I[LogicalExpressionに変換]
    H --> I
    F --> I
    I --> J[変換完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | 短絡評価の維持 | 論理演算子の短絡評価セマンティクスを維持 | 常時 |
| BR-37-02 | 二重評価防止 | MemberExpression左辺のオブジェクト・プロパティをメモ化 | 左辺がMemberExpression時 |
| BR-37-03 | 演算子変換 | "&&=" → "&&", "||=" → "||", "??=" → "??" | 常時 |

### 計算ロジック

- 変換: `a &&= b` → `a && (a = b)`
- 変換: `a ||= b` → `a || (a = b)`
- 変換: `a ??= b` → `a ?? (a = b)`
- 変換: `obj.prop ||= b` → `(_obj = obj).prop || (_obj.prop = b)`

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | SyntaxError | 不正な論理代入演算子構文 | パーサーレベルでエラー |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 変換処理は同期的に実行される
- メモ化により実行時の二重評価を防止

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

- 特になし

## 備考

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

---

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

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

### 推奨読解順序

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

本プラグインはAssignmentExpression（論理代入演算子）をLogicalExpressionに変換する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-plugin-transform-logical-assignment-operators/src/index.ts` | シンプルな構造。AssignmentExpression visitorのみ |

**読解のコツ**: 本プラグインは比較的シンプルで、1ファイルで完結している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-plugin-transform-logical-assignment-operators/src/index.ts` | AssignmentExpression visitorの実装 |

**主要処理フロー**:
1. **1-2行目**: 必要なモジュールのインポート
2. **4-5行目**: APIバージョン検証
3. **10-17行目**: 演算子のチェックと論理演算子の抽出
4. **19行目**: 左辺のクローン
5. **20-44行目**: MemberExpressionの場合のメモ化処理
6. **47-54行目**: LogicalExpressionへの変換

#### Step 3: メモ化ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts (20-44行目) | `packages/babel-plugin-transform-logical-assignment-operators/src/index.ts` | MemberExpression左辺のメモ化処理 |

**主要処理フロー**:
- **20-31行目**: オブジェクトのメモ化
- **22行目**: scope.maybeGenerateMemoised(object)でメモ化必要性判定
- **33-44行目**: 計算プロパティの場合のプロパティメモ化

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

```
@babel/plugin-transform-logical-assignment-operators/src/index.ts
    │
    └─ visitor.AssignmentExpression()
           │
           ├─ operator.slice(0, -1) で論理演算子抽出
           │
           ├─ t.LOGICAL_OPERATORS.includes() チェック
           │
           ├─ t.cloneNode(left) で左辺クローン
           │
           ├─ MemberExpression の場合
           │      ├─ scope.maybeGenerateMemoised(object)
           │      └─ scope.maybeGenerateMemoised(property)
           │
           └─ t.logicalExpression(operator, lhs, assignment)
```

### データフロー図

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

a ||= b             ─▶  AssignmentExpression       ─▶  a || (a = b)
                         visitor

obj.prop &&= val    ─▶  AssignmentExpression       ─▶  (_obj = obj).prop &&
                         visitor                        (_obj.prop = val)
                              │
                              └─ maybeGenerateMemoised()
```

### 関連ファイル一覧

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