# 通知設計書 1-dispose

## 概要

本ドキュメントは、three.jsライブラリにおける`dispose`イベント通知の設計について記載する。`dispose`イベントは、GPUリソースを保持するオブジェクト（Light, Texture, Material, BufferGeometry, RenderTarget, Node, ComputeNode, UniformsGroup, InstancedMesh, CanvasTarget等）が明示的に破棄される際に発火するイベントである。

### 本通知の処理概要

`dispose`イベントは、three.jsのリソース管理において最も重要なイベントの一つであり、GPUメモリのリークを防止するためのクリーンアップ処理を実行するために使用される。

**業務上の目的・背景**：WebGLやWebGPUアプリケーションでは、テクスチャ、ジオメトリ、マテリアル等のGPUリソースが明示的に解放されない限りメモリに残り続ける。この`dispose`イベントは、アプリケーションがリソースを不要と判断した際に発火され、レンダラー内部でGPUリソースの解放処理をトリガーする。メモリリークによるパフォーマンス低下やクラッシュを防止するために不可欠な仕組みである。

**通知の送信タイミング**：各クラスの`dispose()`メソッドが呼び出された際に、`dispatchEvent({ type: 'dispose' })`が実行され、登録されたリスナーに通知される。タイミングは以下の通り：
- アプリケーションコードがオブジェクトを不要と判断し、明示的に`dispose()`を呼び出した時
- RenderTargetの`setSize()`で新しいサイズが設定された時（内部で`dispose()`が呼ばれる）

**通知の受信者**：主な受信者はレンダラー（WebGLRenderer, WebGPURenderer等）であり、GPUリソースの管理を担当するコンポーネントがリスナーとして登録される。具体的には`WebGLTextures`、`WebGLGeometries`、`WebGLMaterials`等の内部モジュールがイベントを監視する。

**通知内容の概要**：イベントオブジェクトには`type: 'dispose'`のみが含まれ、`target`プロパティには`dispatchEvent()`実行時に自動的にイベント発火元のオブジェクト参照が設定される。

**期待されるアクション**：受信者はGPUリソース（テクスチャ、バッファ、シェーダープログラム等）を解放し、内部キャッシュからオブジェクトの参照を削除する。これによりGPUメモリが解放され、ガベージコレクションの対象となる。

## 通知種別

アプリ内イベント通知（EventDispatcherパターン）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無 |

### 送信先決定ロジック

EventDispatcherの`_listeners`オブジェクトに登録されている`dispose`タイプのリスナー関数すべてに対して、登録順に通知が送信される。リスナーの登録は`addEventListener('dispose', callback)`で行う。

## 通知テンプレート

### イベントオブジェクト形式

| 項目 | 内容 |
|-----|------|
| type | 'dispose' |
| target | dispatchEvent実行元オブジェクト（自動設定） |

### イベントオブジェクト例

```javascript
{
  type: 'dispose',
  target: <Texture|Material|BufferGeometry|...>
}
```

### 添付ファイル

該当なし（イベント通知のため添付ファイルは存在しない）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| type | イベントタイプ | 固定値 'dispose' | Yes |
| target | イベント発火元オブジェクト | EventDispatcher.dispatchEvent内で自動設定 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | dispose()メソッド呼び出し | 常に送信 | 各リソースクラスのdispose()メソッドが呼び出された時 |
| 内部処理 | RenderTarget.setSize() | サイズ変更時 | レンダーターゲットのサイズが変更された際に内部でdispose()が呼ばれる |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| リスナー未登録 | _listenersにdisposeタイプのリスナーが存在しない場合は通知処理自体がスキップされる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[dispose()メソッド呼び出し] --> B[dispatchEvent type: dispose 実行]
    B --> C{_listenersにdisposeリスナーが存在?}
    C -->|Yes| D[event.targetに自身を設定]
    C -->|No| E[処理終了]
    D --> F[リスナー配列をコピー]
    F --> G[各リスナーを順次呼び出し]
    G --> H[event.targetをnullにリセット]
    H --> E
