# 帳票設計書 14-ソースマップ（RawSourceMap）

## 概要

本ドキュメントは、Vue.jsのコンパイラパッケージ群（compiler-core、compiler-sfc等）が生成するソースマップ（RawSourceMap）の出力仕様を定義する帳票設計書である。ソースマップは、コンパイル後のコードとコンパイル前のテンプレート/スタイルの位置対応情報を提供し、開発時のデバッグにおいてコンパイル前のソースコード位置を追跡可能にする。

### 本帳票の処理概要

**業務上の目的・背景**：Vueのテンプレートコンパイラは、テンプレート構文（`<template>`）をJavaScriptのrender関数コードに変換し、スタイルコンパイラはSFCのスタイルブロックを処理済みCSSに変換する。この変換過程でソースコードの位置情報が失われるため、デバッグ時に「コンパイル後のエラー位置 → 元のテンプレート/スタイルの位置」を追跡することが困難になる。RawSourceMapはSource Map V3仕様に準拠した位置マッピング情報を保持し、ブラウザの開発者ツールやエディタがコンパイル前のソースを表示できるようにする。

**帳票の利用シーン**：(1) ブラウザの開発者ツールでVueコンポーネントのテンプレート箇所にブレークポイントを設定する場合、(2) ランタイムエラーのスタックトレースで元のテンプレート位置を特定する場合、(3) SFCのstyleブロックのCSS位置を追跡する場合、(4) compileScript処理でscript setupとtemplateのソースマップをマージする場合、(5) SFCのparse処理で各ブロックの位置情報をソースマップとして出力する場合。

**主要な出力内容**：
1. version: ソースマップのバージョン番号（"3"）
2. sources: 元のソースファイル名の配列
3. names: マッピングで参照される識別子名の配列
4. mappings: Base64 VLQエンコードされた位置マッピング文字列
5. sourcesContent: 元のソースコードの内容（任意）
6. file: 出力ファイル名（任意）
7. sourceRoot: ソースファイルのルートパス（任意）

**帳票の出力タイミング**：コンパイラの各関数（generate、compileTemplate、compileStyle、compileScript、parse）がコード生成時にソースマップオプションが有効な場合に自動的に生成される。`sourceMap` オプションが `false` でない場合にRawSourceMapが出力に含まれる。

**帳票の利用者**：Vueアプリケーション開発者（デバッグ時）、ビルドツール（Vite、webpack等）のVueプラグイン開発者、SFCコンパイラを利用するフレームワーク開発者。

## 帳票種別

ソースマップ出力（Source Map V3形式のJSONオブジェクト）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | ビルド時処理 | N/A | generate関数、compileTemplate関数、compileStyle関数等の呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON形式のRawSourceMapオブジェクト（.map / インライン） |
| 用紙サイズ | N/A（データ構造出力） |
| 向き | N/A |
| ファイル名 | 使用側が決定（通常は元ファイル名.map） |
| 出力方法 | コンパイラ関数の戻り値のmapプロパティとして返却 |
| 文字コード | UTF-8 |

### PDF固有設定

N/A

### Excel固有設定

N/A

## 帳票レイアウト

### レイアウト概要

RawSourceMapはSource Map V3仕様に準拠したJSONオブジェクトであり、以下のフィールドで構成される。

