# 通知設計書 18-postMessage通知

## 概要

本ドキュメントは、BunにおけるWebWorker間のpostMessage通知の設計を記載する。WebWorker間でメッセージを送信する機能である。

### 本通知の処理概要

postMessage通知は、メインスレッドとWebWorker間、または複数のWebWorker間でJavaScript値を送受信するためのWeb標準APIである。StructuredCloneアルゴリズムを使用してデータをシリアライズし、別スレッドで実行されているWorkerにメッセージを送信する。

**業務上の目的・背景**：JavaScriptはシングルスレッドで実行されるが、CPU集約的な処理やI/O待ちをメインスレッドから分離したい場合がある。WebWorkerを使用することで、バックグラウンドスレッドで処理を実行し、postMessageでメインスレッドと通信できる。これにより、UIのレスポンシブ性を維持しながら重い処理を実行できる。

**通知の送信タイミング**：`worker.postMessage()`（メインスレッドから）または`self.postMessage()`（Workerから）が呼び出された時点でシリアライズされ、対象スレッドのタスクキューに追加される。

**通知の受信者**：送信先のWorkerまたはメインスレッド。受信側では`message`イベントとしてハンドラに渡される。

**通知内容の概要**：SerializedScriptValueでシリアライズされたJavaScript値。オブジェクト、配列、プリミティブ値、ArrayBuffer（転送可能）、MessagePort（転送可能）などを送信可能。

**期待されるアクション**：受信側の`message`イベントハンドラ（`onmessage`または`addEventListener('message', ...)`）が発火し、デシリアライズされたデータを処理する。

## 通知種別

スレッド間通信（Web Worker postMessage）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（タスクキュー経由） |
| 優先度 | 中 |
| リトライ | なし |

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

- メインスレッド → Worker: Workerオブジェクトのimpl_ポインタ経由
- Worker → メインスレッド: グローバルスコープ経由

## 通知テンプレート

### postMessageの場合

| 項目 | 内容 |
|-----|------|
| プロトコル | スレッド間直接通信 |
| シリアライズ形式 | SerializedScriptValue（StructuredClone） |
| 転送可能オブジェクト | ArrayBuffer, MessagePort, etc. |

### メッセージ構造

```
MessageWithMessagePorts {
    message: SerializedScriptValue,
    transferredPorts: Vector<TransferredMessagePort>
}
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| messageValue | 送信するJavaScript値 | postMessage()の第1引数 | Yes |
| transfer | 転送するオブジェクトの配列 | StructuredSerializeOptions.transfer | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | worker.postMessage() | Workerが終了していない | メインスレッドからWorkerへ |
| API呼び出し | self.postMessage() | Workerが実行中 | Workerからメインスレッドへ |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Worker終了済み | TerminatedFlagが設定されている場合はInvalidStateError |
| シリアライズ不可 | DataCloneErrorをスロー |
| ポート循環参照 | 自身のポートを転送しようとした場合はDataCloneError |

## 処理フロー

### 送信フロー（メインスレッド → Worker）

```mermaid
flowchart TD
    A[worker.postMessage呼び出し] --> B{Workerが終了済み?}
    B -->|Yes| C[InvalidStateError]
    B -->|No| D[SerializedScriptValue.create]
    D --> E{シリアライズ成功?}
    E -->|No| F[DataCloneError]
    E -->|Yes| G{ポート転送あり?}
    G -->|Yes| H[MessagePort.disentanglePorts]
    G -->|No| I[MessageWithMessagePorts作成]
    H --> I
    I --> J[postTaskToWorkerGlobalScope]
    J --> K[Workerスレッドでタスク実行]
    K --> L[MessageEvent作成]
    L --> M[dispatchEvent]
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| Worker.impl_ | Zigワーカー実装へのポインタ | void* |
| Worker.m_terminationFlags | 終了状態フラグ | アトミック操作 |
| SerializedScriptValue | シリアライズされたデータ | WebKit由来 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InvalidStateError | Workerが終了済み | 例外をスロー |
| DataCloneError | シリアライズ不可能な値 | 例外をスロー |
| DataCloneError | 自身のポートを転送 | 例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0 |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

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

### 配信時間帯

