# 機能設計書 5-ソースマップ生成

## 概要

本ドキュメントは、コンパイル時にV3形式のソースマップを生成し、デバッグに利用可能にする機能について、その処理内容、入出力仕様、およびコードリーディングガイドを記載したものである。

### 本機能の処理概要

ソースマップ生成機能は、CoffeeScriptからJavaScriptへのコンパイル時に、生成されたJavaScriptコードの各位置が元のCoffeeScriptソースコードのどの位置に対応するかを記録したソースマップを生成する機能である。

**業務上の目的・背景**：トランスパイルされたJavaScriptをデバッグする際、ブラウザのデベロッパーツールやNode.jsのデバッガーで元のCoffeeScriptコードを参照できるようにする必要がある。ソースマップによって、ブレークポイントの設定、ステップ実行、スタックトレースの表示を元のソースコードで行うことができる。

**機能の利用シーン**：ブラウザでのデバッグ時（Chrome DevTools, Firefox Developer Tools等）、Node.jsでのデバッグ時、エラースタックトレースの元ソース位置表示時、IDE/エディタでのソースマップ利用時に使用される。

**主要な処理内容**：
1. コード生成時の位置情報記録
2. LineMapによる行単位のマッピング管理
3. V3形式ソースマップの生成
4. VLQエンコーディングによるマッピング圧縮
5. JSON形式でのソースマップ出力
6. インラインソースマップ（Data URI）の生成

**関連システム・外部連携**：ブラウザデベロッパーツール、Node.jsデバッガー、各種IDE

**権限による制御**：特になし（すべてのユーザーが利用可能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | トップページ | 補助機能 | コンパイル時にインラインソースマップを生成してデバッグを支援 |
| 2 | Try CoffeeScript | 補助機能 | デバッグ用のインラインソースマップを生成 |
| 15 | Annotated Source - SourceMap | 主機能 | ソースマップ生成sourcemap.litcoffeeのソースコード解説表示 |
| 30 | Annotated Source - SourceMap | 主機能 | ソースマップ生成sourcemap.litcoffeeのソースコード解説表示（v2） |

## 機能種別

計算処理 / エンコーディング / データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options.sourceMap | boolean | No | ソースマップを生成するかどうか | - |
| options.inlineMap | boolean | No | インラインソースマップを生成するかどうか | - |
| options.filename | string | No | ソースファイル名 | - |
| options.sourceRoot | string | No | ソースファイルのルートパス | - |
| options.sourceFiles | array | No | ソースファイル名の配列 | - |
| options.generatedFile | string | No | 生成ファイル名 | - |

### 入力データソース

- コンパイル処理中のコードフラグメント（位置情報付き）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| version | number | ソースマップバージョン（常に3） |
| file | string | 生成ファイル名 |
| sourceRoot | string | ソースルートパス |
| sources | array | ソースファイル名配列 |
| names | array | 名前配列（現在は空） |
| mappings | string | VLQエンコードされたマッピング文字列 |
| sourcesContent | array | ソースコード内容（inlineMap時） |

### 出力先

- 戻り値として返却（sourceMapオプション時）
- JavaScript内にインライン埋め込み（inlineMapオプション時）
- 別ファイル出力（CLI使用時、--map オプション）

## 処理フロー

### 処理シーケンス

```
1. SourceMapインスタンス生成
   └─ compile関数内でnew SourceMap()

2. コードフラグメント処理ループ
   └─ 各フラグメントの位置情報を取得

3. マッピング追加
   └─ map.add(sourceLocation, generatedLocation)

4. 行・列追跡
   └─ 改行ごとに行番号更新、列番号リセット

5. ソースマップ生成
   └─ map.generate(options, code)

6. VLQエンコード
   └─ 各セグメントをBase64 VLQに変換

7. JSON構造構築
   └─ V3形式のオブジェクト生成

8. 出力形式決定
   └─ JSON文字列またはインラインData URI
```

### フローチャート

```mermaid
flowchart TD
    A[開始: compile関数] --> B{sourceMap or inlineMap?}
    B -->|Yes| C[new SourceMap]
    B -->|No| Z[ソースマップなしで続行]
    C --> D[フラグメントループ開始]
    D --> E{フラグメントあり?}
    E -->|Yes| F[位置情報取得]
    E -->|No| I[generate呼び出し]
    F --> G[map.add実行]
    G --> H[行・列更新]
    H --> D
    I --> J[VLQエンコード]
    J --> K[JSON構造構築]
    K --> L{inlineMap?}
    L -->|Yes| M[Base64エンコード]
    M --> N[Data URI埋め込み]
    L -->|No| O[JSON文字列返却]
    N --> P[registerCompiled]
    O --> P
    P --> Q[終了]
    Z --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | V3形式準拠 | Source Map Revision 3に準拠 | 常時 |
| BR-02 | VLQエンコード | マッピングはBase64 VLQでエンコード | 常時 |
| BR-03 | 相対位置 | マッピング値は前回からの相対値 | 常時 |
| BR-04 | 空白/セミコロン除外 | 空白やセミコロンのみのフラグメントは除外 | マッピング追加時 |

### 計算ロジック

**VLQエンコード**:
```coffeescript
encodeVlq: (value) ->
  signBit = if value < 0 then 1 else 0
  valueToEncode = (Math.abs(value) << 1) + signBit
  # 5ビットずつ分割してBase64変換