```
┌─────────────────────────────────────┐
│           RawSourceMap               │
├─────────────────────────────────────┤
│  file?: string                       │
│  sourceRoot?: string                 │
│  version: string                     │
│  sources: string[]                   │
│  names: string[]                     │
│  sourcesContent?: string[]           │
│  mappings: string                    │
│    （Base64 VLQエンコード済み）         │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | version | ソースマップ仕様のバージョン | 固定値 "3" | 文字列 |
| 2 | file | 出力ファイル名 | コンパイラオプション（filename） | 文字列（任意） |
| 3 | sourceRoot | ソースファイルのルートパス | コンパイラオプション | 文字列（任意） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | sources | 元のソースファイル名の配列 | コンパイラオプション（filename） | string[] | N/A |
| 2 | names | マッピングで参照される識別子名の配列 | コード生成時に検出された変数名 | string[] | N/A |
| 3 | sourcesContent | 元のソースコードの内容の配列 | ASTのsourceプロパティ | string[]（任意） | N/A |
| 4 | mappings | Base64 VLQエンコードされた位置マッピング文字列 | SourceMapGeneratorのaddMapping蓄積結果 | string | N/A |

### フッター部

N/A（RawSourceMapは単一のJSONオブジェクトであるためフッター部の概念はない）

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| sourceMap | ソースマップ生成を有効にするフラグ（CodegenOptionsのsourceMapプロパティ） | No（デフォルト: false） |
| filename | ソースファイル名（デフォルト: "template.vue.html"） | No（デフォルト値あり） |
| source | コンパイル対象のソースコード（AST経由） | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | 生成コードの行番号 | 昇順 |
| 2 | 生成コードの列番号 | 昇順 |

### 改ページ条件

N/A

## データベース参照仕様

### 参照テーブル一覧

N/A（データベースアクセスは行わない）

### テーブル別参照項目詳細

N/A

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| マッピング追加（addMapping） | originalLine: loc.line, originalColumn: loc.column - 1, generatedLine: context.line, generatedColumn: context.column - 1 | N/A | source-mapはcolumnが0ベース、VueのPosition型は1ベースのため-1する（codegen.ts 264行目） |
| name検出 | SimpleExpressionノードで!isStaticの場合、_ctx.プレフィックスを除去してname設定 | N/A | codegen.ts 186-191行目 |
| parse用ソースマップ生成 | 各行の非空白文字位置に対してマッピングを追加 | N/A | parse.ts 371-388行目のgenerateSourceMap関数 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コンパイラ関数呼び出し] --> B{sourceMapオプション有効?}
    B -->|No| C[map: undefinedを返却]
    B -->|Yes| D[SourceMapGenerator生成]
    D --> E[setSourceContentでソース設定]
    E --> F[コード生成ループ]
    F --> G{ノードにloc情報あり?}
    G -->|Yes| H[addMappingで開始位置マッピング追加]
    G -->|No| I[スキップ]
    H --> J[コード文字列をpush]
    J --> K{ノードにloc.endあり?}
    K -->|Yes| L[addMappingで終了位置マッピング追加]
    K -->|No| M[次のノードへ]
    L --> M
    I --> M
    M --> F
    F -->|完了| N[map.toJSON でRawSourceMap取得]
    N --> O[CodegenResult.mapとして返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| マッピング不整合 | __TEST__環境でpush()のnewlineIndex指定が実際の改行位置と不一致 | CodegenContext.push() called newlineIndex:... | テスト環境のみで検出。newlineIndex指定を修正 |
| ソースマップ未生成 | __BROWSER__環境ではソースマップ生成がスキップされる | なし（map: undefinedとなる） | ブラウザ環境ではソースマップは不要のため正常動作 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | テンプレートのノード数に比例（数十〜数千ノード） |
| 目標出力時間 | コンパイル時間全体に含まれる（ソースマップ生成は副次的コスト） |
| 同時出力数上限 | ビルドツールの並列度に依存 |

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

- ソースマップにはsourcesContentとして元のソースコードが含まれる可能性がある
- プロダクション環境ではソースマップを公開しないことが推奨される
- ソースマップはデバッグ目的のみに使用すべき

## 備考

- RawSourceMapインターフェースはcodegen.ts 83-91行目で定義されている
- source-map-jsライブラリのSourceMapGeneratorを内部で使用しているが、パフォーマンス最適化のためにprivateプロパティ（_sources, _names, _mappings）に直接アクセスしている（codegen.ts 256-269行目）
- codegen.tsのコメント（63-71行目）にTS 5.3でのdts生成の問題回避のためソースマップ関連型をインライン定義していることが記載されている
- __BROWSER__フラグがtrueの場合、ソースマップ生成はスキップされる（codegen.ts 272行目）
- SFCのparse関数では独自のgenerateSourceMap関数（parse.ts 357-390行目）を使用してブロック単位のソースマップを生成する
- compileScript関数ではscript setupとtemplateのソースマップをmergeSourceMaps関数でマージする（compileScript.ts 1103-1107行目）

---

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

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

### 推奨読解順序

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

RawSourceMapとCodegenSourceMapGeneratorの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | codegen.ts | `packages/compiler-core/src/codegen.ts` | RawSourceMapインターフェース（83-91行目）。version, sources, names, sourcesContent, mappingsの各フィールド |
| 1-2 | codegen.ts | `packages/compiler-core/src/codegen.ts` | CodegenSourceMapGeneratorインターフェース（72-81行目）。setSourceContent, toJSON, _sources, _names, _mappingsのプライベートプロパティ |
| 1-3 | codegen.ts | `packages/compiler-core/src/codegen.ts` | MappingItemインターフェース（93-100行目）。source, generatedLine/Column, originalLine/Column, name |
| 1-4 | codegen.ts | `packages/compiler-core/src/codegen.ts` | CodegenResultインターフェース（108-113行目）。map?: RawSourceMapとして出力に含まれる |

**読解のコツ**: RawSourceMapはSource Map V3仕様の標準的なJSON構造である。source-map-jsライブラリのSourceMapGeneratorをCodegenSourceMapGeneratorとしてキャストし、パフォーマンス最適化のためにprivateプロパティに直接アクセスしている点が特徴的。

#### Step 2: エントリーポイントを理解する（generate関数）

テンプレートコンパイラのgenerate関数でのソースマップ生成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | codegen.ts | `packages/compiler-core/src/codegen.ts` | createCodegenContext関数（141-281行目）。sourceMapオプションに応じたSourceMapGenerator初期化（272-278行目） |
| 2-2 | codegen.ts | `packages/compiler-core/src/codegen.ts` | addMapping関数（256-270行目）。_mappings.addでマッピングを直接追加 |
| 2-3 | codegen.ts | `packages/compiler-core/src/codegen.ts` | generate関数の戻り値（400-405行目）。context.map.toJSON()でRawSourceMapを取得 |

**主要処理フロー**:
1. **272-278行目**: sourceMapオプションがtrue且つ非ブラウザ環境の場合、SourceMapGeneratorを生成し、setSourceContentでソースを設定
2. **182-235行目**: push()メソッド内でノードのloc情報に基づきaddMappingを呼び出し
3. **186-191行目**: SimpleExpressionノードでisStaticでない場合、_ctx.プレフィックスを除去してname設定
4. **193-195行目**: ノードのloc.sourceが存在する場合、開始位置のマッピングを追加
5. **232-234行目**: ノードのloc.endが存在する場合、終了位置のマッピングを追加
6. **404行目**: 最終的にmap.toJSON()でRawSourceMapオブジェクトに変換して返却

#### Step 3: SFC parse時のソースマップ生成を理解する

SFCのparse関数で使用されるgenerateSourceMap関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parse.ts | `packages/compiler-sfc/src/parse.ts` | generateSourceMap関数（357-390行目）。ブロック単位でのソースマップ生成 |

**主要処理フロー**:
- **365-368行目**: SourceMapGeneratorを生成し、ファイルパスのバックスラッシュをスラッシュに正規化
- **369-370行目**: setSourceContentでソースを設定、_sourcesにファイル名を追加
- **371-388行目**: 生成コードの各行をループし、非空白文字位置にマッピングを追加。lineOffsetとcolumnOffsetで位置を調整
- **389行目**: map.toJSON()でRawSourceMapを返却

#### Step 4: compileScript時のソースマップマージを理解する

script setupとtemplateのソースマップをマージする処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | compileScript.ts | `packages/compiler-sfc/src/compileScript.ts` | ソースマップ生成（1094-1101行目）。ctx.s.generateMap()でMagicStringベースのソースマップ生成 |
| 4-2 | compileScript.ts | `packages/compiler-sfc/src/compileScript.ts` | mergeSourceMaps関数（1374-1377行目付近）。script setupとtemplateのソースマップをマージ |

#### Step 5: compileStyle時のソースマップ利用を理解する

スタイルコンパイル時のソースマップの受け渡しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | compileStyle.ts | `packages/compiler-sfc/src/compileStyle.ts` | SFCStyleCompileResults型（62-69行目）。map: RawSourceMap \| undefinedとして出力 |
| 5-2 | compileStyle.ts | `packages/compiler-sfc/src/compileStyle.ts` | doCompileStyle関数（89-109行目）。プリプロセッサのマップまたはinMapを入力ソースマップとして使用 |

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

```
[テンプレートコンパイル]
generate(ast, options)
    │
    ├─ createCodegenContext(ast, options)
    │      ├─ new SourceMapGenerator()
    │      ├─ setSourceContent(filename, source)
    │      └─ _sources.add(filename)
    │
    ├─ genNode(codegenNode, context)
    │      └─ context.push(code, newlineIndex, node)
    │             ├─ addMapping(node.loc.start, name?)
    │             │      └─ _mappings.add({original→generated})
    │             └─ addMapping(node.loc.end)
    │
    └─ context.map.toJSON() → RawSourceMap

