# 機能設計書 101-node:assert

## 概要

本ドキュメントは、BunにおけるNode.js互換の`node:assert`モジュールの機能設計を記述したものである。このモジュールは、テストやデバッグのための値の検証（アサーション）機能を提供する。

### 本機能の処理概要

`node:assert`モジュールは、値の等価性チェックや条件検証を行うアサーション関数群を提供する。アサーションが失敗した場合は、詳細な差分情報を含む`AssertionError`をスローする。

**業務上の目的・背景**：アプリケーションの品質保証において、期待される値と実際の値が一致することを検証する仕組みは不可欠である。`node:assert`モジュールは、Node.js標準のアサーションAPIを提供し、既存のNode.jsプロジェクトがBunに移行する際の互換性を確保する。また、テストフレームワークの基盤としても利用される。

**機能の利用シーン**：
- 単体テストでの値の検証
- 関数の事前条件・事後条件のチェック
- デバッグ時の値の確認
- 例外発生の検証

**主要な処理内容**：
1. 浅い等価性チェック（`equal`/`notEqual`）：`==`演算子による比較
2. 厳密な等価性チェック（`strictEqual`/`notStrictEqual`）：`Object.is()`による比較
3. 深い等価性チェック（`deepEqual`/`deepStrictEqual`）：オブジェクトの再帰的比較
4. 部分的等価性チェック（`partialDeepStrictEqual`）：サブセット比較
5. 例外検証（`throws`/`rejects`/`doesNotThrow`/`doesNotReject`）
6. 正規表現マッチング（`match`/`doesNotMatch`）
7. 失敗時のMyers差分アルゴリズムによるわかりやすいエラー表示

**関連システム・外部連携**：
- `Bun.deepEquals()`: 深い等価性比較のネイティブ実装
- `node:util/types`: 型判定ユーティリティ
- `internal/assert/assertion_error`: AssertionErrorクラス

**権限による制御**：特になし（全ユーザーが利用可能）

## 関連画面

本機能はCLIモジュールであり、直接的な関連画面は存在しない。テストランナー（`bun test`）経由で間接的に利用される。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

バリデーション / テストユーティリティ

## 入力仕様

### 入力パラメータ

主要なアサーション関数の入力パラメータを以下に示す。

#### `assert(value, message)` / `assert.ok(value, message)`

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | unknown | Yes | 真偽値として評価される値 | - |
| message | string \| Error | No | アサーション失敗時のメッセージ | - |

#### `assert.strictEqual(actual, expected, message)`

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| actual | unknown | Yes | 実際の値 | - |
| expected | unknown | Yes | 期待される値 | - |
| message | string \| Error | No | アサーション失敗時のメッセージ | - |

#### `assert.deepStrictEqual(actual, expected, message)`

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| actual | unknown | Yes | 実際の値 | - |
| expected | unknown | Yes | 期待される値 | - |
| message | string \| Error | No | アサーション失敗時のメッセージ | - |

#### `assert.throws(fn, error, message)`

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fn | () => void | Yes | 例外をスローする関数 | 関数であること |
| error | Error \| RegExp \| Function \| Object | No | 期待されるエラーの検証条件 | - |
| message | string \| Error | No | アサーション失敗時のメッセージ | - |

### 入力データソース

- 関数呼び出しの引数として直接渡される

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| void | void | アサーション成功時は値を返さない |
| AssertionError | Error | アサーション失敗時にスローされるエラー |

### AssertionErrorの構造

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| actual | unknown | 実際の値 |
| expected | unknown | 期待される値 |
| operator | string | 使用された比較演算子 |
| message | string | エラーメッセージ（差分表示含む） |
| generatedMessage | boolean | メッセージが自動生成されたかどうか |
| code | string | 'ERR_ASSERTION' |
| name | string | 'AssertionError' |

### 出力先

- アサーション成功時：何も出力しない
- アサーション失敗時：`AssertionError`を例外としてスロー

## 処理フロー

### 処理シーケンス

