# 機能設計書 24-events

## 概要

本ドキュメントは、Node.jsのeventsモジュールの機能設計について記述する。eventsモジュールは、EventEmitterクラスを提供し、Node.jsにおけるイベント駆動プログラミングの基盤となる。多くのNode.jsコアモジュール（Stream、HTTP、FS等）がEventEmitterを継承している。

### 本機能の処理概要

**業務上の目的・背景**：eventsモジュールは、Node.jsの非同期イベント駆動アーキテクチャの中核を担う。オブザーバーパターンを実装し、疎結合なコンポーネント間通信を可能にする。イベントの発行（emit）とリスニング（on/once）により、非同期処理を直感的に記述できる。

**機能の利用シーン**：
- カスタムイベントの発行・購読システムを構築する際
- 非同期処理の完了通知を実装する際
- エラーイベントの一元的なハンドリングを行う際
- ストリームやHTTPリクエストのイベント処理を行う際
- イベントを非同期イテレータとして扱う際
- Promiseベースでイベントを待機する際

**主要な処理内容**：
1. `on(event, listener)` / `addListener()` - イベントリスナーを登録
2. `once(event, listener)` - 一度だけ実行されるリスナーを登録
3. `emit(event, ...args)` - イベントを発行
4. `removeListener(event, listener)` / `off()` - リスナーを削除
5. `removeAllListeners([event])` - 全リスナーを削除
6. `listeners(event)` - リスナー配列を取得
7. `setMaxListeners(n)` - 最大リスナー数を設定
8. `EventEmitter.once()` - Promiseベースでイベント待機（静的メソッド）
9. `EventEmitter.on()` - AsyncIteratorとしてイベントを取得（静的メソッド）
10. `prependListener()` / `prependOnceListener()` - リスナーを先頭に追加
11. `eventNames()` - 登録済みイベント名一覧を取得
12. `listenerCount()` - リスナー数を取得

**関連システム・外部連携**：
- async_hooks - EventEmitterAsyncResource連携
- internal/event_target - EventTarget互換性
- internal/abort_controller - AbortSignal連携

**権限による制御**：特になし。すべての機能は任意のユーザーコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはAPI機能であり、関連する画面はありません |

## 機能種別

イベント駆動基盤 / オブザーバーパターン実装

## 入力仕様

### 入力パラメータ

#### on / addListener

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| event | string \| symbol | Yes | イベント名 | - |
| listener | Function | Yes | コールバック関数 | validateFunction |

#### emit

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| event | string \| symbol | Yes | イベント名 | - |
| ...args | any[] | No | リスナーに渡す引数 | - |

#### setMaxListeners

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| n | number | Yes | 最大リスナー数 | validateNumber(>=0) |

#### EventEmitter.once（静的メソッド）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| emitter | EventEmitter \| EventTarget | Yes | イベントエミッター | - |
| name | string \| symbol | Yes | イベント名 | - |
| options | Object | No | { signal: AbortSignal } | validateObject |

#### EventEmitter.on（静的メソッド）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| emitter | EventEmitter | Yes | イベントエミッター | - |
| event | string \| symbol | Yes | イベント名 | - |
| options | Object | No | { signal, close, highWaterMark, lowWaterMark } | validateObject |

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| on/addListener戻り値 | EventEmitter | チェーン呼び出し用に自身を返す |
| emit戻り値 | boolean | リスナーが存在したかどうか |
| listeners戻り値 | Function[] | リスナー関数の配列 |
| eventNames戻り値 | (string \| symbol)[] | イベント名の配列 |
| once戻り値 | Promise | イベント引数の配列で解決 |
| on戻り値 | AsyncIterator | イベントを順次取得 |

### 出力先

呼び出し元への戻り値として返却。

## 処理フロー

### 処理シーケンス

```
1. リスナー登録（on/addListener）
   └─ _events オブジェクトにリスナーを格納
2. イベント発行（emit）
   └─ 対象イベントの全リスナーを順次実行
3. リスナー削除（removeListener）
   └─ _events から該当リスナーを削除
4. errorイベント特殊処理
   └─ リスナーがない場合は例外をスロー
```

### フローチャート