```

## データベース参照・更新仕様

該当なし（three.jsはクライアントサイドライブラリのためデータベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リスナーエラー | リスナー関数内で例外が発生 | 例外はキャッチされず呼び出し元に伝播。残りのリスナーは呼び出されない |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし

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

- disposeイベント自体には機密情報は含まれない
- リスナー関数はクロージャ経由で外部データにアクセスする可能性があるが、これはアプリケーション実装の責任範囲

## 備考

- dispose()を呼び出してもオブジェクト自体はJavaScriptメモリに残る。完全に解放するには、そのオブジェクトへの参照をすべて削除する必要がある
- dispose()は通常、オブジェクトのライフサイクル終了時に一度だけ呼び出すべきである
- 同一オブジェクトに対してdispose()を複数回呼び出しても、イベントは都度発火する

---

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

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

### 推奨読解順序

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

EventDispatcherの内部構造とイベントオブジェクトの形式を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EventDispatcher.js | `src/core/EventDispatcher.js` | _listenersオブジェクトの構造、イベントオブジェクトの形式を理解 |

**読解のコツ**: EventDispatcherは23行目から128行目までのシンプルなクラス。`_listeners`は`{ [eventType]: Function[] }`の形式で管理される。

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

disposeイベントを発火する各クラスのdispose()メソッドを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Texture.js | `src/textures/Texture.js` | 636-646行目のdispose()メソッドとJSDocコメント |
| 2-2 | Material.js | `src/materials/Material.js` | 989-998行目のdispose()メソッド |
| 2-3 | BufferGeometry.js | `src/core/BufferGeometry.js` | 1450-1454行目のdispose()メソッド |
| 2-4 | Light.js | `src/lights/Light.js` | 55-59行目のdispose()メソッド |

**主要処理フロー**:
1. **636行目（Texture.js）**: dispose()メソッドの定義開始
2. **644行目（Texture.js）**: `this.dispatchEvent( { type: 'dispose' } )`でイベント発火

#### Step 3: イベントディスパッチの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EventDispatcher.js | `src/core/EventDispatcher.js` | 101-126行目のdispatchEvent()メソッドの実装詳細 |

**主要処理フロー**:
- **103行目**: _listenersオブジェクトを取得
- **105行目**: リスナーが未定義の場合は早期リターン
- **107行目**: イベントタイプに対応するリスナー配列を取得
- **111行目**: event.targetに発火元オブジェクトを設定
- **114行目**: リスナー配列をコピー（イテレーション中の変更に対応）
- **116-120行目**: 各リスナーを順次呼び出し
- **122行目**: event.targetをnullにリセット

#### Step 4: 他のリソースクラスのdispose実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | RenderTarget.js | `src/core/RenderTarget.js` | 384-388行目のdispose()メソッド |
| 4-2 | UniformsGroup.js | `src/core/UniformsGroup.js` | 130-134行目のdispose()メソッド |
| 4-3 | Node.js | `src/nodes/core/Node.js` | 292-296行目のdispose()メソッド |
| 4-4 | ComputeNode.js | `src/nodes/gpgpu/ComputeNode.js` | 122-126行目のdispose()メソッド |
| 4-5 | InstancedMesh.js | `src/objects/InstancedMesh.js` | 391-402行目のdispose()メソッド |
| 4-6 | CanvasTarget.js | `src/renderers/common/CanvasTarget.js` | 333-337行目のdispose()メソッド |

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

```
アプリケーションコード
    │
    └─ resource.dispose()
           │
           └─ EventDispatcher.dispatchEvent({ type: 'dispose' })
                  │
                  ├─ リスナー1.call(this, event)  // WebGLTextures等
                  │      └─ GPUリソース解放処理
                  │
                  ├─ リスナー2.call(this, event)  // キャッシュ削除等
                  │
                  └─ リスナーN.call(this, event)
```

### データフロー図

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

dispose()呼び出し ───▶ dispatchEvent() ───▶ リスナーへの通知
                           │
                           └─▶ event.target設定 ───▶ GPUリソース解放
                                                      キャッシュ削除
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EventDispatcher.js | `src/core/EventDispatcher.js` | ソース | イベント発火の基盤クラス |
| Texture.js | `src/textures/Texture.js` | ソース | テクスチャリソースの管理、disposeイベント発火 |
| Material.js | `src/materials/Material.js` | ソース | マテリアルリソースの管理、disposeイベント発火 |
| BufferGeometry.js | `src/core/BufferGeometry.js` | ソース | ジオメトリリソースの管理、disposeイベント発火 |
| Light.js | `src/lights/Light.js` | ソース | ライトリソースの管理、disposeイベント発火 |
| RenderTarget.js | `src/core/RenderTarget.js` | ソース | レンダーターゲットの管理、disposeイベント発火 |
| UniformsGroup.js | `src/core/UniformsGroup.js` | ソース | ユニフォームグループの管理、disposeイベント発火 |
| Node.js | `src/nodes/core/Node.js` | ソース | ノードシステムの基盤、disposeイベント発火 |
| ComputeNode.js | `src/nodes/gpgpu/ComputeNode.js` | ソース | コンピュートノードの管理、disposeイベント発火 |
| InstancedMesh.js | `src/objects/InstancedMesh.js` | ソース | インスタンスメッシュの管理、disposeイベント発火 |
| CanvasTarget.js | `src/renderers/common/CanvasTarget.js` | ソース | キャンバスターゲットの管理、disposeイベント発火 |