[SFC parse]
parse(source, options)
    └─ generateSourceMap(filename, source, generated, ...)
           ├─ new SourceMapGenerator()
           ├─ setSourceContent / _sources.add
           ├─ 行ループ → _mappings.add
           └─ map.toJSON() → RawSourceMap

[SFCスクリプトコンパイル]
compileScript(sfc, options)
    ├─ ctx.s.generateMap() → RawSourceMap
    └─ mergeSourceMaps(scriptMap, templateMap) → RawSourceMap
```

### データフロー図

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

テンプレートAST ──────▶ generate()                  ──▶ CodegenResult.map
  + sourceMapオプション    ├─ SourceMapGenerator生成       (RawSourceMap)
                         ├─ 各ノードのloc情報で
                         │   addMapping
                         └─ toJSON()

SFCソースコード ──────▶ parse()                     ──▶ SFCBlock.map
  + parseオプション       └─ generateSourceMap()          (RawSourceMap)

SFCスクリプト ────────▶ compileScript()             ──▶ SFCScriptBlock.map
  + ソースマップオプション   ├─ MagicString.generateMap()    (RawSourceMap)
                          └─ mergeSourceMaps()

SFCスタイル ──────────▶ compileStyle()              ──▶ SFCStyleCompileResults.map
  + inMap                 └─ PostCSS処理                  (RawSourceMap)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| codegen.ts | `packages/compiler-core/src/codegen.ts` | ソース | RawSourceMap型定義（83-91行目）、CodegenSourceMapGenerator型定義（72-81行目）、generate関数でのソースマップ生成 |
| index.ts | `packages/compiler-core/src/index.ts` | ソース | RawSourceMap型のエクスポート（29行目） |
| parse.ts | `packages/compiler-sfc/src/parse.ts` | ソース | generateSourceMap関数（357-390行目）、SFCブロック単位のソースマップ生成 |
| compileTemplate.ts | `packages/compiler-sfc/src/compileTemplate.ts` | ソース | SFCTemplateCompileResults型でmap?: RawSourceMapを出力（44行目） |
| compileStyle.ts | `packages/compiler-sfc/src/compileStyle.ts` | ソース | SFCStyleCompileResults型でmap: RawSourceMapを出力（64行目）、inMap入力 |
| compileScript.ts | `packages/compiler-sfc/src/compileScript.ts` | ソース | MagicStringベースのソースマップ生成（1094-1101行目）、mergeSourceMaps関数 |
| options.ts | `packages/compiler-core/src/options.ts` | ソース | CodegenOptionsでsourceMapオプション定義 |
