# 機能設計書: node:events - EventEmitter

## 1. 機能概要

### 1.1 機能名
node:events - EventEmitter

### 1.2 機能ID
96

### 1.3 概要説明
BunにおけるNode.js互換のeventsモジュール実装。イベント駆動アーキテクチャの基盤となるEventEmitterクラスを提供し、イベントの発行と購読を管理する。Node.jsのコアモジュールの多くがEventEmitterを継承しており、非同期プログラミングの中心的な役割を果たす。once(), on(), getEventListeners()等の静的ユーティリティ関数も提供する。

### 1.4 関連画面/API
- CLI: `bun run`コマンドでEventEmitterを利用するアプリケーションを実行
- API: `require("node:events")`

## 2. 機能要件

### 2.1 ユースケース

#### UC-96-1: イベントの発行と購読
- **アクター**: 開発者
- **事前条件**: EventEmitterインスタンスが作成されている
- **基本フロー**:
  1. `emitter.on(eventName, listener)`でリスナー登録
  2. `emitter.emit(eventName, ...args)`でイベント発行
  3. リスナーが引数付きで呼び出される
- **事後条件**: イベントが処理される

#### UC-96-2: 一度だけ実行されるリスナー
- **アクター**: 開発者
- **事前条件**: EventEmitterインスタンスが作成されている
- **基本フロー**:
  1. `emitter.once(eventName, listener)`でリスナー登録
  2. `emitter.emit(eventName)`でイベント発行
  3. リスナーが呼び出され、自動的に削除される
- **事後条件**: リスナーは一度だけ実行

#### UC-96-3: Promiseベースのイベント待機
- **アクター**: 開発者
- **事前条件**: EventEmitterインスタンスが作成されている
- **基本フロー**:
  1. `events.once(emitter, eventName)`でPromise取得
  2. イベント発行を待機
  3. Promiseが解決され、イベント引数が返される
- **事後条件**: async/awaitで利用可能

### 2.2 機能仕様

#### 2.2.1 EventEmitterメソッド
| メソッド | 説明 |
|---------|------|
| `on(eventName, listener)` | リスナー登録（末尾に追加） |
| `addListener(eventName, listener)` | on()のエイリアス |
| `once(eventName, listener)` | 一度だけ実行されるリスナー登録 |
| `prependListener(eventName, listener)` | リスナーを先頭に登録 |
| `prependOnceListener(eventName, listener)` | 一度だけ実行されるリスナーを先頭に登録 |
| `emit(eventName, ...args)` | イベント発行 |
| `off(eventName, listener)` | リスナー削除 |
| `removeListener(eventName, listener)` | off()のエイリアス |
| `removeAllListeners([eventName])` | 全リスナー削除 |

#### 2.2.2 EventEmitter取得メソッド
| メソッド | 説明 |
|---------|------|
| `listeners(eventName)` | リスナー配列取得 |
| `rawListeners(eventName)` | ラッパー含むリスナー配列取得 |
| `listenerCount(eventName)` | リスナー数取得 |
| `eventNames()` | イベント名一覧取得 |
| `getMaxListeners()` | 最大リスナー数取得 |
| `setMaxListeners(n)` | 最大リスナー数設定 |

#### 2.2.3 静的メソッド/プロパティ
| 項目 | 説明 |
|------|------|
| `EventEmitter.once(emitter, name[, options])` | Promiseベースの待機 |
| `EventEmitter.on(emitter, name[, options])` | AsyncIterator取得 |
| `EventEmitter.getEventListeners(emitter, name)` | リスナー取得 |
| `EventEmitter.setMaxListeners(n, ...emitters)` | 複数エミッターの最大リスナー設定 |
| `EventEmitter.defaultMaxListeners` | デフォルト最大リスナー数 |
| `EventEmitter.captureRejections` | Promise rejection処理 |
| `EventEmitter.errorMonitor` | エラー監視シンボル |

#### 2.2.4 特殊イベント
| イベント | 説明 |
|---------|------|
| `'error'` | エラーイベント（リスナーなしで例外スロー） |
| `'newListener'` | リスナー追加時に発火 |
| `'removeListener'` | リスナー削除時に発火 |

## 3. 技術設計

### 3.1 アーキテクチャ

