# 機能設計書 50-ランタイムテンプレート

## 概要

本ドキュメントは、RuntimeTemplateクラスによるランタイムコードのテンプレート化・環境依存コード生成機能について設計内容を記述する。

### 本機能の処理概要

本機能は、RuntimeTemplateクラスを通じて、出力環境(ES5/ES6/ESM等)に応じたランタイムJavaScriptコードのテンプレート生成を提供する。arrow function、const、テンプレートリテラル、分割代入等のES6+構文の利用可否をoutputOptions.environmentに基づいて判定し、適切な構文のコードを生成する。

**業務上の目的・背景**：webpackの出力コードは、ターゲット環境のJavaScript仕様レベルに応じて適切な構文を使用する必要がある。ES5環境では`function`キーワードや`var`宣言を使用し、ES6+環境では`=>`やa`const`を使用する。この環境適応ロジックを一元管理するのがRuntimeTemplateの役割である。

**機能の利用シーン**：ランタイムモジュールのgenerate()メソッド内、およびコード生成(CodeGeneration)処理内で使用される。compilation.runtimeTemplateとしてアクセス可能。

**主要な処理内容**：
1. 環境判定メソッド群: supportsArrowFunction(), supportsConst(), supportsDestructuring()等
2. コード生成ヘルパー: basicFunction(), returningFunction(), expressionFunction(), destructureArray()等
3. モジュール参照コード生成: moduleId(), moduleRaw(), moduleNamespace(), moduleNamespacePromise()
4. インポート文生成: importStatement(), exportFromImport()
5. ブロックPromise生成: blockPromise()
6. テンプレートリテラル/文字列結合の最適化: concatenation()

**関連システム・外部連携**：Compilation、Template(静的コード結合ユーティリティ)、RuntimeGlobals

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面との直接的な関連なし（コード生成基盤） |

## 機能種別

コード生成ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| compilation | Compilation | Yes | コンパイルインスタンス | - |
| outputOptions | OutputOptions | Yes | 出力オプション(environment含む) | - |
| requestShortener | RequestShortener | Yes | リクエストパスの短縮表示 | - |

### 入力データソース

- webpack設定のoutput.environment: ターゲット環境のサポート機能フラグ
- webpack設定のoutput.globalObject: グローバルオブジェクト定義

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 関数コード | string | 環境に適応したJavaScript関数コード |
| モジュール参照コード | string | モジュールID解決・require呼び出しコード |
| インポート文 | [string, string] | ハーモニーインポート文と互換文のペア |
| ブロックPromise | string | 非同期チャンク読み込みのPromise式 |

### 出力先

- 各ランタイムモジュールおよびモジュールコード生成結果

## 処理フロー

### 処理シーケンス

```
1. RuntimeTemplate初期化
   +-- constructor(compilation, outputOptions, requestShortener)
   +-- globalObject算出(getGlobalObject)
   +-- contentHashReplacement初期化

2. 環境判定
   +-- supportsArrowFunction() -> output.environment.arrowFunction
   +-- supportsConst() -> output.environment.const
   +-- supportsDestructuring() -> output.environment.destructuring
   +-- supportsForOf() -> output.environment.forOf
   +-- supportsDynamicImport() -> output.environment.dynamicImport
   +-- supportsEcmaScriptModuleSyntax() -> output.environment.module
   +-- supportTemplateLiteral() -> output.environment.templateLiteral

3. コード生成ヘルパー
   +-- basicFunction(args, body) -> arrow function or function expression
   +-- returningFunction(returnValue, args) -> 値を返す関数
   +-- expressionFunction(expression, args) -> 式を評価する関数
   +-- destructureArray(items, value) -> 分割代入 or 個別var
   +-- destructureObject(items, value) -> オブジェクト分割代入 or 個別var
   +-- iife(args, body) -> 即時実行関数式
   +-- forEach(variable, array, body) -> for-of or forEach
   +-- concatenation(...args) -> テンプレートリテラル or 文字列結合

4. モジュール参照
   +-- moduleId(options) -> モジュールIDの文字列表現
   +-- moduleRaw(options) -> __webpack_require__(moduleId)
   +-- moduleNamespace(options) -> exportsType別の名前空間取得
   +-- moduleNamespacePromise(options) -> 非同期名前空間取得Promise

5. インポート/エクスポート
   +-- importStatement(options) -> [importCode, compatCode]
   +-- exportFromImport(options) -> エクスポート参照コード
```

