# 機能設計書 49-ランタイムモジュール群

## 概要

本ドキュメントは、webpackのランタイムモジュール群(lib/runtime/配下)について設計内容を記述する。これらのモジュールは、チャンク読み込み・パス解決・ハッシュ取得・スクリプト読み込み・モジュール互換性処理等のランタイムコードを生成する。

### 本機能の処理概要

本機能は、31以上のランタイムモジュールクラスにより、webpackバンドルの実行に必要な各種ランタイムヘルパーコードを生成する。各ランタイムモジュールはRuntimeModuleまたはHelperRuntimeModuleを継承し、generate()メソッドでランタイムJavaScriptコードの文字列を返す。

**業務上の目的・背景**：webpackバンドルの実行時には、モジュール読み込み・エクスポート処理・チャンク管理・パス解決等の様々なヘルパー関数が必要である。これらを個別のランタイムモジュールとして分離することで、実際に使用される機能のみをバンドルに含めることができる。

**機能の利用シーン**：コンパイル時にruntimeRequirementsとして必要なランタイム機能が検出されると、対応するランタイムモジュールが自動的にチャンクに追加される。

**主要な処理内容**：
1. EnsureChunkRuntimeModule: __webpack_require__.e によるチャンク読み込みオーケストレーション
2. GetChunkFilenameRuntimeModule: チャンクファイル名の動的生成
3. LoadScriptRuntimeModule: scriptタグベースのスクリプト読み込み
4. PublicPathRuntimeModule / AutoPublicPathRuntimeModule: publicPathの設定・自動検出
5. DefinePropertyGettersRuntimeModule: ESMエクスポートのgetter定義
6. MakeNamespaceObjectRuntimeModule: __esModule マーカーの設定
7. HasOwnPropertyRuntimeModule: Object.hasOwnPropertyショートハンド
8. CompatGetDefaultExportRuntimeModule: 非ESMモジュールのデフォルトエクスポート互換
9. CreateFakeNamespaceObjectRuntimeModule: 名前空間オブジェクトの生成
10. OnChunksLoadedRuntimeModule: チャンク読み込み完了コールバック管理
11. AsyncModuleRuntimeModule: 非同期モジュール(Top-Level Await)サポート
12. StartupChunkDependenciesRuntimeModule: 起動時チャンク依存関係読み込み
13. StartupEntrypointRuntimeModule: エントリポイント起動処理
14. GlobalRuntimeModule: クロスプラットフォームグローバルオブジェクト取得
15. GetFullHashRuntimeModule: ビルドハッシュ取得

**関連システム・外部連携**：RuntimeGlobals(グローバル変数名定義)、RuntimeModule基底クラス、HelperRuntimeModule基底クラス

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面との直接的な関連なし（内部ランタイム基盤） |

## 機能種別

ランタイムコード生成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| runtimeRequirements | ReadOnlyRuntimeRequirements | Yes | 必要なランタイム機能のセット | - |
| compilation | Compilation | Yes | コンパイルインスタンス(attach時に設定) | - |
| chunk | Chunk | Yes | 所属チャンク(attach時に設定) | - |
| chunkGraph | ChunkGraph | Yes | チャンクグラフ(attach時に設定) | - |

### 入力データソース

- compilation.hooks.runtimeRequirementInTree フック経由のランタイム要件

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ランタイムコード | string \| null | 各ランタイムモジュールのJavaScriptコード |

### 出力先

- webpackランタイムバンドル内の各チャンク

## 処理フロー

### 処理シーケンス

```
1. RuntimeModule基底クラス
   +-- constructor(name, stage): モジュール名とステージを設定
   +-- attach(compilation, chunk, chunkGraph): コンパイルコンテキスト設定
   +-- generate(): ランタイムコードを文字列として返す(サブクラスで実装)

2. ランタイムモジュール分類
   +-- [STAGE_BASIC] PublicPathRuntimeModule, AutoPublicPathRuntimeModule
   +-- [STAGE_NORMAL(0)] EnsureChunkRuntimeModule, DefinePropertyGettersRuntimeModule 等
   +-- [STAGE_ATTACH] チャンクローディング系RuntimeModule
   +-- [STAGE_TRIGGER] StartupChunkDependenciesRuntimeModule

3. 各ランタイムモジュールのgenerate()
   +-- Template.asString()でコード文字列を生成
   +-- runtimeTemplate.basicFunction()等で環境適応コードを生成
   +-- RuntimeGlobals定数でグローバル変数名を参照
```