プロセス稼働中は常時送信可能

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

- 同一オリジンポリシーにより、異なるオリジンのWorkerへのメッセージ送信は制限される
- transferlistを使用したArrayBufferの転送は、元のコンテキストからデータを切り離す（neutered）
- 機密データの取り扱いには注意が必要

## 備考

- Web標準のWorker APIに準拠
- Node.jsのworker_threadsモジュールとの互換性も考慮されている
- BroadcastChannelも類似の機能を提供するが、postMessageは1対1通信

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Worker.cpp | `src/bun.js/bindings/webcore/Worker.cpp` | Worker構造体、impl_ポインタ |
| 1-2 | SerializedScriptValue.cpp | `src/bun.js/bindings/webcore/SerializedScriptValue.cpp` | シリアライズ処理 |
| 1-3 | MessagePort.cpp | `src/bun.js/bindings/webcore/MessagePort.cpp` | ポート転送処理 |

**読解のコツ**: WebKitのコードベースから派生しているため、WTF（Web Template Framework）の型が多用されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Worker.cpp | `src/bun.js/bindings/webcore/Worker.cpp` | postMessage関数（234-259行目） |

**主要処理フロー**:
1. **236-237行目**: TerminatedFlagのチェック
2. **240-242行目**: SerializedScriptValue.create呼び出し
3. **244-248行目**: MessagePort.disentanglePorts呼び出し
4. **251-258行目**: postTaskToWorkerGlobalScopeでWorkerにタスク送信

#### Step 3: 受信処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Worker.cpp | `src/bun.js/bindings/webcore/Worker.cpp` | postTaskToWorkerGlobalScope内のラムダ（251-258行目） |
| 3-2 | BunWorkerGlobalScope.cpp | `src/bun.js/bindings/webcore/BunWorkerGlobalScope.cpp` | Workerグローバルスコープ |

**主要処理フロー**:
- **253行目**: MessagePort.entanglePortsで受信側ポート作成
- **254-255行目**: MessageEvent作成
- **257行目**: globalEventScope->dispatchEvent

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

```
メインスレッド: worker.postMessage(data, transfer)
    │
    └─ Worker::postMessage()
           │
           ├─ m_terminationFlagsチェック
           │      └─ TerminatedFlag → InvalidStateError
           │
           ├─ SerializedScriptValue::create()
           │      ├─ データのシリアライズ
           │      └─ transfer配列の処理
           │
           ├─ MessagePort::disentanglePorts()
           │      └─ ポートの切り離し
           │
           └─ postTaskToWorkerGlobalScope()
                  │
                  └─ [Workerスレッド]
                         │
                         ├─ MessagePort::entanglePorts()
                         │      └─ ポートの再接続
                         │
                         ├─ MessageEvent::create()
                         │
                         └─ globalEventScope->dispatchEvent()
                                │
                                └─ onmessageハンドラ実行
```

### データフロー図

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

メインスレッド           Worker.cpp                    Workerスレッド
postMessage() ───▶ SerializedScriptValue ───▶ タスクキュー ───▶ MessageEvent
    │                    │                        │              │
    │                    │                        │              │
    └─ data              └─ シリアライズ          └─ スレッド間  └─ onmessage
       + transfer           + ポート切り離し         転送            発火
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Worker.cpp | `src/bun.js/bindings/webcore/Worker.cpp` | ソース | Worker実装、postMessage処理 |
| Worker.h | `src/bun.js/bindings/webcore/Worker.h` | ヘッダー | Worker定義 |
| JSWorker.cpp | `src/bun.js/bindings/webcore/JSWorker.cpp` | ソース | JSバインディング |
| SerializedScriptValue.cpp | `src/bun.js/bindings/webcore/SerializedScriptValue.cpp` | ソース | シリアライズ処理 |
| MessagePort.cpp | `src/bun.js/bindings/webcore/MessagePort.cpp` | ソース | ポート転送処理 |
| BunWorkerGlobalScope.cpp | `src/bun.js/bindings/webcore/BunWorkerGlobalScope.cpp` | ソース | Workerグローバルスコープ |
| worker_threads.ts | `src/js/node/worker_threads.ts` | ソース | Node.js worker_threads互換 |
