# 機能設計書 28-変数代入ライブラリ出力

## 概要

本ドキュメントは、webpackのAssignLibraryPluginによるグローバル変数やオブジェクトプロパティへの代入形式でのライブラリ出力機能について記述する。

### 本機能の処理概要

AssignLibraryPluginは、webpackでバンドルされたライブラリを変数宣言（`var`）やオブジェクトプロパティ代入（`this`, `window`, `self`, `global`）形式で出力する汎用的な機能を提供する。`var`, `assign`, `assign-properties`, `this`, `window`, `self`, `global` の7つのライブラリタイプに対応する。

**業務上の目的・背景**：ブラウザ環境でグローバル変数としてライブラリを公開したり、特定のオブジェクト（`window`, `self`, `this`）のプロパティとして公開するパターンは広く利用されている。`<script>`タグで読み込まれるライブラリの標準的な公開方式を実現する。

**機能の利用シーン**：`output.library.type: 'var'` / `'assign'` / `'assign-properties'` / `'this'` / `'window'` / `'self'` / `'global'` を指定して利用する。`var`は変数宣言、その他はオブジェクトプロパティへの代入となる。

**主要な処理内容**：
1. ライブラリ名とエクスポートオプションをパースする
2. renderメソッドでvar宣言を先頭に追加する（declare="var"の場合のみ）
3. renderStartupメソッドでエクスポート代入コードを生成する
4. プレフィックスとライブラリ名からフルパスを解決し、中間オブジェクトの初期化コードを含む代入文を生成する

**関連システム・外部連携**：EnableLibraryPluginを通じて各タイプが初期化される。commonjsタイプもAssignLibraryPluginで実装されている（No.23参照）。

**権限による制御**：本機能に権限による制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当する画面なし |

## 機能種別

コード生成処理（変数代入形式エクスポートコードの生成）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| library.name | string \| string[] | タイプ依存 | ライブラリ名（ネストパス対応） | var/assign/assign-properties: 必須、その他: 任意 |
| library.export | string \| string[] | No | エクスポートするプロパティ名 | - |
| prefix | string[] \| "global" | - | 代入先プレフィックス | タイプごとに固定 |
| declare | string \| false | - | 変数宣言キーワード | "var" または false |
| unnamed | string | - | 名前なし時の動作 | "error" / "static" / "copy" / "assign" |
| named | string | - | 名前あり時の動作 | "copy" / "assign" |

### 入力データソース

webpack設定の `output.library` オプション。EnableLibraryPluginでタイプに応じたオプションが構成される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| source | ConcatSource | 変数代入付きバンドルソース |

### 出力先

JavascriptModulesPluginのrender/renderStartupフックを通じて、バンドルファイルとして出力される。

## 処理フロー

### 処理シーケンス

```
1. EnableLibraryPluginでのタイプ別初期化
   ├─ var: prefix=[], declare="var", unnamed="error"
   ├─ assign: prefix=[], declare=false, unnamed="error"
   ├─ assign-properties: prefix=[], declare=false, unnamed="error", named="copy"
   ├─ this: prefix=["this"], declare=false, unnamed="copy"
   ├─ window: prefix=["window"], declare=false, unnamed="copy"
   ├─ self: prefix=["self"], declare=false, unnamed="copy"
   └─ global: prefix="global"(→runtimeTemplate.globalObject), declare=false, unnamed="copy"
2. renderでvar宣言追加（declare="var"の場合のみ）
   └─ "var libraryName;\n" を先頭に追加
3. renderStartupでエクスポート代入コード生成
   ├─ fullNameResolved = prefix + name を連結・パステンプレート解決
   ├─ static モード（No.23で記述済み）
   ├─ copy モード: for-inでプロパティコピー
   └─ assign モード: 直接代入
4. accessWithInitで中間オブジェクトの初期化コード生成
   └─ 例: (a = typeof a === "undefined" ? {} : a).b = a.b || {}).c
```

### フローチャート