```
┌─────────────────────────────────────────────────────────────┐
│                    JavaScript Layer                          │
│  ┌─────────────────────────────────────────────────────────┐│
│  │  node:events (src/js/node/events.ts)                    ││
│  │  ┌───────────────────────────────────────────────────┐  ││
│  │  │  EventEmitter                                     │  ││
│  │  │  - _events: Object (イベント→リスナー配列)        │  ││
│  │  │  - _eventsCount: number                           │  ││
│  │  │  - _maxListeners: number | undefined              │  ││
│  │  └───────────────────────────────────────────────────┘  ││
│  │  ┌───────────────────────────────────────────────────┐  ││
│  │  │  Static Functions                                 │  ││
│  │  │  - once(), on(), getEventListeners()              │  ││
│  │  │  - setMaxListeners(), listenerCount()             │  ││
│  │  └───────────────────────────────────────────────────┘  ││
│  └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
```

### 3.2 クラス構成

```
events
├── EventEmitter
│   ├── Instance Properties
│   │   ├── _events - イベント名→リスナー配列のマップ
│   │   ├── _eventsCount - 登録イベント数
│   │   └── _maxListeners - 最大リスナー数
│   ├── Instance Methods
│   │   ├── on(event, listener) - リスナー登録
│   │   ├── once(event, listener) - 一度だけのリスナー
│   │   ├── emit(event, ...args) - イベント発行
│   │   ├── off(event, listener) - リスナー削除
│   │   ├── removeAllListeners() - 全削除
│   │   ├── listeners(event) - リスナー取得
│   │   ├── listenerCount(event) - リスナー数
│   │   ├── eventNames() - イベント名一覧
│   │   ├── setMaxListeners(n) - 最大数設定
│   │   └── getMaxListeners() - 最大数取得
│   └── Static Properties/Methods
│       ├── defaultMaxListeners - デフォルト最大数
│       ├── captureRejections - Promise rejection処理
│       ├── errorMonitor - エラー監視シンボル
│       ├── once(emitter, event) - Promise待機
│       ├── on(emitter, event) - AsyncIterator
│       ├── getEventListeners() - リスナー取得
│       └── setMaxListeners() - 複数エミッター設定
├── EventEmitterAsyncResource
│   └── AsyncResourceと統合されたEventEmitter
└── Utility Functions
    ├── once() - 静的once
    ├── on() - 静的on
    ├── getEventListeners() - リスナー取得
    ├── setMaxListeners() - 最大数設定
    ├── listenerCount() - リスナー数
    └── addAbortListener() - AbortSignal用
```

### 3.3 処理フロー

#### イベント発行フロー
```
1. emitter.on(eventName, listener)
   ├── _events オブジェクト確認/作成
   ├── 'newListener' イベント発火（リスナーあれば）
   ├── イベント配列にリスナー追加
   └── 最大数チェック（警告出力）

2. emitter.emit(eventName, ...args)
   ├── 'error' イベント特別処理
   │   └── リスナーなしで例外スロー
   ├── リスナー配列取得
   ├── 各リスナーを引数付きで呼び出し
   │   ├── args.length == 0: handler.call(this)
   │   ├── args.length == 1-3: handler.call(this, arg0, ...)
   │   └── args.length >= 4: handler.apply(this, args)
   └── true/false 返却（リスナー有無）
```

#### once静的メソッドフロー
```
1. EventEmitter.once(emitter, eventName, options)
   ├── Promise作成
   ├── 'error'リスナー登録（reject用）
   ├── イベントリスナー登録（resolve用）
   ├── AbortSignal処理（オプション）
   └── Promise返却

2. イベント発火時
   ├── 両リスナー削除
   └── Promise resolve(args)

3. エラー発火時
   ├── 両リスナー削除
   └── Promise reject(error)
```

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

### 4.1 推奨読解順序

1. **シンボルと定数定義** (`src/js/node/events.ts`)
   - **43-50行目**: kCapture, kErrorMonitor, kMaxEventTargetListeners等のシンボル定義
   - **53-55行目**: defaultMaxListeners = 10

2. **EventEmitterコンストラクタ**
   - **58-78行目**: EventEmitter関数定義
   - _events, _eventsCount, _maxListeners の初期化
   - captureRejections オプション処理

3. **emit関数**
   - **160-196行目**: emitWithoutRejectionCapture
   - **198-237行目**: emitWithRejectionCapture
   - errorイベントの特別処理（96-135行目: emitError関数）

