# 機能設計書 8-JavaScriptパーサ

## 概要

本ドキュメントは、acornベースのJavaScriptパーサでソースコードを解析し、依存関係・エクスポート・インポート情報を抽出する機能の設計を記述する。

### 本機能の処理概要

JavascriptParserは、JavaScriptソースコードをacornパーサーでAST（抽象構文木）に変換し、ASTを走査しながらtapableフックを通じて依存関係やエクスポート情報を抽出する。式の評価、スコープ管理、変数追跡など、静的解析に必要な機能を包括的に提供する。

**業務上の目的・背景**：webpackがモジュールの依存関係を正確に把握し、Tree ShakingやScope Hoistingなどの最適化を行うためには、ソースコードの精密な静的解析が必要である。JavascriptParserは、この静的解析の中核を担い、多数のParserPluginと連携してさまざまなモジュールパターンを検出する。

**機能の利用シーン**：NormalModuleのbuild()処理内でparser.parse()が呼び出され、ソースコードから依存関係を抽出する。画面機能マッピングでは「JSX構文を含むReactコンポーネントの解析」（画面10, 11）として参照されている。

**主要な処理内容**：
1. acornによるAST生成（import assertions拡張対応）
2. HookMapベースのevaluate/evaluateTypeof/evaluateIdentifierフックによる式評価
3. import/export/require/define等のモジュール宣言フック
4. 変数スコープ管理（StackedMap使用）
5. call/expression/memberフックによるAPIアクセスパターンの検出
6. コメント解析（webpackマジックコメント対応）

**関連システム・外部連携**：acorn（JavaScriptパーサーエンジン）、BasicEvaluatedExpression（式評価結果）、各種ParserPlugin（依存関係検出プラグイン）と連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | Login (reexport-components) | 補助機能 | JSX構文を含むReactコンポーネントの解析 |
| 11 | Dashboard (reexport-components) | 補助機能 | JSX構文を含むReactコンポーネントの解析 |

## 機能種別

パース処理 / 静的解析 / フックベースイベント駆動

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string \| Buffer \| PreparsedAst | Yes | パース対象のソースコード（またはプリパース済みAST） | - |
| state | ParserState | Yes | パーサー状態（current module, compilation等） | - |
| sourceType | "module" \| "script" \| "auto" | No | ソースタイプ（デフォルト: "auto"） | - |

### 入力データソース

- NormalModuleのbuild()後に渡されるソースコード
- パーサーオプション設定（webpack.config.jsのmodule.parser）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| state | ParserState | 解析後のパーサー状態（依存関係、エクスポート情報含む） |
| dependencies | Dependency[] | 検出された依存関係（stateを通じてモジュールに追加） |
| blocks | AsyncDependenciesBlock[] | 非同期依存関係ブロック |

### 出力先

- NormalModuleのdependencies/blocks配列
- buildMetaに解析メタ情報（ESM判定等）

## 処理フロー

### 処理シーケンス

