# 機能設計書 2-モジュール解決

## 概要

本ドキュメントは、BunランタイムにおけるESモジュール、CommonJS、Node.js互換のモジュール解決機能の設計仕様を定義する。

### 本機能の処理概要

本機能は、import文やrequire()で指定されたモジュールパスを実際のファイルパスに解決する処理を担当する。Node.js互換のモジュール解決アルゴリズムをベースに、package.jsonのexportsフィールドやimportsフィールド、条件付きエクスポートなどの最新仕様にも対応する。

**業務上の目的・背景**：JavaScriptエコシステムではnpmパッケージを活用した開発が一般的であり、正確で高速なモジュール解決は開発体験とランタイムパフォーマンスの両方に直結する。Node.js互換性を維持しつつ、Bun独自の最適化を施すことで、既存プロジェクトの移行を容易にしながら性能向上を実現する。

**機能の利用シーン**：import/require文が実行されるすべての場面。アプリケーション起動時の初期モジュールロード、動的インポート、条件付きインポートなど。

**主要な処理内容**：
1. 相対パス・絶対パスの解決
2. node_modulesからのパッケージ探索
3. package.jsonのmain/module/exports/importsフィールド解析
4. 条件付きエクスポート（import/require/node/browser等）の評価
5. 拡張子の自動補完（.js, .ts, .json等）
6. ディレクトリインデックス（index.js等）の解決
7. TypeScript paths/baseUrl解決
8. サブパスインポート/エクスポートの解決

**関連システム・外部連携**：ファイルシステム、package.jsonの解析、tsconfig.jsonの解析

**権限による制御**：ファイルシステムアクセス権限に基づく

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | run | 主画面 | importやrequireによるモジュールの解決処理 |

## 機能種別

データ連携 / パス解決

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| specifier | string | Yes | インポート指定子（モジュール名またはパス） | 空文字でないこと |
| importer | string | No | インポート元ファイルのパス | 有効なファイルパス |
| conditions | string[] | No | 条件付きエクスポートの条件 | import/require/node/browser等 |

### 入力データソース

- ソースコード内のimport/require文
- package.jsonファイル
- tsconfig.jsonファイル
- node_modulesディレクトリ構造

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| resolved_path | string | 解決されたファイルの絶対パス |
| package_json | object | 関連するpackage.json情報 |
| module_type | string | モジュールタイプ（esm/cjs/unknown） |
| side_effects | boolean | サイドエフェクトの有無 |

### 出力先

- パーサー/トランスパイラへのパス情報提供
- ランタイムへのモジュール情報提供

## 処理フロー

### 処理シーケンス

