# 機能設計書 78-Blob

## 概要

本ドキュメントは、BunのBlob機能の機能設計を記述する。BlobはWHATWG File API標準に準拠したバイナリデータを表現するオブジェクトを提供する。

### 本機能の処理概要

BunのBlob APIは、不変のバイナリデータを表現するWeb標準APIを提供する。メモリ上のバイト列、ファイルシステム上のファイル、S3ストレージなど複数のバッキングストアをサポートし、統一されたインターフェースでアクセス可能。

**業務上の目的・背景**：バイナリデータの効率的な表現と操作、ファイルアップロード/ダウンロード、HTTPリクエスト/レスポンスのボディ処理など、バイナリデータを扱うすべての場面で使用される。Web標準互換により、ブラウザとサーバーでコードを共有可能。

**機能の利用シーン**：
- ファイルアップロード処理
- HTTPレスポンスボディの構築
- バイナリデータの変換（ArrayBuffer、テキスト、JSON）
- FormDataでのファイル送信
- S3ストレージとの連携
- ファイルI/O操作

**主要な処理内容**：
1. Blobオブジェクトの生成（メモリ、ファイル、S3）
2. データの読み取り（text(), arrayBuffer(), json(), bytes()）
3. ReadableStreamへの変換（stream()）
4. Blobのスライス操作（slice()）
5. 構造化クローン対応（postMessage転送）

**関連システム・外部連携**：Bun.file、Response、Request、FormData、S3クライアントと連携。ファイルシステム、S3ストレージと連携。

**権限による制御**：特に権限による制御は行われない。すべてのコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | コマンドライン/API経由での利用（画面なし） |

## 機能種別

バイナリデータ処理 / Web標準API

## 入力仕様

### Blobコンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| blobParts | Array | No | Blobを構成するデータの配列 | - |
| options | BlobPropertyBag | No | オプション設定 | - |

### BlobPropertyBagオプション

| オプション | 型 | 説明 |
|-----------|-----|------|
| type | string | MIMEタイプ（ASCII文字列、小文字化される） |

### Blob.Store.Data（内部バッキングストア）

| バリアント | 説明 |
|-----------|------|
| bytes | メモリ上のバイト列 |
| file | ファイルシステム上のファイル |
| s3 | S3ストレージ上のオブジェクト |

### 入力データソース

API呼び出し時の引数として直接指定。blobPartsには以下を含められる：
- ArrayBuffer / TypedArray
- Blob
- string
- URLSearchParams
- FormData

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| blob | Blob | Blobオブジェクト |

### Blobプロパティ

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| size | number | Blobのサイズ（バイト数） |
| type | string | MIMEタイプ |

### Blobメソッド

| メソッド | 戻り値 | 説明 |
|---------|--------|------|
| text() | Promise<string> | テキストとして取得 |
| arrayBuffer() | Promise<ArrayBuffer> | ArrayBufferとして取得 |
| json() | Promise<any> | JSONとしてパース |
| bytes() | Promise<Uint8Array> | Uint8Arrayとして取得 |
| stream() | ReadableStream | ReadableStreamを取得 |
| slice(start?, end?, type?) | Blob | 部分Blobを作成 |
| formData() | Promise<FormData> | FormDataとしてパース |

### Fileオブジェクト（Blobの拡張）

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| name | string | ファイル名 |
| lastModified | number | 最終更新日時（ミリ秒） |

### 出力先

Blobオブジェクトとして返却。

## 処理フロー

### 処理シーケンス（Blob作成）

```
1. Blobコンストラクタ呼び出し
   └─ blobPartsを解析
2. Storeの作成
   └─ bytes/file/s3に応じた初期化
3. Blobオブジェクト構築
   └─ size, content_type設定
4. 参照カウント設定
   └─ ref_count = 1
```

### フローチャート