```
1. 入力パラメータの検証
   └─ 必須引数の存在確認、型チェック
2. 比較処理の実行
   └─ 演算子に応じた比較ロジックの適用
3. 結果判定
   └─ 条件を満たす場合：正常終了（void）
   └─ 条件を満たさない場合：AssertionErrorを生成
4. エラーメッセージの生成（失敗時）
   └─ Myers差分アルゴリズムによる差分計算
   └─ カラー表示対応のフォーマット
5. 例外スロー（失敗時）
   └─ AssertionErrorをスロー
```

### フローチャート

```mermaid
flowchart TD
    A[アサーション関数呼び出し] --> B{引数の検証}
    B -->|不正| C[TypeError/ERR_MISSING_ARGS]
    B -->|正常| D{比較処理}
    D -->|一致| E[正常終了 void]
    D -->|不一致| F[AssertionError生成]
    F --> G[Myers差分計算]
    G --> H[エラーメッセージ生成]
    H --> I[AssertionErrorをスロー]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-101 | 厳密等価性 | `Object.is()`を使用して比較 | strictEqual/notStrictEqual |
| BR-102 | 浅い等価性 | `==`演算子（型変換あり）を使用 | equal/notEqual |
| BR-103 | 深い等価性（厳密） | プロトタイプ、プロパティの型も比較 | deepStrictEqual |
| BR-104 | 深い等価性（緩い） | 型変換を許容した再帰比較 | deepEqual |
| BR-105 | NaN比較 | NaN同士は等価と見なす | equal/notEqual |
| BR-106 | 部分一致 | expectedがactualのサブセットであればOK | partialDeepStrictEqual |

### 計算ロジック

**深い等価性比較（Bun.deepEquals）**：
- `Bun.deepEquals(a, b, strict)`を使用
- strictがtrueの場合：型とプロトタイプも厳密に比較
- strictがfalseの場合：値のみを比較

**Myers差分アルゴリズム**：
- 文字列の最小編集距離を計算
- 挿入（+）、削除（-）、等価（空白）で差分を表現
- `src/bun.js/node/assert/myers_diff.zig`で実装

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_ASSERTION | AssertionError | アサーション条件が不成立 | 期待値と実際の値を確認 |
| ERR_MISSING_ARGS | TypeError | 必須引数が不足 | 引数を正しく指定 |
| ERR_INVALID_ARG_TYPE | TypeError | 引数の型が不正 | 正しい型の引数を指定 |
| ERR_INVALID_ARG_VALUE | TypeError | 引数の値が不正 | 有効な値を指定 |
| ERR_AMBIGUOUS_ARGUMENT | TypeError | エラーとメッセージが同一 | 異なる値を指定 |
| ERR_INVALID_RETURN_VALUE | TypeError | promiseFnがPromiseを返さない | Promiseを返す関数を指定 |

### リトライ仕様

本機能はリトライを行わない（即座に結果を返す）。

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

本機能はトランザクションを使用しない。

## パフォーマンス要件

- 比較処理は同期的に実行され、即座に結果を返す
- 深い比較では再帰的な処理が行われるため、深くネストしたオブジェクトでは処理時間が増加
- Myers差分計算は入力サイズに応じて計算量が増加（O((M+N)*D)、M,Nは入力長、Dは差分数）

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

- 特に機密情報を扱う処理はない
- エラーメッセージに値が含まれるため、機密情報をアサーション引数に渡さないよう注意

## 備考

- `assert.strict`は厳密モードのアサーション関数を提供（equal->strictEqual等）
- `assert/strict`モジュールは`assert.strict`と同等
- `CallTracker`はNode.js v20で非推奨（DEP0173）

---

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

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

### 推奨読解順序

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

まず、AssertionErrorクラスの構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | assertion_error.ts | `src/js/internal/assert/assertion_error.ts` | AssertionErrorクラスの定義、エラーメッセージ生成ロジック |

**読解のコツ**:
- **38-49行目**: `kReadableOperator`オブジェクトで各演算子のエラーメッセージテンプレートを定義
- **243-426行目**: `AssertionError`クラスのコンストラクタでメッセージ生成ロジックを実装
- **183-230行目**: `createErrDiff`関数でMyers差分を使用した差分メッセージを生成

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

メインのassertモジュールの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | assert.ts | `src/js/node/assert.ts` | 全アサーション関数のエントリーポイント |

**主要処理フロー**:
1. **60-65行目**: `isDeepEqual`と`isDeepStrictEqual`は`Bun.deepEquals()`を使用
2. **88行目**: `assert`関数は`ok`関数のエイリアス
3. **99-159行目**: `fail`関数でアサーション失敗時の処理を実装
4. **184-188行目**: `ok`関数で真偽値チェック
5. **198-212行目**: `equal`関数で`==`による比較
6. **291-304行目**: `deepStrictEqual`関数で深い等価性チェック
7. **337-350行目**: `strictEqual`関数で`Object.is()`による比較
8. **540-555行目**: `partialDeepStrictEqual`関数で部分一致チェック
9. **842-844行目**: `throws`関数で例外検証
10. **1023-1032行目**: `strict`モードの定義

#### Step 3: 深い等価性比較のネイティブ実装を理解する

Zigで実装されたバインディングを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | node_assert.zig | `src/bun.js/node/node_assert.zig` | Myers差分計算のZig実装 |

**主要処理フロー**:
- **13-65行目**: `myersDiff`関数で文字列の差分を計算
- **67-77行目**: `diffChars`関数で文字単位の差分
- **79-102行目**: `diffLines`関数で行単位の差分

#### Step 4: Myers差分アルゴリズムの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | myers_diff.zig | `src/bun.js/node/assert/myers_diff.zig` | Myers差分アルゴリズムの詳細実装 |

**主要処理フロー**:
- **10-22行目**: `Options`構造体で設定を定義
- **67-98行目**: `Differ`関数で比較器を生成
- **122-216行目**: `diff`関数で最短編集距離を計算
- **218-279行目**: `backtrack`関数で差分リストを生成
- **373-386行目**: `DiffKind`列挙型（insert/delete/equal）

#### Step 5: JavaScriptバインディングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | node_assert_binding.zig | `src/bun.js/node/node_assert_binding.zig` | JSからZig関数を呼び出すバインディング |

**主要処理フロー**:
- **10-49行目**: `myersDiff`関数でJavaScriptからの呼び出しを処理
- **67-77行目**: `generate`関数でエクスポートオブジェクトを生成

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

```
JavaScript (assert.ts)
    │
    ├─ assert.ok(value)
    │      └─ innerOk()
    │
    ├─ assert.strictEqual(actual, expected)
    │      └─ Object.is()
    │      └─ innerFail() [失敗時]
    │             └─ AssertionError
    │
    ├─ assert.deepStrictEqual(actual, expected)
    │      └─ Bun.deepEquals(a, b, true)  [ネイティブ]
    │      └─ innerFail() [失敗時]
    │             └─ AssertionError
    │                    └─ createErrDiff()
    │                           └─ myersDiff() [Zig実装]
    │                                  └─ Differ.diff()
    │                                  └─ backtrack()
    │
    └─ assert.throws(fn, error)
           └─ getActual(fn)
           └─ expectsError()
                  └─ expectedException()
