# 機能設計書 15-defineExpose() / defineOptions()

## 概要

本ドキュメントは、コンポーネントの公開インターフェースとオプションを定義するコンパイラマクロ `defineExpose()` と `defineOptions()` の機能設計書である。

### 本機能の処理概要

`defineExpose()` は `<script setup>` コンポーネントから親コンポーネントに公開するプロパティを明示的に定義するマクロである。`<script setup>` コンポーネントはデフォルトで閉じた状態（クローズド）であり、テンプレートrefを通じてアクセス可能なプロパティを `defineExpose()` で明示的に指定する必要がある。

`defineOptions()` は `<script setup>` 内でComposition APIでは表現できないコンポーネントオプション（`inheritAttrs`、`name` 等）を宣言するマクロである。ただし、`props`、`emits`、`expose`、`slots` は専用マクロがあるため `defineOptions()` では宣言できない。

**業務上の目的・背景**：`<script setup>` 構文は簡潔さと型安全性を提供するが、コンポーネントの公開APIとオプションの制御が必要な場面がある。`defineExpose()` はコンポーネントのカプセル化を維持しつつ必要な情報のみを公開し、`defineOptions()` は `inheritAttrs: false` のような設定を別途 `<script>` ブロックを追加せずに行えるようにする。

**機能の利用シーン**：
- `defineExpose()`: 親コンポーネントがテンプレートrefを通じて子コンポーネントのメソッドやプロパティにアクセスする必要がある場合
- `defineOptions()`: `inheritAttrs: false` の設定、コンポーネント名の明示的指定等

**主要な処理内容**：
1. **defineExpose()のコンパイル時処理**：
   - 重複呼び出しチェック
   - `ctx.hasDefineExposeCall` フラグの設定
2. **defineOptions()のコンパイル時処理**：
   - 重複呼び出しチェック
   - 型引数の拒否チェック
   - props/emits/expose/slotsオプションの禁止チェック
   - `ctx.optionsRuntimeDecl` への設定

**関連システム・外部連携**：`@vue/compiler-sfc` パッケージでコンパイル時の変換が行われる。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | defineExpose/defineOptionsは特定の画面に限定されない汎用マクロ |

## 機能種別

コンパイラマクロ / 型定義ヘルパー

## 入力仕様

### defineExpose() の入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| exposed | Record\<string, any\> | No | 公開するプロパティのオブジェクト | - |

### defineOptions() の入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| options | ComponentOptionsBase（props/emits/expose/slots除外） | No | コンポーネントオプション | props/emits/expose/slotsを含む場合はエラー |

### 入力データソース

`<script setup>` ブロック内で開発者が直接呼び出す（コンパイラマクロ）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| defineExpose戻り値 | void | 戻り値なし |
| defineOptions戻り値 | void | 戻り値なし |

### 出力先

コンパイル後のコンポーネントオプションに展開される。

## 処理フロー

### 処理シーケンス

```
defineExpose():
1. isCallOf(node, 'defineExpose') で呼び出し検出
2. 重複呼び出しチェック
3. ctx.hasDefineExposeCall = true に設定
4. コンパイル出力にexpose設定を反映

defineOptions():
1. isCallOf(node, 'defineOptions') で呼び出し検出
2. 重複呼び出しチェック
3. 型引数の拒否チェック
4. 引数がない場合はreturn true
5. ctx.optionsRuntimeDecl に引数を設定
6. ObjectExpressionの場合、props/emits/expose/slotsプロパティを検出してエラー
```

### フローチャート