```mermaid
flowchart TD
    A[renderStartup呼び出し] --> B[fullNameResolved解決]
    B --> C{declare=var?}
    C -->|Yes| D[var宣言追加]
    C -->|No| E[宣言なし]
    D --> F{unnamed/namedモード判定}
    E --> F
    F -->|static| G[個別プロパティ代入 + for-in + __esModule]
    F -->|copy| H[for-inプロパティコピー + __esModule条件]
    F -->|assign| I[accessWithInitで直接代入]
    G --> J[ConcatSource返却]
    H --> J
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | varタイプ名前必須 | var宣言には有効な識別子名が必要 | type='var' |
| BR-02 | 識別子バリデーション | var宣言名は予約語でなく有効なJS識別子であること | declare="var" |
| BR-03 | globalプレフィックス | "global"指定時はruntimeTemplate.globalObjectに解決 | prefix="global" |
| BR-04 | assign-propertiesのcopy | named="copy"で名前付きプロパティコピー | type='assign-properties' |
| BR-05 | accessWithInit初期化 | ネストパスの中間オブジェクトを自動初期化 | ネストパス指定時 |
| BR-06 | embedInRuntimeBailout | トップレベル宣言との競合時にランタイム埋め込みを中止 | topLevelDeclarations競合時 |
| BR-07 | strictRuntimeBailout | strictモードでのグローバル変数作成を警告 | declare=false, prefix空, name未設定 |

### 計算ロジック

accessWithInit関数（54-97行目）：
- 入力: accessor配列（例: `["window", "MyLib", "sub"]`）、existingLength
- 出力: 中間オブジェクト初期化付きのアクセスコード
- 例: `(((window).MyLib = window.MyLib || {}).sub`

isNameValid関数（45-46行目）：
- JavaScript予約語チェック（KEYWORD_REGEX）
- 有効な識別子チェック（IDENTIFIER_REGEX、Unicode対応）

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

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

本機能にデータベース操作はない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | unnamed="error"でname未指定 | "Library name must be a string or string array" |
| - | Error | var宣言でベース名が無効な識別子 | "Library name base must be a valid identifier" |

### リトライ仕様

リトライ処理はない。

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

トランザクション管理はない。

## パフォーマンス要件

エクスポートコード生成はコンパイル時処理であり、パフォーマンスへの影響は軽微。

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

グローバル変数への代入はグローバルスコープ汚染のリスクがある。命名規則に注意が必要。

## 備考

- AssignLibraryPluginは最も汎用的なライブラリプラグインであり、7つのタイプ + commonjs系4タイプの計11タイプに対応する
- `assign-properties` は `assign` と異なり、既存のオブジェクトにプロパティをコピーする（破壊的でない）
- `global` プレフィックスはビルドターゲットに応じて `globalThis`, `window`, `self`, `global` などに解決される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | AssignLibraryPluginOptions型（102-108行目） |
| 1-2 | AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | KEYWORD_REGEX/IDENTIFIER_REGEX（36-38行目）- 識別子バリデーション |
| 1-3 | AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | accessWithInit関数（54-97行目）- 中間オブジェクト初期化 |

**読解のコツ**: accessWithInit関数は本プラグインの核心部分。ネストされたプロパティアクセスで中間オブジェクトを`||{}`で初期化するパターンを理解することが重要。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EnableLibraryPlugin.js | `lib/library/EnableLibraryPlugin.js` | 99-183行目: var/assign/assign-properties/this/window/self/global の全構成 |

**主要処理フロー**:
1. **99-109行目**: `case 'var':` - prefix=[], declare="var", unnamed="error"
2. **111-122行目**: `case 'assign-properties':` - named="copy" が特徴
3. **124-134行目**: `case 'assign':` - declare=false
4. **136-183行目**: this/window/self/global - prefix=[targetObject], unnamed="copy"

#### Step 3: レンダリング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | 228-248行目: renderメソッド（var宣言） |
| 3-2 | AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | 303-406行目: renderStartupメソッド（エクスポート代入） |

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

```
EnableLibraryPlugin.apply()
    │
    └─ AssignLibraryPlugin(タイプ別オプション).apply()
           │
           ├─ AbstractLibraryPlugin.apply()
           │      ├─ hooks.finishModules.tap() ──▶ finishEntryModule()
           │      ├─ hooks.render.tap() ──▶ render() [var宣言追加]
           │      ├─ hooks.renderStartup.tap() ──▶ renderStartup() [代入コード]
           │      ├─ hooks.embedInRuntimeBailout.tap()
           │      └─ hooks.strictRuntimeBailout.tap()
           │
           ├─ _getPrefix() - プレフィックス解決（"global"→globalObject）
           ├─ _getResolvedFullName() - prefix + name を連結
           │
           └─ renderStartup()
                  ├─ accessWithInit() - 中間オブジェクト初期化コード
                  ├─ static/copy/assign モード分岐
                  └─ ConcatSource生成
```

### データフロー図

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

library.type ──────────────▶ EnableLibraryPlugin ──────▶ prefix/declare/unnamed
    (var/this/window等)         (オプション決定)

library.name ──────────────▶ _getResolvedFullName() ──▶ fullNameResolved
prefix ────────────────────▶    (パス結合・テンプレート解決)    ["window","MyLib"]

fullNameResolved ──────────▶ accessWithInit() ─────────▶ 初期化付きアクセスコード
                               (中間オブジェクト初期化)

ソースコード ──────────────▶ renderStartup() ───────────▶ 代入コード付きバンドル
                               (static/copy/assign)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AssignLibraryPlugin.js | `lib/library/AssignLibraryPlugin.js` | ソース | 変数代入型ライブラリ出力の汎用実装 |
| AbstractLibraryPlugin.js | `lib/library/AbstractLibraryPlugin.js` | ソース | ライブラリプラグインの基底クラス |
| EnableLibraryPlugin.js | `lib/library/EnableLibraryPlugin.js` | ソース | タイプに応じたAssignLibraryPluginの構成 |
| ExportPropertyLibraryPlugin.js | `lib/library/ExportPropertyLibraryPlugin.js` | ソース | 特定エクスポートの抽出 |
| RuntimeGlobals.js | `lib/RuntimeGlobals.js` | ソース | ランタイムグローバル変数名定義 |