```

**Base64変換**:
```coffeescript
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
encodeBase64: (value) -> BASE64_CHARS[value]
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | Base64エンコードエラー | 不正な値のエンコード試行 | 内部エラー（通常発生しない） |

### リトライ仕様

リトライは行わない

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

本機能はトランザクション管理を行わない

## パフォーマンス要件

- ソースマップ生成はコード生成と同時に行われ、追加オーバーヘッドは最小
- VLQエンコードによりマッピングデータを効率的に圧縮

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

- ソースマップにはソースコードが含まれる場合がある
- 本番環境ではソースマップを公開しないことを推奨

## 備考

- Source Map Revision 3仕様に準拠
- ソースマップキャッシュはスタックトレース変換に使用

---

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

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

### 推奨読解順序

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

まず、ソースマップの内部データ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | LineMapクラス（20-31行目）で行単位の位置管理を確認 |
| 1-2 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | SourceMapクラス（43-62行目）で全体構造を確認 |

**読解のコツ**: Literate CoffeeScriptファイルでは、インデントされたコードブロックが実際のコード部分。

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

ソースマップ生成の起点を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | coffeescript.coffee | `src/coffeescript.coffee` | 71行目のnew SourceMap()でインスタンス生成 |
| 2-2 | coffeescript.coffee | `src/coffeescript.coffee` | 116-130行目でフラグメントループ中にmap.add呼び出し |

**主要処理フロー**:
1. **71行目**: SourceMapインスタンス生成
2. **118-124行目**: 有効なフラグメントに対してmap.add実行
3. **125-130行目**: 行・列の追跡更新
4. **140行目**: map.generate呼び出し

#### Step 3: マッピング追加処理を理解する

位置情報の記録方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | SourceMap.add（52-55行目）とLineMap.add（24-26行目） |

**主要処理フロー**:
- **52-55行目**: 生成位置から行を取得、LineMapに委譲
- **24-26行目**: 列ごとのマッピングを配列に格納

#### Step 4: V3ソースマップ生成を理解する

最終的なソースマップ生成処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | generate メソッド（89-154行目） |

**主要処理フロー**:
- **90-95行目**: 状態変数初期化
- **97-133行目**: マッピング文字列構築
- **117-132行目**: VLQエンコード呼び出し
- **137-154行目**: V3 JSONオブジェクト構築

#### Step 5: VLQエンコードを理解する

Base64 VLQエンコーディングを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sourcemap.litcoffee | `src/sourcemap.litcoffee` | encodeVlq（170-186行目）とencodeBase64（194-195行目） |

**主要処理フロー**:
- **174行目**: 符号ビットの決定
- **177行目**: 値の絶対値を左シフトして符号ビット追加
- **180-185行目**: 5ビットずつ分割してBase64変換

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

```
CoffeeScript.compile (coffeescript.coffee:62)
    │
    ├─ new SourceMap (sourcemap.litcoffee:43)
    │
    ├─ フラグメントループ (coffeescript.coffee:116)
    │      │
    │      └─ map.add (sourcemap.litcoffee:52)
    │             └─ LineMap.add (sourcemap.litcoffee:24)
    │
    ├─ map.generate (sourcemap.litcoffee:89)
    │      │
    │      └─ encodeVlq (sourcemap.litcoffee:170)
    │             └─ encodeBase64 (sourcemap.litcoffee:194)
    │
    ├─ base64encode (coffeescript.coffee:29) [inlineMap時]
    │
    └─ registerCompiled (sourcemap.litcoffee:73)
```

### データフロー図

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

CodeFragment[]     ──▶  SourceMap.add           ──▶  LineMap.columns[]
{code, locationData}     (位置記録)                   {line, column, sourceLine, sourceColumn}
                              │
                              ▼
                        generate              ──▶  VLQエンコード済み
                        (マッピング構築)             mappings文字列
                              │
                              ▼
                        JSON構造構築           ──▶  V3 SourceMap
                        {                           {
                          version: 3                 version: 3,
                          sources: [...]             file: "...",
                          mappings: "..."            sources: [...],
                        }                            mappings: "AAAA;..."
                                                   }
                              │
                              ▼
                        Base64エンコード       ──▶  Data URI
                        (inlineMap時)               "data:application/json;base64,..."
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sourcemap.litcoffee | `src/sourcemap.litcoffee` | ソース | SourceMap/LineMapクラス、VLQエンコード |
| coffeescript.coffee | `src/coffeescript.coffee` | ソース | ソースマップ生成の呼び出し元 |
