# 機能設計書 53-scriptタグ実行

## 概要

本ドキュメントは、CoffeeScriptのscriptタグ実行機能の設計を記述する。HTML内の`text/coffeescript`タイプのscriptタグを自動的に検出し、コンパイル・実行する機能を提供する。

### 本機能の処理概要

scriptタグ実行機能は、HTMLドキュメント内に配置された`text/coffeescript`または`text/literate-coffeescript`タイプのscriptタグを自動的に検出し、ページ読み込み時にCoffeeScriptコードとしてコンパイル・実行する。

**業務上の目的・背景**：HTML内に直接CoffeeScriptコードを記述することで、ビルドプロセスを経ずにCoffeeScriptを使用できる環境を提供する。これは学習目的、プロトタイピング、ドキュメント内のインタラクティブな例など、手軽にCoffeeScriptを試したい場面で有用である。従来のJavaScriptと同様の感覚でHTMLにCoffeeScriptを埋め込むことができる。

**機能の利用シーン**：
- CoffeeScript公式ドキュメントのインタラクティブな例
- テストスイートのブラウザ上での実行
- 学習・教育目的でのサンプルコード
- プロトタイプ開発での迅速な実装

**主要な処理内容**：
1. DOMContentLoadedイベントでの自動起動
2. `text/coffeescript`および`text/literate-coffeescript`タイプのscriptタグ検索
3. src属性がある場合は外部ファイルをXHRで読み込み
4. インラインの場合はinnerHTMLからコード取得
5. 順序を保持した実行

**関連システム・外部連携**：
- DOM API（getElementsByTagName、getAttribute）
- CoffeeScript.load関数（外部ファイル読み込み用）
- CoffeeScript.run関数（コンパイル・実行用）

**権限による制御**：特になし。ブラウザ環境で利用可能なすべてのユーザーが本機能を利用できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | テストスイート | 主画面 | text/coffeescriptタイプのscriptタグを自動でコンパイル・実行 |
| 5 | v1テストスイート | 主画面 | text/coffeescriptタイプのscriptタグを自動コンパイル・実行 |
| 7 | v2テストスイート | 主画面 | text/coffeescriptタイプのscriptタグを自動コンパイル・実行 |
| 22 | Annotated Source - Browser | 補助画面 | runScriptsの解説を含む |
| 37 | Annotated Source - Browser | 補助画面 | runScriptsの解説を含む（v2） |

## 機能種別

実行処理 / DOM操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| scriptタグ.type | String | Yes | スクリプトのタイプ属性 | "text/coffeescript"または"text/literate-coffeescript" |
| scriptタグ.src | String | No | 外部CoffeeScriptファイルのURL | 有効なURL形式 |
| scriptタグ.data-src | String | No | srcの代替属性 | 有効なURL形式 |
| scriptタグ.innerHTML | String | No | インラインCoffeeScriptコード | - |
| scriptタグ.id | String | No | ソースマップ用のファイル名として使用 | - |

### 入力データソース

- HTMLドキュメント内のscriptタグ
- 外部CoffeeScriptファイル（src属性指定時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 実行結果 | Any | 各scriptタグのCoffeeScriptコードの実行結果 |

### 出力先

- ブラウザのJavaScript実行環境
- コンソール（デバッグ出力がある場合）

## 処理フロー

### 処理シーケンス

```
1. runScripts関数の呼び出し（DOMContentLoadedイベント）
   └─ ページ読み込み完了時に自動実行

2. scriptタグの収集
   └─ getElementsByTagName('script')ですべてのscriptタグを取得
   └─ typeがtext/coffeescriptまたはtext/literate-coffeescriptのものをフィルタリング

3. 各scriptタグの処理
   └─ src属性またはdata-src属性がある場合
      └─ CoffeeScript.loadで外部ファイルを読み込み（非同期、順序保持）
   └─ src属性がない場合
      └─ innerHTMLからインラインコードを取得
      └─ ソースマップ用のファイル名を設定（id属性またはcoffeescript+インデックス）

4. 順序保持実行
   └─ execute関数で配列内のスクリプトを順番に実行
   └─ XHR読み込み完了後にコールバックで次のスクリプトへ
```

### フローチャート

