# 機能設計書 26-jest-environment-node

## 概要

本ドキュメントは、JestのNode.jsテスト環境（jest-environment-node）の機能設計を記述する。このパッケージは、Node.js環境でテストを実行するためのJestEnvironment実装を提供する。

### 本機能の処理概要

jest-environment-nodeは、Node.js環境でJestテストを実行するための環境実装を提供するパッケージである。VMコンテキストを使用してテストごとに隔離されたグローバルスコープを作成し、Node.jsのグローバル変数を適切に設定する。

**業務上の目的・背景**：Jestでテストを実行する際、各テストファイルは独立した環境で実行される必要がある。jest-environment-nodeは、Node.jsのVMモジュールを使用して隔離されたコンテキストを作成し、テスト間の相互干渉を防ぐ。また、グローバルオブジェクトのメモリリーク防止機能（globalsCleanup）も提供する。

**機能の利用シーン**：
- Node.jsベースのテストを実行する際（デフォルト環境）
- サーバーサイドJavaScriptのテスト
- CLIツールやライブラリのテスト

**主要な処理内容**：
1. VMコンテキストの作成と初期化
2. Node.jsグローバル変数（Buffer, Error等）の設定
3. フェイクタイマー（Legacy/Modern）の初期化
4. ModuleMockerの初期化
5. globalsCleanupによるメモリリーク防止
6. カスタムexportConditionsのサポート

**関連システム・外部連携**：
- @jest/environment: 環境インターフェース
- @jest/fake-timers: フェイクタイマー
- jest-mock: モック機能
- jest-util: ユーティリティ関数
- Node.js VM: コンテキスト隔離

**権限による制御**：この機能に権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | Configurationページ | 補助機能 | testEnvironment設定オプションの説明 |

## 機能種別

テスト実行環境

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| config | JestEnvironmentConfig | Yes | 環境設定（projectConfig, globalConfig） | - |
| context | EnvironmentContext | Yes | 環境コンテキスト（console, testPath） | - |

### testEnvironmentOptions

| オプション名 | 型 | デフォルト | 説明 |
|-------------|-----|----------|------|
| customExportConditions | Array<string> | ['node', 'node-addons'] | エクスポート条件 |
| globalsCleanup | 'on' / 'soft' / 'off' | 'soft' | グローバルクリーンアップモード |

### 入力データソース

- jest-runtimeからのテスト実行リクエスト
- Jest設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| global | Global.Global | 隔離されたグローバルオブジェクト |
| context | Context | VMコンテキスト |
| fakeTimers | LegacyFakeTimers | レガシーフェイクタイマー |
| fakeTimersModern | ModernFakeTimers | モダンフェイクタイマー |
| moduleMocker | ModuleMocker | モジュールモッカー |

### 出力先

- テスト実行環境

## 処理フロー

### 処理シーケンス

```
1. コンストラクタ呼び出し
   └─ globalsCleanupモードの読み取り
   └─ GlobalProxyの作成
   └─ VMコンテキストの作成

2. グローバル変数の設定
   └─ nodeGlobalsのイテレーション
   └─ Buffer, ArrayBuffer, Uint8Arrayの設定
   └─ 共通グローバルのインストール
   └─ Symbol.asyncDispose/disposeの設定

3. モック/タイマーの初期化
   └─ ModuleMockerの作成
   └─ LegacyFakeTimersの作成
   └─ ModernFakeTimersの作成

4. setup()呼び出し（空実装）

5. テスト実行

6. teardown()呼び出し
   └─ fakeTimersのdispose
   └─ fakeTimersModernのdispose
   └─ GlobalProxyのclear
```

### フローチャート

```mermaid
flowchart TD
    A[コンストラクタ] --> B[GlobalProxy作成]
    B --> C[VMコンテキスト作成]
    C --> D[グローバル変数設定]
    D --> E[ModuleMocker初期化]
    E --> F[FakeTimers初期化]
    F --> G[setup]
    G --> H[テスト実行]
    H --> I[teardown]
    I --> J[リソース解放]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | グローバルクリーンアップ | globalsCleanupが'soft'（デフォルト）の場合、環境セットアップ後に設定されたプロパティをクリーンアップ | teardown時 |
| BR-26-02 | denyList | GLOBAL, root, global, globalThis, Buffer, ArrayBuffer, Uint8ArrayはnodeGlobalsから除外 | 初期化時 |
| BR-26-03 | Error.stackTraceLimit | エラースタックトレース上限を100に設定 | 初期化時 |
| BR-26-04 | カスタムexportConditions | 配列かつ全要素が文字列の場合のみ許可 | 設定時 |

### 計算ロジック

計算処理は存在しない。

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

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

データベース操作は存在しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | customExportConditionsが文字列配列でない場合 | 文字列配列を指定 |
| - | Warning | globalsCleanupが不正な値の場合 | on/soft/offのいずれかを指定 |

### リトライ仕様

リトライ処理は存在しない。

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

トランザクション処理は存在しない。

## パフォーマンス要件

- VMコンテキスト作成は各テストファイルごとに行われる
- globalsCleanupによるメモリリーク防止

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

- VMコンテキストによるテスト間の隔離を提供
- ただしセキュリティサンドボックスではない（信頼できないコード実行には不適）

## 備考

- jest-environment-nodeはJestのデフォルトテスト環境
- TestEnvironmentとしてもエクスポートされる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/jest-environment-node/src/index.ts` | Timer型、denyList、nodeGlobals |