### フローチャート

```mermaid
flowchart TD
    A[RuntimeTemplate生成] --> B[outputOptions.environment読み取り]
    B --> C{環境判定}
    C --> D[ES6+ サポート]
    C --> E[ES5 のみ]
    D --> F[arrow function / const / destructuring]
    E --> G[function / var / 個別代入]
    F --> H[コード文字列生成]
    G --> H
    H --> I[ランタイムモジュール/コード生成で使用]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | Arrow Function適応 | arrowFunctionサポート時は`(args) => {body}`、非サポート時は`function(args) {body}` | 常時 |
| BR-50-02 | const/var選択 | constサポート時は`const`、非サポート時は`var` | 常時 |
| BR-50-03 | テンプレートリテラル最適化 | テンプレートリテラルと文字列結合のコスト比較で短い方を選択 | concatenation()呼び出し時 |
| BR-50-04 | exportsType分岐 | namespace/default-with-named/default-only/dynamicの4種類で異なる名前空間処理 | moduleNamespace/moduleNamespacePromise |
| BR-50-05 | weak dependency処理 | moduleId===nullかつweak=trueの場合、エラーコード生成(MODULE_NOT_FOUND) | weakモジュール参照時 |
| BR-50-06 | globalObject安全化 | グローバルオブジェクト定義が識別子・IIFE・括弧式でない場合、Object()でラップ | 常時 |
| BR-50-07 | 遅延モジュール対応 | import deferフェーズのモジュールはmakeDeferredNamespaceObjectで処理 | defer import時 |

### 計算ロジック

- テンプレートリテラルコスト: 式1つにつき3文字(`${expr}`)
- 文字列結合コスト: 連続式は1文字(`+`)、非連続式は4文字(`+" "+`)。末尾式は-3、先頭単独式は-3
- コストが低い方の構文を選択

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MODULE_NOT_FOUND | Error | throwMissingModuleErrorBlock: モジュールが見つからない | エラーコード付きErrorを投げる |
| - | Error | moduleId/moduleRaw: moduleId===nullかつweak=false | noModuleIdErrorMessageでエラー |
| - | Error | weakError: weak dependencyのモジュール未利用可能 | "Module is not available (weak dependency)" |

### リトライ仕様

リトライは行わない。

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

該当なし

## パフォーマンス要件

- concatenation()メソッドでテンプレートリテラルと文字列結合のコスト比較を行い、最短のコードを生成
- moduleNamespacePromise()でasyncモジュール判定による最適なPromiseチェーン生成

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

- getGlobalObject(): 安全でないグローバルオブジェクト定義をObject()でラップ

## 備考

- RuntimeTemplateはCompilationのコンストラクタで生成され、compilation.runtimeTemplateとしてアクセス可能
- isNeutralPlatform()はweb/nodeどちらでもないプラットフォームを判定
- pathinfo設定時にはリクエストパスをコメントとして出力

---

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

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

### 推奨読解順序

#### Step 1: コンストラクタと環境判定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **95-109行目**: コンストラクタ。compilation, outputOptions, requestShortener, globalObjectの設定 |
| 1-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **77-93行目**: getGlobalObject()。識別子/IIFE/括弧式の判定とObject()ラップ |
| 1-3 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **111-172行目**: 環境判定メソッド群。isIIFE, isModule, supportsConst, supportsArrowFunction, supportsDestructuring, supportsForOf, supportsDynamicImport, supportsEcmaScriptModuleSyntax, supportTemplateLiteral等 |

#### Step 2: コード生成ヘルパーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **196-200行目**: returningFunction()。arrow function vs function式の分岐 |
| 2-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **207-211行目**: basicFunction()。本体付き関数の生成 |
| 2-3 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **284-288行目**: expressionFunction()。式を評価する関数 |
| 2-4 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **302-308行目**: destructureArray()。分割代入 vs 個別var宣言 |
| 2-5 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **315-323行目**: destructureObject()。オブジェクト分割代入 |
| 2-6 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **340-346行目**: forEach()。for-of vs Array.forEach |

#### Step 3: テンプレートリテラル最適化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **217-260行目**: concatenation()。テンプレートリテラルvs文字列結合のコスト比較アルゴリズム |
| 3-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **267-277行目**: _es5Concatenation()。ES5フォールバック文字列結合 |

#### Step 4: モジュール参照コード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **475-494行目**: moduleId()。モジュールIDの文字列表現生成 |
| 4-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **505-537行目**: moduleRaw()。__webpack_require__(moduleId)の生成 |
| 4-3 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **568-625行目**: moduleNamespace()。exportsType(namespace/default-with-named/default-only/dynamic)による分岐 |
| 4-4 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **640-817行目**: moduleNamespacePromise()。非同期名前空間取得。blockPromise + exportsType分岐 + deferred module対応 |

#### Step 5: インポート文生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **870-959行目**: importStatement()。harmony import文と互換文(defaultExport)の生成 |
| 5-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **981-998行目**: exportFromImport()。エクスポート参照コードの生成 |

#### Step 6: エラー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **384-389行目**: throwMissingModuleErrorBlock()。MODULE_NOT_FOUNDエラー |
| 6-2 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **440-465行目**: weakError()。statements/promise/expressionの3形式 |
| 6-3 | RuntimeTemplate.js | `lib/RuntimeTemplate.js` | **52-71行目**: noModuleIdErrorMessage()。モジュールID未割り当てエラー |

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

```
Compilation.constructor()
    +-- new RuntimeTemplate(compilation, outputOptions, requestShortener)