### フローチャート

```mermaid
flowchart TD
    A[コンパイル] --> B[runtimeRequirements検出]
    B --> C[必要なランタイムモジュールを追加]
    C --> D[RuntimeModule.attach]
    D --> E[RuntimeModule.generate]
    E --> F{ステージ順にソート}
    F --> G[STAGE_BASIC: publicPath等]
    F --> H[STAGE_NORMAL: 汎用ヘルパー]
    F --> I[STAGE_ATTACH: チャンクローディング]
    F --> J[STAGE_TRIGGER: スタートアップ]
    G --> K[ランタイムコード結合]
    H --> K
    I --> K
    J --> K
    K --> L[バンドル出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-49-01 | 必要最小限の原則 | runtimeRequirementsに含まれるもののみランタイムに含める | 常時 |
| BR-49-02 | ステージ順序 | STAGE_BASIC -> STAGE_NORMAL -> STAGE_ATTACH -> STAGE_TRIGGERの順でコード生成 | 常時 |
| BR-49-03 | 環境適応 | runtimeTemplateを使用して出力環境に応じたコード(arrow function, const等)を生成 | 常時 |
| BR-49-04 | ヘルパー分離 | HelperRuntimeModuleはヘルパーレジストリに登録され、重複を防止 | Helper系モジュール |
| BR-49-05 | ハッシュ依存 | fullHash=trueのモジュールはビルドハッシュに依存し、ハッシュ変更時に再生成 | GetFullHashRuntimeModule等 |

### 計算ロジック

- AutoPublicPath: `scriptUrl.replace(/^blob:/, "").replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/")` + undoPath
- GlobalObject: `globalThis || this || new Function('return this')() || window`

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | AutoPublicPath: scriptUrl検出不可 | "Automatic publicPath is not supported in this browser" |
| - | Error | LoadScript: スクリプト読み込みタイムアウト | timeout後にonScriptCompleteでエラーハンドリング |
| - | Error | HMRマニフェスト: fetch失敗 | "No browser support: need fetch API" |

### リトライ仕様

リトライは行わない。LoadScriptRuntimeModuleのタイムアウトはchunkLoadTimeout設定で制御。

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

該当なし

## パフォーマンス要件

- 必要最小限のランタイムモジュールのみバンドルに含めることで出力サイズを最適化
- LoadScriptRuntimeModuleはinProgressマップで同一URLの重複読み込みを防止
- GetChunkFilenameRuntimeModuleはstaticUrlsとdynamicUrlの分離で最適なコード生成

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

- LoadScriptRuntimeModule: scriptNonce属性によるCSP(Content Security Policy)対応
- LoadScriptRuntimeModule: crossOriginLoading設定によるCORS制御
- AutoPublicPathRuntimeModule: document.currentScriptのtagNameチェックでスクリプト注入攻撃を防止
- CreateScriptUrlRuntimeModule: Trusted Types対応のURLサニタイズ

## 備考

- RuntimeModuleのstage定数: STAGE_NORMAL=0, STAGE_BASIC=5, STAGE_ATTACH=10, STAGE_TRIGGER=20
- HelperRuntimeModuleはRuntimeModuleを継承し、ヘルパー関数の登録・重複排除を管理
- 全ランタイムモジュールはidentifier()で`webpack/runtime/{name}`を返す

---

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

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

### 推奨読解順序