**読解のコツ**:
- Timer型（27-31行目）はフェイクタイマー用のタイマー参照
- denyList（34-44行目）はnodeGlobalsから除外するグローバル変数
- nodeGlobals（48-65行目）はNode.jsグローバル変数のマップ

#### Step 2: NodeEnvironmentクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-environment-node/src/index.ts` | NodeEnvironmentクラス（83-238行目） |

**主要処理フロー**:
- **94-106行目**: コンストラクタ - GlobalProxyとVMコンテキスト作成
- **108-157行目**: nodeGlobalsの設定（レイジーゲッター使用）
- **159-165行目**: Buffer, ArrayBuffer, Uint8Arrayの設定
- **167行目**: installCommonGlobals呼び出し
- **169-175行目**: Symbol.asyncDispose/disposeの設定
- **179行目**: Error.stackTraceLimitを100に設定
- **181-193行目**: customExportConditionsの設定
- **195行目**: ModuleMocker初期化
- **197-210行目**: FakeTimers初期化
- **216行目**: setup() - 空実装
- **218-229行目**: teardown() - リソース解放
- **231-233行目**: exportConditions() - エクスポート条件取得
- **235-237行目**: getVmContext() - VMコンテキスト取得

#### Step 3: GlobalProxyクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/jest-environment-node/src/index.ts` | GlobalProxyクラス（249-347行目） |

**主要処理フロー**:
- **249-256行目**: クラス定義とプロパティ
- **262-264行目**: proxy() - プロキシオブジェクト取得
- **270-272行目**: envSetupCompleted() - セットアップ完了マーク
- **279-293行目**: clear() - プロパティのクリーンアップ
- **295-319行目**: defineProperty() - プロパティ定義時のフック
- **321-332行目**: deleteProperty() - プロパティ削除時のフック
- **334-346行目**: register() - プロパティ登録

#### Step 4: 設定読み取りを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/jest-environment-node/src/index.ts` | readGlobalsCleanupConfig関数（349-370行目） |

**主要処理フロー**:
- **352-353行目**: testEnvironmentOptionsからglobalsCleanupを読み取り
- **354-358行目**: on/soft/offのいずれかに変換
- **359-368行目**: 不正な値の場合は警告を出してデフォルト'soft'を返す

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

```
@jest/runtime
    │
    └─ jest-environment-node
           │
           ├─ NodeEnvironment (JestEnvironment実装)
           │      ├─ constructor()
           │      │      ├─ GlobalProxy作成
           │      │      ├─ createContext()
           │      │      ├─ installCommonGlobals()
           │      │      ├─ ModuleMocker()
           │      │      ├─ LegacyFakeTimers()
           │      │      └─ ModernFakeTimers()
           │      │
           │      ├─ setup()
           │      ├─ teardown()
           │      ├─ getVmContext()
           │      └─ exportConditions()
           │
           └─ GlobalProxy (ProxyHandler)
                  ├─ proxy()
                  ├─ envSetupCompleted()
                  ├─ clear()
                  ├─ defineProperty()
                  └─ deleteProperty()
```

### データフロー図

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

JestEnvironmentConfig ─────▶ NodeEnvironment ─────▶ 隔離されたテスト環境
                                    │
                                    ├─▶ VMコンテキスト
                                    │
                                    ├─▶ グローバルオブジェクト
                                    │      ├─ Buffer
                                    │      ├─ Error (stackTraceLimit=100)
                                    │      └─ Node.jsグローバル
                                    │
                                    ├─▶ ModuleMocker
                                    │
                                    └─▶ FakeTimers (Legacy/Modern)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-environment-node/src/index.ts` | ソース | NodeEnvironment実装 |
| package.json | `packages/jest-environment-node/package.json` | 設定 | パッケージ定義 |