```mermaid
flowchart TD
    A[script setup解析] --> B{defineExpose検出?}
    B -->|Yes| C{重複?}
    C -->|Yes| D[エラー]
    C -->|No| E[hasDefineExposeCall = true]

    A --> F{defineOptions検出?}
    F -->|Yes| G{重複?}
    G -->|Yes| H[エラー]
    G -->|No| I{型引数あり?}
    I -->|Yes| J[エラー: 型引数不可]
    I -->|No| K{引数あり?}
    K -->|No| L[return true]
    K -->|Yes| M{props/emits/expose/slots含む?}
    M -->|Yes| N[エラー: 専用マクロを使用]
    M -->|No| O[optionsRuntimeDecl設定]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-15-01 | defineExpose単一呼び出し | defineExpose()は1回のみ呼び出し可能 | コンパイル時 |
| BR-15-02 | defineOptions単一呼び出し | defineOptions()は1回のみ呼び出し可能 | コンパイル時 |
| BR-15-03 | defineOptions型引数禁止 | defineOptions()は型パラメータを受け付けない | コンパイル時 |
| BR-15-04 | defineOptionsプロパティ制限 | props/emits/expose/slotsは専用マクロで定義する必要がある | コンパイル時 |
| BR-15-05 | script setupクローズド | defineExposeなしの場合、テンプレートrefからの内部変数アクセスは不可 | ランタイム |

### 計算ロジック

特に複雑な計算ロジックは存在しない。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コンパイルエラー | defineExpose()の重複呼び出し | 1回のみに修正 |
| - | コンパイルエラー | defineOptions()の重複呼び出し | 1回のみに修正 |
| - | コンパイルエラー | defineOptions()への型引数指定 | 型引数を除去 |
| - | コンパイルエラー | defineOptions()でpropsを宣言 | defineProps()を使用 |
| - | コンパイルエラー | defineOptions()でemitsを宣言 | defineEmits()を使用 |
| - | コンパイルエラー | defineOptions()でexposeを宣言 | defineExpose()を使用 |
| - | コンパイルエラー | defineOptions()でslotsを宣言 | defineSlots()を使用 |
| - | ランタイム警告 | `<script setup>` 外での呼び出し | `<script setup>` 内で使用する |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

特になし。コンパイル時のみの処理であり、ランタイムへの影響はない。

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

- `defineExpose()` は最小限の公開を心がけ、不必要なメソッドやプロパティを公開しないこと。

## 備考

- `defineExpose()` を使用しない `<script setup>` コンポーネントは完全に閉じた状態となり、テンプレートrefから内部の変数やメソッドにアクセスできない。
- `defineOptions()` は Vue 3.3 で追加されたマクロである。

---

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

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

### 推奨読解順序

#### Step 1: ランタイム型定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | apiSetupHelpers.ts | `packages/runtime-core/src/apiSetupHelpers.ts` | defineExpose関数のランタイムスタブ（178-184行目） |
| 1-2 | apiSetupHelpers.ts | `packages/runtime-core/src/apiSetupHelpers.ts` | defineOptions関数のランタイムスタブ（193-232行目） |

**読解のコツ**: defineOptions の型定義では、`props?: never`、`emits?: never`、`expose?: never`、`slots?: never` と明示的に禁止されている。

#### Step 2: コンパイラ側のdefineExpose処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | defineExpose.ts | `packages/compiler-sfc/src/script/defineExpose.ts` | processDefineExpose関数（7-19行目） |

**主要処理フロー**:
- **11行目**: `isCallOf(node, DEFINE_EXPOSE)` で呼び出し検出
- **12-14行目**: 重複チェック
- **15行目**: `ctx.hasDefineExposeCall = true` 設定

#### Step 3: コンパイラ側のdefineOptions処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | defineOptions.ts | `packages/compiler-sfc/src/script/defineOptions.ts` | processDefineOptions関数（12-87行目） |

**主要処理フロー**:
- **16行目**: `isCallOf(node, DEFINE_OPTIONS)` で呼び出し検出
- **19-21行目**: 重複チェック
- **22-24行目**: 型引数チェック
- **28行目**: `ctx.optionsRuntimeDecl` に引数を設定
- **34-58行目**: ObjectExpressionの場合、各プロパティを走査してprops/emits/expose/slotsを検出
- **61-84行目**: 禁止プロパティが見つかった場合のエラー出力

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

```
compileScript(sfc, options)
    │
    ├─ processDefineExpose(ctx, node)
    │      └─ ctx.hasDefineExposeCall = true
    │
    └─ processDefineOptions(ctx, node)
           ├─ unwrapTSNode(node.arguments[0])
           └─ ctx.optionsRuntimeDecl = ...
               └─ ObjectExpression走査
                   ├─ props検出 → エラー（DEFINE_PROPS使用を推奨）
                   ├─ emits検出 → エラー（DEFINE_EMITS使用を推奨）
                   ├─ expose検出 → エラー（DEFINE_EXPOSE使用を推奨）
                   └─ slots検出 → エラー（DEFINE_SLOTS使用を推奨）
```

### データフロー図

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

defineExpose({ method })  ▶ processDefineExpose()      ▶ expose: ['method']
defineOptions({            ▶ processDefineOptions()     ▶ コンポーネントオプションにマージ
  inheritAttrs: false
})
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apiSetupHelpers.ts | `packages/runtime-core/src/apiSetupHelpers.ts` | ソース | defineExpose/defineOptionsのランタイムスタブ |
| defineExpose.ts | `packages/compiler-sfc/src/script/defineExpose.ts` | ソース | defineExposeのコンパイラ処理 |
| defineOptions.ts | `packages/compiler-sfc/src/script/defineOptions.ts` | ソース | defineOptionsのコンパイラ処理 |
| context.ts | `packages/compiler-sfc/src/script/context.ts` | ソース | ScriptCompileContext |
| utils.ts | `packages/compiler-sfc/src/script/utils.ts` | ソース | isCallOf等のユーティリティ |
| compileScript.ts | `packages/compiler-sfc/src/compileScript.ts` | ソース | SFCスクリプトコンパイルのエントリーポイント |