```mermaid
flowchart TD
    A[DOMContentLoaded] --> B[runScripts呼び出し]
    B --> C[全scriptタグ取得]
    C --> D[CoffeeScriptタイプをフィルタリング]
    D --> E{scriptタグあり?}
    E -->|No| F[終了]
    E -->|Yes| G[index = 0]
    G --> H{現在のscriptにsrc属性?}
    H -->|Yes| I[CoffeeScript.load呼び出し]
    I --> J[コールバックでcoffeesに結果格納]
    H -->|No| K[innerHTMLを取得]
    K --> L[ファイル名設定（id or coffeescript+index）]
    L --> M[coffees配列に格納]
    J --> N[execute関数呼び出し]
    M --> O[次のscriptタグへ]
    N --> P{coffees[index]がArray?}
    O --> H
    P -->|Yes| Q[CoffeeScript.run実行]
    P -->|No| R[待機]
    Q --> S[index++]
    S --> T{index < coffees.length?}
    T -->|Yes| P
    T -->|No| F
    R --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-53-01 | サポートタイプ | text/coffeescriptとtext/literate-coffeescriptの2種類をサポート | scriptタグ検出時 |
| BR-53-02 | Literate判定 | type=text/literate-coffeescriptの場合はliterate:trueオプションを設定 | scriptタグのtype確認時 |
| BR-53-03 | ファイル名設定 | id属性があればそれを使用、なければcoffeescript+インデックス | インラインスクリプト処理時 |
| BR-53-04 | 最初のスクリプト番号省略 | インデックス0の場合は番号なし（coffeescript）、それ以外は番号付き（coffeescript1等） | ファイル名生成時 |
| BR-53-05 | 順序保持実行 | スクリプトはHTML内での記述順に実行される | 全ケース |
| BR-53-06 | src優先 | src属性とdata-src属性の両方がある場合はsrcを優先 | 外部ファイル読み込み時 |
| BR-53-07 | ESモジュール非登録 | this===windowでない場合はイベントハンドラを登録しない | モジュールロード時 |

### 計算ロジック

該当なし

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

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

該当なし（ブラウザ環境のため、データベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | 構文エラー | 不正なCoffeeScriptコード | コンソールにエラー表示 |
| NetworkError | ネットワークエラー | 外部ファイルの読み込み失敗 | CoffeeScript.loadのエラーハンドリングに委譲 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- DOMContentLoaded時に同期的に実行される
- 外部ファイル読み込みは非同期だが、実行順序は保持される
- 多数のscriptタグがある場合、ページ読み込み時間に影響する可能性がある

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

- ユーザー入力を含むCoffeeScriptの動的生成は避けるべき
- 外部ファイル読み込みは同一オリジンポリシーに従う
- XSS攻撃のリスクに注意

## 備考

- text/coffeescriptタイプはブラウザによって無視されるため、JavaScriptとして誤って実行されることはない
- ESモジュール版では自動実行が無効化されており、手動でrunScriptsを呼び出す必要がある
- sourceFilesオプションには'embedded'が設定される（インラインスクリプトの場合）

---

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

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

### 推奨読解順序

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

scriptタグの処理では、coffees配列で各スクリプトの状態を管理する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | browser.coffee | `src/browser.coffee` | coffees配列とparamの構造 |

**読解のコツ**:
- coffees配列の各要素は `[code, options]` の配列形式
- 外部ファイルの場合、読み込み完了までは空で、コールバックで設定される

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | browser.coffee | `src/browser.coffee` | runScripts関数の実装（61-96行目） |

**主要処理フロー**:
1. **61行目**: runScripts関数の定義
2. **62行目**: getElementsByTagNameでscriptタグ取得
3. **63行目**: 対応するtypeの配列定義
4. **64行目**: coffeetypesに一致するscriptタグをフィルタリング
5. **67-72行目**: execute関数の定義（順序保持実行）
6. **74-94行目**: 各scriptタグの処理ループ

#### Step 3: scriptタグ処理ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | browser.coffee | `src/browser.coffee` | 外部ファイルとインラインの分岐処理（74-94行目） |

**主要処理フロー**:
- **74-75行目**: do構文でスクリプトとインデックスをキャプチャ
- **76行目**: literateオプションの設定
- **77行目**: srcまたはdata-src属性の取得
- **78-85行目**: 外部ファイルの場合のCoffeeScript.load呼び出し
- **87-94行目**: インラインの場合のファイル名生成とcoffees配列への格納

#### Step 4: イベントハンドラ登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | browser.coffee | `src/browser.coffee` | DOMContentLoadedイベント登録（98-107行目） |

**主要処理フロー**:
- **103行目**: this === windowの判定（ESモジュール対応）
- **104-105行目**: addEventListener対応ブラウザでのイベント登録
- **106-107行目**: attachEvent対応ブラウザでのフォールバック

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

```
DOMContentLoaded / onload
    │
    └─ CoffeeScript.runScripts()
           │
           ├─ getElementsByTagName('script')
           │
           ├─ [フィルタリング] text/coffeescript, text/literate-coffeescript
           │
           ├─ [外部ファイルの場合]
           │      └─ CoffeeScript.load(src, callback, options, hold=true)
           │             └─ callback: coffees[i] = param
           │
           ├─ [インラインの場合]
           │      └─ coffees[i] = [innerHTML, options]
           │
           └─ execute()
                  └─ CoffeeScript.run(coffees[index]...)
                         └─ index++ → execute()
```

### データフロー図

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

HTML                    ───▶  runScripts()
  │                                │
  ├─ <script                       │
  │   type="text/coffeescript"     │
  │   src="file.coffee">           ├─▶ load() ───▶ XHR ───┐
  │                                │                       │
  └─ <script                       │                       ▼
      type="text/coffeescript">    ├─▶ innerHTML ───▶ coffees[]
      code...                      │                       │
      </script>                    │                       │
                                   ▼                       │
                              execute()  ◀─────────────────┘
                                   │
                                   ▼
                              CoffeeScript.run() ───▶ 実行結果
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| browser.coffee | `src/browser.coffee` | ソース | runScripts関数の実装 |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | compile関数（runから呼び出し） |