```
1. parse(source, state) 呼び出し
   └─ preprocess / program フック
2. AST生成
   ├─ sourceType = "auto"の場合: "module"でまず試行、失敗したら"script"
   ├─ acorn.parse() 呼び出し（import assertions拡張付き）
   └─ コメントの収集
3. programフック呼び出し（AST全体）
4. prewalkStatements()
   └─ 宣言の事前走査（import/export文の収集）
5. blockPreWalkStatements()
   └─ ブロックレベルの事前走査
6. walkStatements()
   └─ 各ステートメントの詳細走査
7. walkExpression()
   └─ 式ノードの走査（call, member, identifier等のフック発火）
8. finish / statementフック呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[parse呼び出し] --> B{sourceType auto?}
    B -->|Yes| C[moduleで試行]
    C --> D{成功?}
    D -->|No| E[scriptで再試行]
    D -->|Yes| F[AST取得]
    E --> F
    B -->|No| F
    F --> G[programフック]
    G --> H[prewalkStatements - 宣言事前走査]
    H --> I[blockPreWalkStatements]
    I --> J[walkStatements - 詳細走査]
    J --> K[各ノードのフック発火]
    K --> L[依存関係の収集完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | auto sourceType | "auto"の場合、"module"でまずパースを試み、SyntaxErrorが出たら"script"にフォールバック | sourceType = "auto"時 |
| BR-02 | importAssertions拡張 | acornをimport assertions/attributesに対応するよう拡張 | 常時 |
| BR-03 | SyncBailHookによるフック優先度 | 最初にnon-undefinedを返したプラグインが勝つ | evaluate/call等のフック |
| BR-04 | スコープ管理 | StackedMapで変数スコープを管理し、シャドウイングを正確に追跡 | 関数・ブロックスコープ |
| BR-05 | マジックコメント | webpackMagicComment（webpackChunkName等）の解析 | import()呼び出し時 |

### 計算ロジック

特になし。

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

該当なし。

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

該当なし。

### テーブル別操作詳細

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| SyntaxError | パースエラー | JavaScriptの構文が不正 | ソースコードの構文を修正 |

### リトライ仕様

sourceType = "auto"の場合、"module"でパース失敗時に"script"で再試行する。これ以外のリトライはない。

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

該当なし。

## パフォーマンス要件

- acornは高速なJavaScriptパーサー
- SyncBailHookにより不要なプラグイン実行をスキップ
- StackedMapによる効率的なスコープ管理
- memoize()による遅延モジュールロード

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

- パーサーはソースコードを解析するのみで実行はしない（executeModuleとは異なる）

## 備考

- JavascriptParserはParserクラスを継承
- acornのECMAScript最新仕様（"latest"）を使用
- import assertions/attributesはカスタムプラグインで拡張されている

---

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

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

### 推奨読解順序

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

パーサーの型定義とフック構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | JavascriptParser.js | `lib/javascript/JavascriptParser.js` | VariableInfo/ScopeInfo型定義（279-395行目）でスコープ管理データ構造を理解する |
| 1-2 | JavascriptParser.js | `lib/javascript/JavascriptParser.js` | ImportAttributes型定義（204行目）でimport属性の構造を理解する |

**読解のコツ**: JavascriptParserは非常に大きなファイル（数千行）。まずフック定義部分（487行目以降）を俯瞰し、どのようなイベントが発火されるかを把握すると全体像が見えやすい。

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

parse()メソッドが処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | JavascriptParser.js | `lib/javascript/JavascriptParser.js` | parse()メソッドでAST生成→prewalk→walk→finishの流れを理解する |

#### Step 3: フック構造を理解する

HookMapベースのフック群を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | JavascriptParser.js | `lib/javascript/JavascriptParser.js` | コンストラクタ（485行目以降）のフック定義群を理解する |

**主要フック**:
- **488-497行目**: evaluateTypeof/evaluate/evaluateIdentifier/evaluateDefinedIdentifier（式評価フック）
- import/call/expression/identifier等のフック
- program/finish/preStatement/statement等の走査フック

#### Step 4: AST走査を理解する

walk系メソッドの処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | JavascriptParser.js | `lib/javascript/JavascriptParser.js` | walkStatements()/walkExpression()メソッドでAST走査ロジックを理解する |

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

```
JavascriptParser.parse(source, state)
    │
    ├─ acorn.parse(source, options) [import assertions拡張付き]
    │      └─ AST生成 + コメント収集
    │
    ├─ hooks.program.call(ast, comments)
    │
    ├─ prewalkStatements(ast.body)
    │      └─ import/export宣言の事前収集
    │
    ├─ blockPreWalkStatements(ast.body)
    │      └─ ブロックレベル宣言の事前収集
    │
    ├─ walkStatements(ast.body)
    │      ├─ walkStatement(statement)
    │      │      ├─ hooks.statement.call(statement)
    │      │      ├─ walkExpression(expression)
    │      │      │      ├─ hooks.expression.for(name).call()
    │      │      │      ├─ hooks.call.for(name).call()
    │      │      │      └─ hooks.evaluate.for(type).call()
    │      │      └─ walkVariableDeclaration() / walkIfStatement() etc.
    │      └─ [再帰的にネストされたステートメントを走査]
    │
    └─ hooks.finish.call(ast, comments)
```

### データフロー図

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

ソースコード ────────▶ acorn.parse() ──────────▶ AST（Program）
                            │
AST ──────────────▶ prewalk: import/export収集
                            │
                     walk: 各ノード走査
                     ├─ HookMap発火
                     │   ├─ import → ParserPlugin → Dependency生成
                     │   ├─ call → ParserPlugin → Dependency生成
                     │   └─ evaluate → BasicEvaluatedExpression
                     │
                     └─ スコープ管理（StackedMap）

                     state.module.dependencies[] に依存関係を蓄積
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| JavascriptParser.js | `lib/javascript/JavascriptParser.js` | ソース | JavaScriptパーサー本体 |
| Parser.js | `lib/Parser.js` | ソース | パーサー基底クラス |
| BasicEvaluatedExpression.js | `lib/javascript/BasicEvaluatedExpression.js` | ソース | 式評価結果クラス |
| StackedMap.js | `lib/util/StackedMap.js` | ソース | スコープ管理用スタックマップ |
| magicComment.js | `lib/util/magicComment.js` | ソース | webpackマジックコメント解析 |
| binarySearchBounds.js | `lib/util/binarySearchBounds.js` | ソース | 二分探索ユーティリティ |