#### Step 1: 基底クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RuntimeModule.js | `lib/RuntimeModule.js` | **37-64行目**: コンストラクタ。name, stage, fullHash, dependentHash等のプロパティ |
| 1-2 | RuntimeModule.js | `lib/RuntimeModule.js` | **72-76行目**: attach()メソッド。compilation, chunk, chunkGraphの設定 |
| 1-3 | RuntimeModule.js | `lib/RuntimeModule.js` | **81-83行目**: identifier()。`webpack/runtime/{name}`形式の一意識別子 |

#### Step 2: チャンク読み込みオーケストレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EnsureChunkRuntimeModule.js | `lib/runtime/EnsureChunkRuntimeModule.js` | **27-66行目**: generate()全体。ensureChunkHandlersの有無で分岐 |
| 2-2 | EnsureChunkRuntimeModule.js | `lib/runtime/EnsureChunkRuntimeModule.js` | **36-54行目**: ensureChunkHandlers存在時のPromise.all + reduce実装 |
| 2-3 | EnsureChunkRuntimeModule.js | `lib/runtime/EnsureChunkRuntimeModule.js` | **58-65行目**: ハンドラ不存在時のPromise.resolve()返却 |

#### Step 3: スクリプト読み込みを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LoadScriptRuntimeModule.js | `lib/runtime/LoadScriptRuntimeModule.js` | **23-42行目**: 静的コンパイルフック(createScript)の管理 |
| 3-2 | LoadScriptRuntimeModule.js | `lib/runtime/LoadScriptRuntimeModule.js` | **59-171行目**: generate()メソッド全体 |
| 3-3 | LoadScriptRuntimeModule.js | `lib/runtime/LoadScriptRuntimeModule.js` | **74-111行目**: script要素の生成コード(type, charset, nonce, fetchPriority, src, crossOrigin) |
| 3-4 | LoadScriptRuntimeModule.js | `lib/runtime/LoadScriptRuntimeModule.js` | **114-169行目**: inProgressマップによる重複防止、タイムアウト、onerror/onloadハンドリング |

#### Step 4: パス解決を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PublicPathRuntimeModule.js | `lib/runtime/PublicPathRuntimeModule.js` | **26-34行目**: 静的publicPathの設定 |
| 4-2 | AutoPublicPathRuntimeModule.js | `lib/runtime/AutoPublicPathRuntimeModule.js` | **24-87行目**: scriptUrl自動検出(import.meta.url, importScripts, document.currentScript) |
| 4-3 | GetChunkFilenameRuntimeModule.js | `lib/runtime/GetChunkFilenameRuntimeModule.js` | **44-296行目**: チャンクファイル名テンプレートからURL生成コードを構築 |

#### Step 5: ESMヘルパーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | DefinePropertyGettersRuntimeModule.js | `lib/runtime/DefinePropertyGettersRuntimeModule.js` | **21-39行目**: Object.definePropertyによるgetter定義 |
| 5-2 | MakeNamespaceObjectRuntimeModule.js | `lib/runtime/MakeNamespaceObjectRuntimeModule.js` | **21-37行目**: Symbol.toStringTagとesModuleマーカー設定 |
| 5-3 | CreateFakeNamespaceObjectRuntimeModule.js | `lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js` | **21-66行目**: modeビットフラグによる名前空間オブジェクト生成 |
| 5-4 | CompatGetDefaultExportRuntimeModule.js | `lib/runtime/CompatGetDefaultExportRuntimeModule.js` | **21-38行目**: ESM/CJS互換デフォルトエクスポート |
| 5-5 | HasOwnPropertyRuntimeModule.js | `lib/runtime/HasOwnPropertyRuntimeModule.js` | **22-33行目**: Object.prototype.hasOwnCallのショートハンド |

#### Step 6: チャンク完了・非同期処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | OnChunksLoadedRuntimeModule.js | `lib/runtime/OnChunksLoadedRuntimeModule.js` | **21-75行目**: deferred配列による優先度付きチャンク完了コールバック |
| 6-2 | AsyncModuleRuntimeModule.js | `lib/runtime/AsyncModuleRuntimeModule.js` | **26-196行目**: Top-Level Awaitサポート。キュー管理・依存解決・Promise連鎖 |
| 6-3 | StartupChunkDependenciesRuntimeModule.js | `lib/runtime/StartupChunkDependenciesRuntimeModule.js` | **29-74行目**: 起動時依存チャンクの同期/非同期読み込み |
| 6-4 | StartupEntrypointRuntimeModule.js | `lib/runtime/StartupEntrypointRuntimeModule.js` | **25-52行目**: エントリポイント起動関数 |

