# 機能設計書 8-track() / trigger()

## 概要

本ドキュメントは、Vue 3のリアクティビティシステムにおける`track()`および`trigger()` APIの機能設計を記述する。これらはリアクティブプロパティの依存性追跡とエフェクトトリガーを手動で行う低レベルAPIであり、カスタムリアクティビティの実装に使用される。

### 本機能の処理概要

`track()`は現在実行中のエフェクト（activeSub）がリアクティブプロパティに依存していることを記録する。`trigger()`はリアクティブプロパティの変更を通知し、そのプロパティに依存する全てのエフェクトを再実行する。これらは`targetMap`（WeakMap<object, Map<key, Dep>>）によるグローバル依存マップを通じて動作する。

**業務上の目的・背景**：reactive()のProxyハンドラ内部で自動的に呼び出されるだけでなく、カスタムリアクティビティを実装する際に明示的に呼び出すためにAPIとして公開されている。独自のデータ構造にリアクティビティを付与する場合などに使用される。

**機能の利用シーン**：baseHandlers.tsのgetハンドラからtrack()が呼ばれ、setハンドラからtrigger()が呼ばれる。カスタムリアクティビティ実装、低レベルパフォーマンス最適化、独自のProxyハンドラ構築などに使用される。

**主要な処理内容**：
1. `track()`: targetMapからDep取得/生成し、dep.track()でSubscriberとの依存リンクを構築
2. `trigger()`: targetMapからDep取得し、操作種別（SET/ADD/DELETE/CLEAR）に応じたDep群のdep.trigger()を呼び出す
3. 配列のlength変更、ITERATE_KEY、MAP_KEY_ITERATE_KEY等の特殊依存処理
4. batch処理（startBatch/endBatch）による複数トリガーの一括実行

**関連システム・外部連携**：`@vue/reactivity`パッケージに所属。dep.tsに定義され、baseHandlers.tsやcollectionHandlers.tsから呼び出される。

**権限による制御**：shouldTrack変数とactiveSub変数がtruthyの場合のみtrack()が動作する。pauseTracking()で一時的に無効化可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 低レベル内部APIのため画面機能マッピングに直接関連する画面はない |

## 機能種別

リアクティビティ管理 / 低レベル依存性管理API

## 入力仕様

### 入力パラメータ

#### track()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| target | object | Yes | リアクティブプロパティを持つオブジェクト | - |
| type | TrackOpTypes | Yes | アクセス種別（GET, HAS, ITERATE） | TrackOpTypes列挙値 |
| key | unknown | Yes | リアクティブプロパティの識別子 | - |

#### trigger()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| target | object | Yes | リアクティブプロパティを持つオブジェクト | - |
| type | TriggerOpTypes | Yes | 操作種別（SET, ADD, DELETE, CLEAR） | TriggerOpTypes列挙値 |
| key | unknown | No | 変更されたプロパティの識別子 | - |
| newValue | unknown | No | 新しい値 | - |
| oldValue | unknown | No | 古い値 | - |
| oldTarget | Map \| Set | No | コレクションのクリア前の状態 | - |

### 入力データソース

Proxyハンドラまたはカスタムリアクティビティ実装から直接呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | 返り値なし（副作用として依存記録/エフェクトトリガーを行う） |

### 出力先

内部的にtargetMap（依存マップ）とDep（依存オブジェクト）に作用する。

## 処理フロー

### 処理シーケンス

#### track()の処理シーケンス

```
1. shouldTrack && activeSub の確認
   └─ どちらかがfalsyの場合は何もしない
2. targetMap.get(target) でdepsMapを取得
   └─ 存在しない場合: 新規Map()を作成してtargetMapに登録
3. depsMap.get(key) でDepを取得
   └─ 存在しない場合: 新規Dep()を作成してdepsMapに登録
4. dep.track() を呼び出す
   └─ activeSubとの依存リンク（Link）を構築
```

#### trigger()の処理シーケンス