RuntimeModule.generate()  (各ランタイムモジュール)
    +-- compilation.runtimeTemplate.basicFunction()
    +-- compilation.runtimeTemplate.returningFunction()
    +-- compilation.runtimeTemplate.destructureArray()
    +-- compilation.runtimeTemplate.expressionFunction()

CodeGeneration (モジュールコード生成)
    +-- compilation.runtimeTemplate.moduleId()
    +-- compilation.runtimeTemplate.moduleRaw()
    +-- compilation.runtimeTemplate.moduleNamespace()
    +-- compilation.runtimeTemplate.moduleNamespacePromise()
    +-- compilation.runtimeTemplate.importStatement()
    +-- compilation.runtimeTemplate.exportFromImport()
    +-- compilation.runtimeTemplate.blockPromise()

RuntimeTemplate内部呼び出し
    +-- moduleNamespacePromise()
    |       +-- blockPromise()
    |       +-- moduleRaw() / moduleId()
    |       +-- weakError()
    |
    +-- importStatement()
    |       +-- moduleId()
    |       +-- moduleRaw()
    |       +-- weakError()
    |       +-- missingModuleStatement()
    |
    +-- concatenation()
            +-- _es5Concatenation()
```

### データフロー図

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

outputOptions.environment ----> supportsArrowFunction()等   ----> boolean
                                (環境判定)

args, body             -------> basicFunction()             ----> "(args) => { body }"
                                                                  or "function(args) { body }"

module, chunkGraph     -------> moduleId()                  ----> '"moduleId"'
                                moduleRaw()                 ----> '__webpack_require__("moduleId")'
                                moduleNamespace()           ----> 名前空間参照コード

block, module          -------> moduleNamespacePromise()    ----> "Promise.resolve().then(...)"
                                +-- blockPromise()
                                +-- exportsType分岐

module, importVar      -------> importStatement()           ----> ["var x = __wr__(id);", "var x_default = ...;"]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RuntimeTemplate.js | `lib/RuntimeTemplate.js` | ソース | ランタイムコードテンプレート生成の中核 |
| Template.js | `lib/Template.js` | ソース | 静的コード結合ユーティリティ(asString, indent等) |
| RuntimeGlobals.js | `lib/RuntimeGlobals.js` | ソース | ランタイムグローバル変数名定義 |
| RuntimeModule.js | `lib/RuntimeModule.js` | ソース | ランタイムモジュール基底クラス |
| InitFragment.js | `lib/InitFragment.js` | ソース | コード初期化フラグメント |
| compileBooleanMatcher.js | `lib/util/compileBooleanMatcher.js` | ソース | 条件式の最適化 |
| propertyAccess.js | `lib/util/propertyAccess.js` | ソース | プロパティアクセスコード生成 |