```

### データフロー図

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

actual, expected ──────▶ 比較ロジック選択 ────────────▶ void (成功)
                              │
                              ├─ strictEqual: Object.is()
                              ├─ deepStrictEqual: Bun.deepEquals()
                              ├─ equal: == 演算子
                              └─ deepEqual: Bun.deepEquals(false)
                              │
                              ▼ [不一致時]
                         差分計算
                              │
                              ├─ inspectValue() で文字列化
                              └─ myersDiff() で差分計算
                              │
                              ▼
                         AssertionError生成 ─────────▶ throw AssertionError
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| assert.ts | `src/js/node/assert.ts` | ソース | メインのassertモジュール実装 |
| assert.strict.ts | `src/js/node/assert.strict.ts` | ソース | strict版のエクスポート |
| assertion_error.ts | `src/js/internal/assert/assertion_error.ts` | ソース | AssertionErrorクラス定義 |
| node_assert.zig | `src/bun.js/node/node_assert.zig` | ソース | Myers差分のZig実装 |
| node_assert_binding.zig | `src/bun.js/node/node_assert_binding.zig` | ソース | JSバインディング |
| myers_diff.zig | `src/bun.js/node/assert/myers_diff.zig` | ソース | Myers差分アルゴリズム |
| assert.js | `src/node-fallbacks/assert.js` | フォールバック | Node互換フォールバック |