```
1. targetMap.get(target) でdepsMapを取得
   └─ 存在しない場合: globalVersion++して返却
2. startBatch() でバッチ開始
3. 操作種別に応じた処理
   ├─ CLEAR: depsMapの全Depをトリガー
   ├─ 配列 + length変更: lengthとARRAY_ITERATE_KEYのDepをトリガー
   └─ その他:
       ├─ key のDepをトリガー
       ├─ 配列整数キー: ARRAY_ITERATE_KEYのDepをトリガー
       ├─ ADD: ITERATE_KEY(+Map: MAP_KEY_ITERATE_KEY)のDepをトリガー
       ├─ DELETE: ITERATE_KEY(+Map: MAP_KEY_ITERATE_KEY)のDepをトリガー
       └─ SET + Map: ITERATE_KEYのDepをトリガー
4. endBatch() でバッチ内のエフェクトを実行
```

### フローチャート

```mermaid
flowchart TD
    A[trigger target, type, key] --> B{depsMap存在?}
    B -->|No| C[globalVersion++ return]
    B -->|Yes| D[startBatch]
    D --> E{type?}
    E -->|CLEAR| F[全Depトリガー]
    E -->|Array+length| G[length+ARRAY_ITERATE Depトリガー]
    E -->|その他| H[key Depトリガー]
    H --> I{isArrayIndex?}
    I -->|Yes| J[ARRAY_ITERATE Depトリガー]
    I -->|No| K{type判定}
    J --> K
    K -->|ADD| L[ITERATE_KEY Depトリガー]
    K -->|DELETE| M[ITERATE_KEY Depトリガー]
    K -->|SET+Map| N[ITERATE_KEY Depトリガー]
    F --> O[endBatch]
    G --> O
    L --> O
    M --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 追跡ガード | shouldTrack=falseまたはactiveSub=undefinedの場合track()は何もしない | pauseTracking中など |
| BR-02 | 遅延Dep生成 | Depは初回track時に遅延的に生成される | 初めてプロパティが追跡される時 |
| BR-03 | 配列length特殊処理 | 配列のlength変更時は新length以上のインデックスのDepもトリガー | 配列 + key==='length' |
| BR-04 | ITERATE_KEY | ADD/DELETEでイテレーション依存をトリガー | for...in/Object.keys等の監視 |
| BR-05 | ARRAY_ITERATE_KEY | 配列の整数キー変更時にイテレーション依存をトリガー | 配列要素の追加・変更 |
| BR-06 | MAP_KEY_ITERATE_KEY | Map.keys()のイテレーション依存をトリガー | MapのADD/DELETE時 |
| BR-07 | batch処理 | trigger()はstartBatch/endBatchで囲まれ、複数Depの変更を一括処理 | 常時 |

### 計算ロジック

- `targetMap`: WeakMap<object, Map<key, Dep>> - グローバル依存マップ
- 特殊キー: `ITERATE_KEY`（Symbol('Object iterate')）、`MAP_KEY_ITERATE_KEY`（Symbol('Map keys iterate')）、`ARRAY_ITERATE_KEY`（Symbol('Array iterate')）

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

該当なし

## エラー処理

### エラーケース一覧

該当なし（内部APIのためユーザー向けエラーは発生しない）

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- WeakMapベースのtargetMapでGC効率を確保（オブジェクト参照がなくなれば自動削除）
- Dep.scカウンターでSubscriber数を追跡し、0になった場合はdepsMapから削除（#11979）
- batch処理で同一ティック内の複数trigger()を一括実行

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

特になし

## 備考

- track()はbaseHandlers.tsのgetハンドラ（112-114行目）から自動的に呼ばれる
- trigger()はbaseHandlers.tsのsetハンドラ（186-189行目）から自動的に呼ばれる
- `getDepFromReactive(object, key)`で外部からDepオブジェクトを取得可能
- globalVersion変数はリアクティブな変更がある度にインクリメントされ、computedの高速パスに使用される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dep.ts | `packages/reactivity/src/dep.ts` | targetMap WeakMap（240行目）。グローバル依存マップ |
| 1-2 | dep.ts | `packages/reactivity/src/dep.ts` | ITERATE_KEY, MAP_KEY_ITERATE_KEY, ARRAY_ITERATE_KEY（242-250行目）。特殊キー |
| 1-3 | constants.ts | `packages/reactivity/src/constants.ts` | TrackOpTypes（4-8行目）、TriggerOpTypes（10-15行目） |
| 1-4 | dep.ts | `packages/reactivity/src/dep.ts` | Dep.track()メソッド（108-165行目）。Link構築ロジック |

**読解のコツ**: targetMapは`WeakMap<object, Map<key, Dep>>`の2層構造。外側はオブジェクト単位、内側はプロパティ単位でDepを管理する。特殊キー（ITERATE_KEY等）はイテレーション系操作の依存追跡に使用される。

#### Step 2: track()を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dep.ts | `packages/reactivity/src/dep.ts` | track()関数（262-284行目）。targetMapからDep取得/生成、dep.track()呼び出し |

**主要処理フロー**:
- **263行目**: shouldTrack && activeSub ガード
- **264-273行目**: targetMap -> depsMap -> dep の取得/生成
- **274-283行目**: dep.track()呼び出し（デバッグ情報付き/なし）

#### Step 3: trigger()を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dep.ts | `packages/reactivity/src/dep.ts` | trigger()関数（294-389行目）。操作種別に応じたDepトリガー |

**主要処理フロー**:
- **302-307行目**: depsMap未存在の場合、globalVersion++してリターン
- **309-324行目**: run()ヘルパー関数定義。dep.trigger()をdebugInfoと共に呼び出し
- **326行目**: startBatch()
- **328-331行目**: CLEAR: depsMap全てのDepをトリガー
- **336-346行目**: 配列 + length変更: 対象Depを選択的にトリガー
- **348-384行目**: その他: key別 + 操作種別別のDepトリガー
- **388行目**: endBatch()

#### Step 4: Dep.track()とDep.trigger()を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dep.ts | `packages/reactivity/src/dep.ts` | Dep.track()（108-165行目）。Linkの作成/再利用とactiveSub.depsリストへの追加 |
| 4-2 | dep.ts | `packages/reactivity/src/dep.ts` | Dep.trigger()（167-171行目）。version++, globalVersion++, notify()呼び出し |
| 4-3 | dep.ts | `packages/reactivity/src/dep.ts` | Dep.notify()（173-204行目）。全購読者のnotify()をバッチ処理内で呼び出す |

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

```
track(target, type, key)
    |
    +-- targetMap.get(target) -> depsMap
    |       +-- depsMap.get(key) -> dep
    |               +-- dep.track()
    |                       +-- new Link(activeSub, dep)
    |                       +-- activeSub.deps/depsTail更新
    |                       +-- addSub(link)