4. **リスナー管理メソッド**
   - **241-287行目**: addListener, prependListener
   - **302-323行目**: once, _onceWrap
   - **332-363行目**: removeListener

5. **静的メソッド**
   - **439-479行目**: once静的関数（Promise返却）
   - **486-630行目**: on静的関数（AsyncIterator返却）

6. **ユーティリティ関数**
   - **656-662行目**: getEventListeners
   - **665-682行目**: setMaxListeners
   - **691-702行目**: listenerCount

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

```
new EventEmitter(opts)
├── this._events = Object.create(null)
├── this._eventsCount = 0
├── this._maxListeners = undefined
└── captureRejections 処理
    └── this.emit = emitWithRejectionCapture

emitter.on(type, fn)
├── checkListener(fn)
│   └── validateFunction(fn)
├── events.newListener ? emit('newListener', type, fn) : skip
└── events[type].push(fn)
    └── _getMaxListeners() 超過時 overflowWarning()

emitter.emit(type, ...args)
├── type === 'error' ? emitError(this, args) : continue
├── handlers = events[type]
├── handlers.length > 1 ? handlers.slice() : handlers
└── for handler of handlers
    ├── args.length 0-3: handler.$call(this, ...)
    └── args.length >= 4: handler.$apply(this, args)

EventEmitter.once(emitter, type, options)
├── validateAbortSignal(options.signal)
├── const { resolve, reject, promise } = newPromiseCapability()
├── emitter.on(type, resolver)
├── emitter.once('error', errorListener)
├── signal?.addEventListener('abort', abortListener)
└── return promise
```

### 4.3 データフロー図

```
[Event Registration]
    emitter.on('data', callback)
           │
           ▼
    ┌─────────────────────────┐
    │ _events = {             │
    │   'data': [callback]    │
    │ }                       │
    │ _eventsCount = 1        │
    └─────────────────────────┘

[Event Emission]
    emitter.emit('data', payload)
           │
           ▼
    ┌─────────────────────────┐
    │ _events['data']         │
    │    │                    │
    │    ▼                    │
    │ callback(payload)       │
    └─────────────────────────┘

[Error Event Special Case]
    emitter.emit('error', new Error())
           │
           ▼
    ┌─────────────────────────┐
    │ _events['error'] exists?│
    │    ├─ Yes: call handler │
    │    └─ No: throw error   │
    └─────────────────────────┘
```

### 4.4 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `src/js/node/events.ts` | TypeScript | node:eventsモジュールのメイン実装（866行） |
| `src/js/internal/validators.ts` | TypeScript | validateFunction等の検証関数 |
| `src/js/internal/fixed_queue.ts` | TypeScript | on()で使用するFixedQueue |
| `src/js/node/async_hooks.ts` | TypeScript | EventEmitterAsyncResource用 |

## 5. 設計上の考慮事項

### 5.1 Node.js互換性
- Node.jsのevents APIと完全互換を目指す
- _events, _eventsCount, _maxListenersの内部構造互換
- newListener, removeListenerイベントの互換性

### 5.2 パフォーマンス最適化
- **58行目**: EventEmitterは標準関数として定義（$apply対応）
- **173-191行目**: args.lengthに応じたcall/apply最適化
- **173行目**: リスナー1つの場合はslice()をスキップ

### 5.3 エラーハンドリング
- errorイベントのリスナーがない場合は例外スロー
- kErrorMonitorシンボルでエラー監視
- captureRejectionsでPromise rejection処理

### 5.4 メモリリーク防止
- defaultMaxListeners = 10 で警告出力
- MaxListenersExceededWarningの発行
- setMaxListeners()でプログラム的に制御

## 6. テスト方針

### 6.1 単体テスト
- on(), once(), emit()の基本動作
- removeListener(), removeAllListeners()のテスト
- 最大リスナー警告のテスト

### 6.2 統合テスト
- 複数イベントの同時処理
- errorイベントのスロー動作
- newListener/removeListenerイベント

### 6.3 互換性テスト
- Node.jsのeventsテストスイートの実行
- EventEmitterを継承するモジュールの動作確認

## 7. 変更履歴

| 日付 | バージョン | 変更内容 |
|------|-----------|---------|
| 2026-01-27 | 1.0 | 初版作成 |