```mermaid
flowchart TD
    A[new Blob] --> B{引数あり?}
    B -->|No| C[空のBlob作成]
    B -->|Yes| D[blobPartsを解析]
    D --> E[Storeを作成]
    E --> F{optionsあり?}
    F -->|Yes| G[typeを設定]
    F -->|No| H[Blob完成]
    G --> H
    C --> H

    subgraph データ取得
    I[text/arrayBuffer/json/bytes] --> J{Store種別}
    J -->|bytes| K[メモリから読み取り]
    J -->|file| L[ファイルから読み取り]
    J -->|s3| M[S3から読み取り]
    K --> N[Promise resolve]
    L --> N
    M --> N
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | イミュータブル | Blobの内容は変更不可 | 常時 |
| BR-78-02 | サイズ上限 | u52で表現可能な9ペタバイトまで対応 | 常時 |
| BR-78-03 | 参照カウント | Store共有時は参照カウントで管理 | 常時 |
| BR-78-04 | 遅延読み込み | ファイル/S3の内容は実際にアクセスするまで読み込まない | file/s3 |

### 計算ロジック

なし

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

### 操作別データベース影響一覧

なし（データベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | Error | detachedなBlobにアクセス | 新しいBlobを作成 |
| Error | Error | ファイル読み取りエラー | ファイルパスを確認 |
| Error | Error | S3アクセスエラー | 認証情報を確認 |
| SyntaxError | Error | json()でパース失敗 | JSONフォーマットを確認 |

### リトライ仕様

なし（呼び出し側で制御）

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

なし

## パフォーマンス要件

- 参照カウントによるメモリ効率的な管理
- ファイルバッキングでの遅延読み込み
- Linuxでのmemfdによる大規模データの効率的処理
- sliceでのゼロコピー操作

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

- Blobデータはイミュータブルで安全
- S3アクセスには認証情報が必要
- 構造化クローンでWorker間転送可能

## 備考

バッキングストアの種類：
- **bytes**：メモリ上のバイト列、stored_nameでファイル名を保持可能
- **file**：ファイルシステム上のファイル、パスまたはFDで参照
- **s3**：S3互換ストレージ、認証情報とオプションを保持

Bun.file()で作成されるBlobは内部的にfileストアを使用。

---

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

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

### 推奨読解順序

#### Step 1: Blob構造体を理解する

Blobの基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Blob.zig | `src/bun.js/webcore/Blob.zig` | Blob構造体定義（26-68行目） |
| 1-2 | Blob.zig | `src/bun.js/webcore/Blob.zig` | SizeType定義（60-61行目） |

**読解のコツ**: Blobはsize, offset, store, content_type, nameなどのフィールドを持つ。SizeTypeはu52で9PBまで対応。

**主要処理フロー**:
1. **26-52行目**: Blobフィールド（size, offset, store, content_type等）
2. **54行目**: Ref型でExternalSharedによる参照管理
3. **60-61行目**: SizeType（u52）とmax_size定義

#### Step 2: Storeを理解する

バッキングストアの実装。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Store.zig | `src/bun.js/webcore/blob/Store.zig` | Store構造体（1-35行目） |
| 2-2 | Store.zig | `src/bun.js/webcore/blob/Store.zig` | Data union型（37-41行目） |
| 2-3 | Store.zig | `src/bun.js/webcore/blob/Store.zig` | File構造体（250-288行目） |
| 2-4 | Store.zig | `src/bun.js/webcore/blob/Store.zig` | S3構造体（291-327行目） |

**主要処理フロー**:
- **1-35行目**: Store構造体（data, mime_type, ref_count, allocator）
- **37-41行目**: Data union（bytes, file, s3）
- **43-50行目**: ref/hasOneRef関数
- **171-177行目**: deref関数（参照カウント減少、0でdeinit）

#### Step 3: コンストラクタを理解する

Blobの生成処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Blob.zig | `src/bun.js/webcore/Blob.zig` | constructor関数（3236-3290行目） |
| 3-2 | Blob.zig | `src/bun.js/webcore/Blob.zig` | init関数（3319-3329行目） |
| 3-3 | Blob.zig | `src/bun.js/webcore/Blob.zig` | initWithStore関数（3391-3401行目） |

**主要処理フロー**:
- **3236-3246行目**: 引数なしの場合は空のBlob
- **3247-3286行目**: blobPartsからBlobを構築、optionsでtypeを設定
- **3319-3329行目**: initでbytesからBlobを作成

#### Step 4: データ取得メソッドを理解する

text(), arrayBuffer(), json()等の実装。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Blob.zig | `src/bun.js/webcore/Blob.zig` | getText関数（2079-2085行目） |
| 4-2 | Blob.zig | `src/bun.js/webcore/Blob.zig` | getArrayBuffer関数（2145-2151行目） |
| 4-3 | Blob.zig | `src/bun.js/webcore/Blob.zig` | getJSON関数（2107-2113行目） |
| 4-4 | Blob.zig | `src/bun.js/webcore/Blob.zig` | getStream関数（2014-2054行目） |

**主要処理フロー**:
- **2079-2095行目**: getText→getTextClone→toStringをPromiseでラップ
- **2145-2151行目**: getArrayBuffer→getArrayBufferClone→toArrayBufferをPromiseでラップ
- **2014-2054行目**: getStreamでReadableStreamを作成、FDストアはキャッシュ

#### Step 5: ファイル/S3読み取りを理解する

非同期読み取り処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Blob.zig | `src/bun.js/webcore/Blob.zig` | doReadFile関数（125-170行目） |
| 5-2 | Blob.zig | `src/bun.js/webcore/Blob.zig` | doReadFromS3関数（114-123行目） |

**主要処理フロー**:
- **125-170行目**: doReadFileでファイル読み取り（Windows: ReadFileUV、その他: ReadFile）
- **114-123行目**: doReadFromS3でS3BlobDownloadTaskを開始

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

```
new Blob(blobParts, options)
    │
    ├─ constructor() [エントリーポイント]
    │      ├─ get() でblobPartsを解析
    │      ├─ Store.init() でストア作成
    │      └─ options.typeを設定
    │
    └─ Blob.new() で参照カウント設定