trigger(target, type, key, newValue, oldValue, oldTarget)
    |
    +-- targetMap.get(target) -> depsMap
    +-- startBatch()
    +-- 操作種別に応じたDepの選択
    |       +-- run(dep) -> dep.trigger()
    |               +-- dep.version++
    |               +-- globalVersion++
    |               +-- dep.notify()
    |                       +-- startBatch()
    |                       +-- sub.notify() for each subscriber
    |                       +-- endBatch()
    +-- endBatch()
            +-- batchedSub/batchedComputedの処理
            +-- e.trigger() for each effect
```

### データフロー図

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

target, type, key  ───>  track()                      ──> 依存関係記録
                             |
                    targetMap[target][key] = Dep
                             |
                    dep.track()
                             |
                    Link(activeSub, dep)構築

target, type, key  ───>  trigger()                    ──> エフェクト再実行
newValue, oldValue           |
                    targetMap[target] -> depsMap
                             |
                    操作種別に応じたDep選択
                             |
                    dep.trigger() -> dep.notify()
                             |
                    batch処理 -> effect.trigger()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dep.ts | `packages/reactivity/src/dep.ts` | ソース | track()/trigger()のメイン実装。Dep/Linkクラス、targetMap |
| constants.ts | `packages/reactivity/src/constants.ts` | ソース | TrackOpTypes, TriggerOpTypes列挙型 |
| effect.ts | `packages/reactivity/src/effect.ts` | ソース | activeSub, shouldTrack, startBatch/endBatch |
| baseHandlers.ts | `packages/reactivity/src/baseHandlers.ts` | ソース | Proxyハンドラからのtrack/trigger呼び出し |
| collectionHandlers.ts | `packages/reactivity/src/collectionHandlers.ts` | ソース | コレクション用ハンドラからのtrack/trigger呼び出し |
| index.ts | `packages/reactivity/src/index.ts` | ソース | パッケージエクスポート定義 |