#### Step 7: その他ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | GlobalRuntimeModule.js | `lib/runtime/GlobalRuntimeModule.js` | **19-44行目**: クロスプラットフォームglobalThis検出 |
| 7-2 | GetFullHashRuntimeModule.js | `lib/runtime/GetFullHashRuntimeModule.js` | **22-28行目**: ビルドハッシュ返却関数 |

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

```
Compilation
    |
    +-- hooks.runtimeRequirementInTree
    |       +-- RuntimePlugin.handler()
    |               +-- compilation.addRuntimeModule(chunk, runtimeModule)
    |                       +-- RuntimeModule.attach(compilation, chunk, chunkGraph)
    |
    +-- codeGeneration
            +-- RuntimeModule.generate()
                    |
                    +-- [STAGE_BASIC=5]
                    |       +-- PublicPathRuntimeModule.generate()
                    |       +-- AutoPublicPathRuntimeModule.generate()
                    |
                    +-- [STAGE_NORMAL=0]
                    |       +-- EnsureChunkRuntimeModule.generate()
                    |       +-- DefinePropertyGettersRuntimeModule.generate()
                    |       +-- MakeNamespaceObjectRuntimeModule.generate()
                    |       +-- HasOwnPropertyRuntimeModule.generate()
                    |       +-- CompatGetDefaultExportRuntimeModule.generate()
                    |       +-- CreateFakeNamespaceObjectRuntimeModule.generate()
                    |       +-- OnChunksLoadedRuntimeModule.generate()
                    |       +-- AsyncModuleRuntimeModule.generate()
                    |       +-- GlobalRuntimeModule.generate()
                    |       +-- GetFullHashRuntimeModule.generate()
                    |       +-- GetChunkFilenameRuntimeModule.generate()
                    |       +-- StartupEntrypointRuntimeModule.generate()
                    |
                    +-- [STAGE_ATTACH=10]
                    |       +-- LoadScriptRuntimeModule.generate()
                    |
                    +-- [STAGE_TRIGGER=20]
                            +-- StartupChunkDependenciesRuntimeModule.generate()
```

### データフロー図

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

runtimeRequirements  ----->  RuntimePlugin                  ----->  RuntimeModule群
                             +-- 必要なモジュールを判定
                             +-- compilation.addRuntimeModule()

RuntimeModule群      ----->  RuntimeModule.generate()        ----->  ランタイムコード(string)
                             +-- Template.asString()
                             +-- runtimeTemplate.basicFunction()
                             +-- RuntimeGlobals.*

ランタイムコード     ----->  JavascriptModulesPlugin        ----->  バンドルファイル
                             +-- ランタイムコード結合
                             +-- チャンクファイル出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RuntimeModule.js | `lib/RuntimeModule.js` | ソース | ランタイムモジュール基底クラス |