blob.text()
    │
    ├─ getText()
    │      └─ getTextClone()
    │             └─ JSPromise.wrap(toString)
    │
    └─ toString()
           ├─ store.data == .bytes → 直接変換
           ├─ store.data == .file → doReadFile()
           │      └─ ReadFile / ReadFileUV
           └─ store.data == .s3 → doReadFromS3()
                  └─ S3BlobDownloadTask

blob.stream()
    │
    └─ getStream()
           └─ ReadableStream.fromBlobCopyRef()

Store管理:
Store
    ├─ data: Data (union)
    │      ├─ bytes: Bytes
    │      │      └─ slice, stored_name, allocator
    │      ├─ file: File
    │      │      └─ pathlike, mime_type, mode
    │      └─ s3: S3
    │             └─ pathlike, credentials, options
    │
    ├─ ref() → ref_count += 1
    └─ deref() → ref_count -= 1, 0ならdeinit()
```

### データフロー図

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

new Blob([...])    ───▶  constructor()
                         ├─ blobParts解析
                         └─ Store作成
                                │
                                ▼
                         Blob {
                           size, offset,
                           store, content_type
                         }                        ───▶   Blob

blob.text()        ───▶  getText()
                         └─ toString()
                                │
                                ▼
                         Store読み取り
                         ├─ bytes: 直接
                         ├─ file: ReadFile
                         └─ s3: S3Download
                                │
                                ▼
                         文字列変換               ───▶   Promise<string>

blob.stream()      ───▶  getStream()
                         └─ ReadableStream
                            .fromBlobCopyRef()   ───▶   ReadableStream

blob.slice()       ───▶  offset/sizeを
                         調整した新Blob
                         └─ Store共有（ref）     ───▶   Blob
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Blob.zig | `src/bun.js/webcore/Blob.zig` | ソース | Blobメイン実装 |
| Store.zig | `src/bun.js/webcore/blob/Store.zig` | ソース | バッキングストア実装 |
| read_file.zig | `src/bun.js/webcore/blob/read_file.zig` | ソース | ファイル読み取り |
| write_file.zig | `src/bun.js/webcore/blob/write_file.zig` | ソース | ファイル書き込み |
| copy_file.zig | `src/bun.js/webcore/blob/copy_file.zig` | ソース | ファイルコピー |
| JSBlob.classes.ts | `src/bun.js/api/classes/JSBlob.classes.ts` | 定義 | クラス定義（もし存在） |
| Response.zig | `src/bun.js/webcore/Response.zig` | ソース | Response連携 |
| Request.zig | `src/bun.js/webcore/Request.zig` | ソース | Request連携 |