```
1. パッケージパス判定
   └─ 相対パス/絶対パス/パッケージ名を判定
2. 相対・絶対パス解決
   └─ ファイル存在確認と拡張子補完
3. パッケージ解決
   └─ node_modulesを上方向に探索
4. package.json解析
   └─ exports/imports/main/moduleフィールドを評価
5. 条件付きエクスポート評価
   └─ import/require/node/browser等の条件マッチ
6. 最終パス決定
   └─ 解決結果をキャッシュして返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{パッケージパス?}
    B -->|No| C[相対/絶対パス解決]
    B -->|Yes| D[node_modules探索]
    C --> E{ファイル存在?}
    E -->|No| F[拡張子補完試行]
    E -->|Yes| G[パス確定]
    F --> H{見つかった?}
    H -->|No| I[エラー: MODULE_NOT_FOUND]
    H -->|Yes| G
    D --> J[package.json解析]
    J --> K{exports有り?}
    K -->|Yes| L[条件付きエクスポート評価]
    K -->|No| M[main/module評価]
    L --> G
    M --> G
    G --> N[結果返却]
    I --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | パッケージパス判定 | ./や../で始まらず、絶対パスでないものはパッケージ | モジュール解決開始時 |
| BR-02 | exports優先 | package.jsonにexportsがある場合、main/moduleより優先 | パッケージ解決時 |
| BR-03 | 条件優先順位 | import > require > node > default の順で評価 | 条件付きエクスポート評価時 |
| BR-04 | 拡張子補完順序 | .ts > .tsx > .js > .jsx > .mjs > .cjs の順で試行 | ファイル解決時 |
| BR-05 | ディレクトリインデックス | ディレクトリの場合、index.{ts,tsx,js,jsx}を探索 | ディレクトリパス指定時 |

### 計算ロジック

該当なし

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

該当なし（ファイルシステム操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| MODULE_NOT_FOUND | モジュール未検出 | 指定モジュールが存在しない | パッケージインストールまたはパス修正 |
| ERR_PACKAGE_PATH_NOT_EXPORTED | エクスポート未定義 | exportsで定義されていないサブパス | package.jsonのexportsを確認 |
| ERR_INVALID_PACKAGE_CONFIG | 設定エラー | package.jsonの形式が不正 | package.jsonを修正 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- モジュール解決: 1ms以内（キャッシュヒット時）
- 新規パッケージ解決: 10ms以内
- ディレクトリ情報のキャッシュ活用

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

- シンボリックリンクの循環参照検出
- node_modules以外の意図しないディレクトリへのアクセス防止

## 備考

Bunはnode_modulesの構造を最適化し、ハードリンクを活用することでディスク使用量と解決速度を改善している。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | resolver.zig | `src/resolver/resolver.zig` | Result構造体とPathPair構造体で解決結果のデータ構造を理解 |
| 1-2 | dir_info.zig | `src/resolver/dir_info.zig` | ディレクトリ情報のキャッシュ構造 |

**読解のコツ**: SideEffects enumでパッケージのサイドエフェクト判定を理解。Result.Flagsでbool値をビットフラグに圧縮している設計パターンに注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | resolver.zig | `src/resolver/resolver.zig` | isPackagePath()とisPackagePathNotAbsolute()でパッケージ判定ロジック |

**主要処理フロー**:
1. **6-11行目**: isPackagePath()でパッケージパスかを判定
2. **13-27行目**: isPackagePathNotAbsolute()で相対パス/絶対パス以外を判定

#### Step 3: パス解決処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | resolver.zig | `src/resolver/resolver.zig` | PathPair構造体で主パスと副パスを管理 |

**主要処理フロー**:
- **81-113行目**: PathPair.Iterでパスの反復処理
- **137-200行目**: Result構造体で解決結果を保持

#### Step 4: バッファ管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | resolver.zig | `src/resolver/resolver.zig` | bufs構造体でスレッドローカルバッファを管理 |

**読解のコツ**:
- threadlocal修飾子でスレッドセーフなバッファ管理
- 複数の専用バッファで用途別にメモリを分離

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

```
import/require文
    │
    ├─ resolver.zig::Resolver
    │      ├─ isPackagePath() - パッケージ判定
    │      ├─ resolveWithoutRemapping() - リマッピングなし解決
    │      └─ loadAsFileOrDirectory() - ファイル/ディレクトリ解決
    │
    ├─ dir_info.zig::DirInfo
    │      └─ package.json解析
    │
    └─ Result
           └─ 解決パス + メタデータ
```

### データフロー図

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

import "pkg"  ───▶ isPackagePath() ───▶ true
                         │
                         ▼
               node_modules探索
                         │
                         ▼
               package.json解析 ───▶ exports評価
                         │
                         ▼
               PathPair ───▶ Result ───▶ 絶対パス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| resolver.zig | `src/resolver/resolver.zig` | ソース | メインリゾルバ実装 |
| dir_info.zig | `src/resolver/dir_info.zig` | ソース | ディレクトリ情報管理 |
| data_url.zig | `src/resolver/data_url.zig` | ソース | data:URLの解析 |
| resolve_path.zig | `src/resolver/resolve_path.zig` | ソース | パス操作ユーティリティ |
| PackageJSON.zig | `src/resolver/PackageJSON.zig` | ソース | package.json解析 |