| HelperRuntimeModule.js | `lib/runtime/HelperRuntimeModule.js` | ソース | ヘルパーランタイムモジュール基底クラス |
| EnsureChunkRuntimeModule.js | `lib/runtime/EnsureChunkRuntimeModule.js` | ソース | チャンク読み込みオーケストレーション |
| GetChunkFilenameRuntimeModule.js | `lib/runtime/GetChunkFilenameRuntimeModule.js` | ソース | チャンクファイル名生成 |
| LoadScriptRuntimeModule.js | `lib/runtime/LoadScriptRuntimeModule.js` | ソース | scriptタグによるスクリプト読み込み |
| PublicPathRuntimeModule.js | `lib/runtime/PublicPathRuntimeModule.js` | ソース | 静的publicPath設定 |
| AutoPublicPathRuntimeModule.js | `lib/runtime/AutoPublicPathRuntimeModule.js` | ソース | 自動publicPath検出 |
| DefinePropertyGettersRuntimeModule.js | `lib/runtime/DefinePropertyGettersRuntimeModule.js` | ソース | ESMエクスポートgetter定義 |
| MakeNamespaceObjectRuntimeModule.js | `lib/runtime/MakeNamespaceObjectRuntimeModule.js` | ソース | ESM名前空間マーカー設定 |
| HasOwnPropertyRuntimeModule.js | `lib/runtime/HasOwnPropertyRuntimeModule.js` | ソース | hasOwnPropertyショートハンド |
| CompatGetDefaultExportRuntimeModule.js | `lib/runtime/CompatGetDefaultExportRuntimeModule.js` | ソース | デフォルトエクスポート互換 |
| CreateFakeNamespaceObjectRuntimeModule.js | `lib/runtime/CreateFakeNamespaceObjectRuntimeModule.js` | ソース | 名前空間オブジェクト生成 |
| OnChunksLoadedRuntimeModule.js | `lib/runtime/OnChunksLoadedRuntimeModule.js` | ソース | チャンク読み込み完了コールバック |
| AsyncModuleRuntimeModule.js | `lib/runtime/AsyncModuleRuntimeModule.js` | ソース | Top-Level Awaitサポート |
| StartupChunkDependenciesRuntimeModule.js | `lib/runtime/StartupChunkDependenciesRuntimeModule.js` | ソース | 起動チャンク依存関係 |
| StartupChunkDependenciesPlugin.js | `lib/runtime/StartupChunkDependenciesPlugin.js` | ソース | 起動チャンク依存関係プラグイン |
| StartupEntrypointRuntimeModule.js | `lib/runtime/StartupEntrypointRuntimeModule.js` | ソース | エントリポイント起動 |
| GlobalRuntimeModule.js | `lib/runtime/GlobalRuntimeModule.js` | ソース | グローバルオブジェクト取得 |
| GetFullHashRuntimeModule.js | `lib/runtime/GetFullHashRuntimeModule.js` | ソース | ビルドハッシュ取得 |
| BaseUriRuntimeModule.js | `lib/runtime/BaseUriRuntimeModule.js` | ソース | ベースURI設定 |
| ChunkNameRuntimeModule.js | `lib/runtime/ChunkNameRuntimeModule.js` | ソース | チャンク名取得 |
| RuntimeIdRuntimeModule.js | `lib/runtime/RuntimeIdRuntimeModule.js` | ソース | ランタイムID取得 |
| NonceRuntimeModule.js | `lib/runtime/NonceRuntimeModule.js` | ソース | CSPノンス管理 |
| CreateScriptRuntimeModule.js | `lib/runtime/CreateScriptRuntimeModule.js` | ソース | スクリプト要素生成 |
| CreateScriptUrlRuntimeModule.js | `lib/runtime/CreateScriptUrlRuntimeModule.js` | ソース | Trusted Types対応URL生成 |
| GetTrustedTypesPolicyRuntimeModule.js | `lib/runtime/GetTrustedTypesPolicyRuntimeModule.js` | ソース | Trusted Typesポリシー取得 |
| CompatRuntimeModule.js | `lib/runtime/CompatRuntimeModule.js` | ソース | 互換性ランタイム |
| RelativeUrlRuntimeModule.js | `lib/runtime/RelativeUrlRuntimeModule.js` | ソース | 相対URL解決 |
| SystemContextRuntimeModule.js | `lib/runtime/SystemContextRuntimeModule.js` | ソース | System.jsコンテキスト |
| GetMainFilenameRuntimeModule.js | `lib/runtime/GetMainFilenameRuntimeModule.js` | ソース | メインファイル名取得 |
| ToBinaryRuntimeModule.js | `lib/runtime/ToBinaryRuntimeModule.js` | ソース | バイナリ変換ユーティリティ |
| MakeDeferredNamespaceObjectRuntime.js | `lib/runtime/MakeDeferredNamespaceObjectRuntime.js` | ソース | 遅延名前空間オブジェクト生成 |