```mermaid
flowchart TD
    A[emit呼び出し] --> B{イベント種別}
    B -->|error| C{errorリスナーあり?}
    B -->|その他| D{リスナーあり?}
    C -->|Yes| E[errorリスナーを実行]
    C -->|No| F[例外をスロー]
    D -->|Yes| G[全リスナーを実行]
    D -->|No| H[false を返却]
    E --> I[true を返却]
    G --> I
    F --> J[処理終了（例外）]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルト最大リスナー | 10を超えるリスナー登録時に警告 | defaultMaxListeners = 10 |
| BR-002 | errorイベント特殊処理 | errorイベントにリスナーがない場合、エラーをスロー | emit('error') |
| BR-003 | newListenerイベント | リスナー追加時にnewListenerイベントを発行 | on/addListener使用時 |
| BR-004 | removeListenerイベント | リスナー削除時にremoveListenerイベントを発行 | removeListener使用時 |
| BR-005 | captureRejections | Promiseリジェクションをerrorイベントとして捕捉 | captureRejections=true |

### 計算ロジック

#### emit処理（455-534行目）
1. 'error'イベントの特殊処理（errorMonitor呼び出し、リスナーなしの場合はスロー）
2. リスナーが単一関数の場合は直接呼び出し
3. リスナーが配列の場合は全要素を順次呼び出し
4. captureRejectionsが有効な場合、Promiseリジェクションを捕捉

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

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_UNHANDLED_ERROR | Error | errorイベントにリスナーがない | errorリスナーを登録 |
| ERR_INVALID_ARG_TYPE | TypeError | 引数の型が不正 | 正しい型の引数を渡す |
| AbortError | Error | AbortSignalがabortされた | シグナルの状態を確認 |

### リトライ仕様

リトライ処理は行わない。

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

トランザクション処理は行わない。

## パフォーマンス要件

- リスナー配列のクローン最適化（arrayClone関数、865-876行目）
- 単一リスナーの場合は配列を作成せず直接格納
- kShapeModeによる最適化（削除時のdelete vs undefinedの使い分け）

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

- MaxListeners警告によるメモリリーク検出支援
- errorイベントの強制ハンドリングによるサイレントエラー防止

## 備考

- EventEmitterAsyncResourceはasync_hooksとの連携機能
- captureRejectionSymbolでカスタムリジェクションハンドラを設定可能
- errorMonitor（kErrorMonitor）でerrorイベントを監視可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | events.js | `lib/events.js` | EventEmitterの内部プロパティ（255-257行目） |

**読解のコツ**: `_events`（イベント→リスナーのマップ）、`_eventsCount`（イベント数）、`_maxListeners`（最大リスナー数）の3つの内部プロパティを理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | events.js | `lib/events.js` | EventEmitterコンストラクタ（208-210行目） |
| 2-2 | events.js | `lib/events.js` | module.exports（211-217行目） |

**主要処理フロー**:
1. **208-210行目**: EventEmitterコンストラクタ（init呼び出し）
2. **211行目**: デフォルトエクスポート
3. **212-217行目**: 静的メソッドのエクスポート（addAbortListener, once, on等）

#### Step 3: emit処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | events.js | `lib/events.js` | emit関数（455-534行目） |

**主要処理フロー**:
- **456-464行目**: errorイベントの特殊処理判定
- **467-500行目**: errorイベントでリスナーがない場合の例外スロー
- **502-506行目**: リスナーが存在しない場合のfalse返却
- **507-534行目**: リスナーの実行とcaptureRejections処理

#### Step 4: リスナー管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | events.js | `lib/events.js` | _addListener関数（536-591行目） |
| 4-2 | events.js | `lib/events.js` | removeListener関数（669-721行目） |

**主要処理フロー**:
- **536-559行目**: newListenerイベントの発行
- **561-575行目**: リスナーの格納（単一/配列の使い分け）
- **577-587行目**: MaxListeners警告の発行
- **669-721行目**: リスナーの削除とremoveListenerイベント

#### Step 5: 静的メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | events.js | `lib/events.js` | once静的メソッド（963-1005行目） |
| 5-2 | events.js | `lib/events.js` | on静的メソッド（1047-1201行目） |

**主要処理フロー**:
- **963-1005行目**: Promiseベースのonce実装（AbortSignal対応）
- **1047-1201行目**: AsyncIterator実装（highWaterMark/lowWaterMark対応）

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

```
lib/events.js
    │
    ├─ EventEmitter() [208-210行目]
    │      └─ EventEmitter.init() [331-353行目]
    │
    ├─ emit() [455-534行目]
    │      ├─ kErrorMonitor処理
    │      ├─ errorイベント特殊処理
    │      └─ addCatch() [355-375行目] (captureRejections用)
    │
    ├─ on() / addListener() [599-601行目, 603行目]
    │      └─ _addListener() [536-591行目]
    │              └─ checkListener() [264-266行目]
    │
    ├─ once() [641-646行目]
    │      └─ _onceWrap() [627-633行目]
    │
    ├─ removeListener() / off() [669-721行目, 723行目]
    │
    ├─ removeAllListeners() [732-778行目]
    │
    ├─ static once() [963-1005行目]
    │      └─ eventTargetAgnosticAddListener() [1021-1033行目]
    │
    └─ static on() [1047-1201行目]
           ├─ listenersController() [1203-1217行目]
           └─ FixedQueue (internal/fixed_queue)
```

### データフロー図

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

イベント+リスナー ───▶ on/addListener ───▶ EventEmitter（チェーン用）
イベント+引数 ───▶ emit ───▶ boolean（リスナー有無）
イベント+リスナー ───▶ removeListener ───▶ EventEmitter（チェーン用）
エミッター+イベント ───▶ once（静的） ───▶ Promise<引数配列>
エミッター+イベント ───▶ on（静的） ───▶ AsyncIterator
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| events.js | `lib/events.js` | ソース | メインモジュール |
| internal/event_target.js | `lib/internal/event_target.js` | ソース | EventTarget互換 |
| internal/events/abort_listener.js | `lib/internal/events/abort_listener.js` | ソース | AbortListener |
| internal/events/symbols.js | `lib/internal/events/symbols.js` | ソース | シンボル定義 |
| internal/fixed_queue.js | `lib/internal/fixed_queue.js` | ソース | AsyncIterator用キュー |
| internal/validators.js | `lib/internal/validators.js` | ソース | バリデーション |
| async_hooks.js | `lib/async_hooks.js` | ソース | AsyncResource連携 |
