# Node.js コードリーディングガイドライン

## はじめに

このガイドラインは、Node.jsのコードベースを効率的に理解するための手引きです。
JavaScript/TypeScriptやC++に精通していないエンジニアでも、段階的に学習できるよう構成されています。

**対象読者:**
- プロジェクトに新規参画するエンジニア
- 他言語からの経験者
- コードレビューを行う担当者

---

## 1. 言語基礎

> このセクションでは、Node.jsで使用されているJavaScriptとC++の基本構文と概念を解説します。

### 1.1 プログラム構造

Node.jsはJavaScriptとC++の二層構造で構成されています。

**JavaScript層（lib/ディレクトリ）:**
- ユーザー向けAPIを提供
- ECMAScript標準に準拠
- `'use strict'`モードで動作

```javascript
// ファイル: lib/fs.js:25-26
'use strict';
```

**C++層（src/ディレクトリ）:**
- V8エンジンとlibuvのバインディング
- パフォーマンスクリティカルな処理
- Node.jsのコア機能を実装

```cpp
// ファイル: src/node.cc:22-23
#include "node.h"
#include "node_config_file.h"
```

### 1.2 データ型と変数

**JavaScript:**
Node.jsではprimordialsパターンを使用し、組み込みオブジェクトのモンキーパッチを防止します。

```javascript
// ファイル: lib/fs.js:27-48
const {
  ArrayFromAsync,
  ArrayPrototypePush,
  BigIntPrototypeToString,
  Boolean,
  FunctionPrototypeCall,
  MathMax,
  Number,
  ObjectDefineProperties,
  ObjectDefineProperty,
  Promise,
  PromisePrototypeThen,
  PromiseResolve,
  ReflectApply,
  SafeMap,
  SafeSet,
  StringPrototypeCharCodeAt,
  StringPrototypeIndexOf,
  StringPrototypeSlice,
  SymbolDispose,
  uncurryThis,
} = primordials;
```

**C++:**
C++ではヘッダーガードとネームスペースを使用します。

```cpp
// ファイル: src/env.h:22-25
#ifndef SRC_ENV_H_
#define SRC_ENV_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
```

### 1.3 制御構造

**条件分岐とnullish coalescing:**

```javascript
// ファイル: lib/internal/validators.js:72-83
function parseFileMode(value, name, def) {
  value ??= def;
  if (typeof value === 'string') {
    if (RegExpPrototypeExec(octalReg, value) === null) {
      throw new ERR_INVALID_ARG_VALUE(name, value, modeDesc);
    }
    value = NumberParseInt(value, 8);
  }

  validateUint32(value, name);
  return value;
}
```

### 1.4 関数/メソッド定義

**hideStackFramesパターン:**
エラースタックトレースからバリデーション関数を隠すためのパターンです。

```javascript
// ファイル: lib/internal/validators.js:95-100
const validateInteger = hideStackFrames(
  (value, name, min = NumberMIN_SAFE_INTEGER, max = NumberMAX_SAFE_INTEGER) => {
    if (typeof value !== 'number')
      throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
    if (!NumberIsInteger(value))
      throw new ERR_OUT_OF_RANGE(name, 'an integer', value);
```

### 1.5 モジュール/インポート

**internalBinding（C++バインディング）:**

```javascript
// ファイル: lib/fs.js:50
const { fs: constants } = internalBinding('constants');
```

**内部モジュールのインポート:**

```javascript
// ファイル: lib/fs.js:62-63
const pathModule = require('path');
const { isArrayBufferView } = require('internal/util/types');
```

---

## 2. プロジェクト固有の概念

> このセクションでは、Node.js特有の概念を解説します。

### 2.1 フレームワーク固有の概念

**Primordials（原始オブジェクト）:**
ユーザーコードによるモンキーパッチの影響を受けないよう、組み込みオブジェクトのコピーを保持するメカニズムです。

```javascript
// ファイル: lib/internal/bootstrap/node.js:56-67
const {
  FunctionPrototypeCall,
  JSONParse,
  Number,
  NumberIsNaN,
  ObjectDefineProperty,
  ObjectFreeze,
  ObjectGetPrototypeOf,
  ObjectSetPrototypeOf,
  SymbolToStringTag,
  globalThis,
} = primordials;
```

**internalBinding:**
C++で実装されたNode.jsの内部機能にアクセスするためのメカニズムです。

```javascript
// ファイル: lib/internal/bootstrap/node.js:68
const config = internalBinding('config');
```

### 2.2 プロジェクト独自のパターン

**エラーコードパターン:**
Node.jsではエラーをコード化し、semver-majorバージョンアップなしにメッセージを変更できるようにしています。

```javascript
// ファイル: lib/internal/errors.js:6-11
// The whole point behind this internal module is to allow Node.js to no
// longer be forced to treat every error message change as a semver-major
// change. The NodeError classes here all expose a `code` property whose
// value statically and permanently identifies the error. While the error
// message may change, the code should not.
```

**遅延初期化パターン:**
パフォーマンスのため、重い依存関係は必要になるまで読み込みを遅延します。

```javascript
// ファイル: lib/events.js:95-99
let EventEmitterAsyncResource;
// The EventEmitterAsyncResource has to be initialized lazily because event.js
// is loaded so early in the bootstrap process, before async_hooks is available.
```

---

## 3. 命名規則

> このセクションでは、プロジェクト全体で使用される命名規則を解説します。

### 3.1 ファイル・ディレクトリ命名

| パターン | 意味 | 例 |
|---------|------|-----|
| `_xxx.js` | プライベート/内部モジュール（アンダースコアプレフィックス） | `_http_agent.js`, `_http_client.js` |
| `xxx.js` | パブリックAPI | `fs.js`, `http.js`, `events.js` |
| `xxx-inl.h` | インライン関数を含むC++ヘッダー | `env-inl.h`, `debug_utils-inl.h` |
| `xxx.cc` | C++実装ファイル | `node.cc`, `async_wrap.cc` |
| `node_xxx.h/cc` | Node.js固有のC++モジュール | `node_binding.h`, `node_realm.h` |

### 3.2 クラス・関数・変数命名

| プレフィックス/サフィックス | 意味 | 例 |
|---------------------------|------|-----|
| `k` + PascalCase | 定数（C++およびJS） | `kEmptyObject`, `kExitCode`, `kCapture` |
| `ERR_` | エラーコード | `ERR_INVALID_ARG_TYPE`, `ERR_OUT_OF_RANGE` |
| `validate` + PascalCase | バリデーション関数 | `validateInteger`, `validateString`, `validateBoolean` |
| `Safe` + ClassName | モンキーパッチ耐性のある組み込み型 | `SafeMap`, `SafeSet`, `SafeWeakMap` |
| `xxxPrototypexxx` | プロトタイプメソッドの関数化 | `ArrayPrototypePush`, `StringPrototypeSlice` |
| `_private_symbol` | プライベートシンボル（内部使用） | `module_source_private_symbol` |

### 3.3 プログラム分類一覧

| 分類 | ディレクトリ | 説明 |
|------|-------------|------|
| パブリックAPI | `lib/*.js` | ユーザーが `require()` で利用可能なモジュール |
| 内部モジュール | `lib/internal/` | 内部実装、ユーザーアクセス不可 |
| ブートストラップ | `lib/internal/bootstrap/` | Node.js起動時の初期化コード |
| メインエントリ | `lib/internal/main/` | 各実行モードのエントリーポイント |
| C++バインディング | `src/` | V8/libuv連携のネイティブコード |
| テスト | `test/` | ユニットテスト・結合テスト |

---

## 4. ディレクトリ構造

> このセクションでは、プロジェクトのディレクトリ構造を解説します。

```
node-main/
├── lib/                    # JavaScript実装（パブリックAPI + 内部モジュール）
│   ├── *.js               # パブリックAPI（fs.js, http.js, events.js等）
│   ├── _*.js              # プライベートモジュール（_http_agent.js等）
│   └── internal/          # 内部実装
│       ├── bootstrap/     # 起動時の初期化処理
│       ├── main/          # 各実行モードのエントリーポイント
│       ├── modules/       # モジュールローダー（CJS/ESM）
│       ├── errors.js      # エラー定義
│       └── validators.js  # バリデーション関数
├── src/                   # C++実装
│   ├── node.cc           # メインエントリーポイント
│   ├── env.h/cc          # Environment（実行環境）クラス
│   ├── node_binding.h    # C++バインディング定義
│   ├── api/              # パブリックC++ API
│   └── crypto/           # 暗号化関連
├── deps/                  # サードパーティ依存（V8, libuv, OpenSSL等）
├── test/                  # テストコード
│   ├── parallel/         # 並列実行可能なテスト
│   ├── sequential/       # 順次実行が必要なテスト
│   └── fixtures/         # テスト用フィクスチャ
├── doc/                   # ドキュメント
│   └── api/              # API リファレンス（Markdown）
├── tools/                 # ビルド・開発ツール
├── benchmark/             # パフォーマンスベンチマーク
└── typings/               # TypeScript型定義
```

### 各ディレクトリの役割

| ディレクトリ | 役割 | 主要ファイル |
|-------------|------|-------------|
| `lib/` | JavaScript API実装 | `fs.js`, `http.js`, `events.js` |
| `lib/internal/` | 内部実装・ユーティリティ | `errors.js`, `validators.js`, `util.js` |
| `lib/internal/bootstrap/` | 起動時初期化 | `node.js`, `realm.js` |
| `lib/internal/main/` | 実行モード別エントリー | `run_main_module.js`, `repl.js` |
| `src/` | C++コア実装 | `node.cc`, `env.cc`, `async_wrap.cc` |
| `deps/` | 外部依存ライブラリ | v8/, uv/, openssl/ |
| `test/parallel/` | 並列テスト | `test-*.js` |
| `doc/api/` | APIドキュメント | `fs.md`, `http.md` |

---

## 5. アーキテクチャ

> このセクションでは、プロジェクトのアーキテクチャパターンを解説します。

### 5.1 全体アーキテクチャ

Node.jsは「イベント駆動・非ブロッキングI/Oモデル」を採用した二層アーキテクチャです。

```
┌─────────────────────────────────────────────────────────────────┐
│                      JavaScript Layer (lib/)                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │ Public API  │  │  Internal   │  │      Bootstrap          │  │
│  │ (fs, http)  │  │  Modules    │  │ (node.js, realm.js)     │  │
│  └──────┬──────┘  └──────┬──────┘  └────────────┬────────────┘  │
│         │                │                      │                │
│         └────────────────┼──────────────────────┘                │
│                          │ internalBinding()                     │
├──────────────────────────┼──────────────────────────────────────┤
│                      C++ Layer (src/)                            │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │    Node     │  │ Environment │  │     Node Bindings       │  │
│  │   (node.cc) │  │   (env.cc)  │  │  (node_binding.h)       │  │
│  └──────┬──────┘  └──────┬──────┘  └────────────┬────────────┘  │
│         │                │                      │                │
├─────────┼────────────────┼──────────────────────┼────────────────┤
│         │           Dependencies                │                │
│  ┌──────▼──────┐  ┌──────▼──────┐  ┌───────────▼────────────┐   │
│  │     V8      │  │    libuv    │  │    OpenSSL / zlib      │   │
│  │ (JS Engine) │  │(Event Loop) │  │    (Crypto/Compress)   │   │
│  └─────────────┘  └─────────────┘  └────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘
```

### 5.2 レイヤー構成

| レイヤー | 責務 | 代表的なファイル |
|---------|------|-----------------|
| パブリックAPI | ユーザー向けインターフェース | `lib/fs.js`, `lib/http.js` |
| 内部実装 | 共通ロジック、バリデーション | `lib/internal/errors.js`, `lib/internal/validators.js` |
| ブートストラップ | 起動時初期化、グローバル設定 | `lib/internal/bootstrap/node.js` |
| C++バインディング | JS-C++ブリッジ | `src/node_binding.h`, `src/async_wrap.cc` |
| 依存ライブラリ | 低レベル機能 | `deps/v8/`, `deps/uv/` |

### 5.3 データフロー

1. **起動時フロー:**
   - `src/node.cc` がC++初期化を実行
   - `lib/internal/bootstrap/realm.js` がJSランタイムを設定
   - `lib/internal/bootstrap/node.js` がグローバルオブジェクトを初期化
   - `lib/internal/main/run_main_module.js` がユーザースクリプトを実行

2. **APIコール時フロー:**
   - ユーザーが `require('fs')` を呼び出し
   - `lib/fs.js` が処理を受け付け
   - `internalBinding('fs')` でC++層にアクセス
   - `src/node_file.cc` がlibuv経由でシステムコールを実行

---

## 6. 主要コンポーネント

> このセクションでは、主要なコンポーネントとその連携を解説します。

### 6.1 エントリーポイント

**C++エントリーポイント:**

```cpp
// ファイル: src/node.cc:22-48
#include "node.h"
#include "node_config_file.h"
#include "node_dotenv.h"
#include "node_task_runner.h"

// ========== local headers ==========

#include "debug_utils-inl.h"
#include "env-inl.h"
#include "histogram-inl.h"
#include "memory_tracker-inl.h"
#include "node_binding.h"
#include "node_builtins.h"
#include "node_errors.h"
#include "node_internals.h"
#include "node_main_instance.h"
```

**JavaScriptブートストラップ:**

```javascript
// ファイル: lib/internal/bootstrap/node.js:1-48
// Hello, and welcome to hacking node.js!
//
// This file is invoked by `Realm::BootstrapRealm()` in `src/node_realm.cc`,
// and is responsible for setting up Node.js core before main scripts
// under `lib/internal/main/` are executed.
```

### 6.2 ビジネスロジック

**モジュールローダー（CJS）:**

```javascript
// ファイル: lib/internal/modules/cjs/loader.js:80-96
// Internal properties for Module instances.
/**
 * Cached {@link Module} source string.
 */
const kModuleSource = module_source_private_symbol;
/**
 * Cached {@link Module} export names for ESM loader.
 */
const kModuleExportNames = module_export_names_private_symbol;
```

### 6.3 データアクセス

**ファイルシステムアクセス:**

```javascript
// ファイル: lib/fs.js:65-70
const binding = internalBinding('fs');

const { createBlobFromFilePath } = require('internal/blob');

const { Buffer } = require('buffer');
const { isBuffer: BufferIsBuffer } = Buffer;
```

### 6.4 ユーティリティ/共通機能

**バリデーション関数:**

```javascript
// ファイル: lib/internal/validators.js:46-56
function isInt32(value) {
  return value === (value | 0);
}

function isUint32(value) {
  return value === (value >>> 0);
}
```

**エラーハンドリング:**

```javascript
// ファイル: lib/internal/errors.js:62-67
const kIsNodeError = Symbol('kIsNodeError');

const isWindows = process.platform === 'win32';

const messages = new SafeMap();
const codes = {};
```

---

## 7. よく使われるパターン

> このセクションでは、コード内で頻出するパターンを解説します。

### パターン一覧

| パターン | 説明 | 出現頻度 | 代表的なファイル |
|---------|------|---------|-----------------|
| Primordials | 組み込みオブジェクトの保護 | 高 | 全libファイル |
| internalBinding | C++バインディング呼び出し | 高 | `lib/fs.js`, `lib/net.js` |
| hideStackFrames | スタックトレース簡略化 | 中 | `lib/internal/validators.js` |
| 遅延初期化 | パフォーマンス最適化 | 中 | `lib/events.js` |
| エラーコード | 安定したエラー識別 | 高 | `lib/internal/errors.js` |

### 各パターンの詳細

#### パターン1: Primordials（原始オブジェクトパターン）

**目的:** ユーザーコードによる組み込みオブジェクトのモンキーパッチから内部コードを保護

**実装例:**
```javascript
// ファイル: lib/internal/util.js:1-50
'use strict';

const {
  ArrayFrom,
  ArrayPrototypePush,
  ArrayPrototypeSlice,
  ArrayPrototypeSort,
  Error,
  ErrorCaptureStackTrace,
  FunctionPrototypeCall,
  // ... 多数の組み込みオブジェクト参照
} = primordials;
```

**解説:** `primordials`オブジェクトは`lib/internal/per_context/primordials.js`で定義され、V8の組み込みオブジェクトへの安全な参照を提供します。`Array.prototype.push`ではなく`ArrayPrototypePush`を使用することで、ユーザーが`Array.prototype.push`を上書きしても影響を受けません。

#### パターン2: internalBindingパターン

**目的:** JavaScript層からC++で実装された機能にアクセス

**実装例:**
```javascript
// ファイル: lib/fs.js:50, 65
const { fs: constants } = internalBinding('constants');
const binding = internalBinding('fs');
```

**解説:** `internalBinding()`は`lib/internal/bootstrap/realm.js`で定義され、C++で登録されたモジュール（`src/node_binding.h`で定義）にアクセスします。

#### パターン3: エラーコードパターン

**目的:** エラーメッセージを変更してもsemver-majorバージョンアップを不要にする

**実装例:**
```javascript
// ファイル: lib/internal/errors.js:66-67
const messages = new SafeMap();
const codes = {};
```

**解説:** エラーは`ERR_INVALID_ARG_TYPE`のようなコードで識別され、メッセージは変更可能です。これにより、ユーザーはエラーコードで条件分岐でき、Node.jsチームはメッセージを改善できます。

---

## 8. 業務フロー追跡の実践例

> このセクションでは、実際の業務フローをコードで追跡する方法を解説します。

### 8.1 フロー追跡の基本手順

1. エントリーポイントを特定
2. 処理の流れを追跡（呼び出し関係を追う）
3. データの変換を確認
4. 最終的な出力を確認

### 8.2 フロー追跡の実例

#### 例1: ファイル読み込み（fs.readFile）

**概要:** ユーザーが`fs.readFile()`を呼び出してファイル内容を取得するフロー

**処理フロー:**
```
require('fs') → fs.readFile() → binding.read() → libuv → OS システムコール
```

**詳細な追跡:**

1. **ユーザーコード**
   ```javascript
   const fs = require('fs');
   fs.readFile('/path/to/file', 'utf8', callback);
   ```

2. **パブリックAPI** (`lib/fs.js`)
   ```javascript
   // ファイル: lib/fs.js
   // fs.readFile は lib/fs.js で定義され、
   // 内部でバリデーションとbindingへの委譲を行う
   ```

3. **C++バインディング呼び出し**
   ```javascript
   // ファイル: lib/fs.js:65
   const binding = internalBinding('fs');
   ```

4. **C++実装** (`src/node_file.cc`)
   - libuvを使用してOSのファイルシステムAPIを呼び出し

#### 例2: Node.js起動フロー

**概要:** `node script.js`実行時の初期化フロー

**処理フロー:**
```
node.cc → BootstrapRealm → node.js → run_main_module.js → ユーザースクリプト
```

**詳細な追跡:**

1. **C++エントリー** (`src/node.cc`)
   ```cpp
   // ファイル: src/node.cc:22
   #include "node.h"
   ```

2. **ブートストラップ** (`lib/internal/bootstrap/node.js:85-88`)
   ```javascript
   setupProcessObject();

   setupGlobalProxy();
   setupBuffer();

   process.domain = null;
   ```

3. **メインスクリプト実行** (`lib/internal/main/run_main_module.js`)
   ```javascript
   // ファイル: lib/internal/main/run_main_module.js
   // ユーザーのスクリプトをロードして実行
   ```

### 8.3 フロー追跡チェックリスト

- [ ] エントリーポイントを特定したか
- [ ] 呼び出し関係を把握したか
- [ ] データの変換ポイントを確認したか
- [ ] エラーハンドリングを確認したか
- [ ] 最終的な出力を確認したか

---

## 9. 設計書の参照順序

> このセクションでは、プロジェクト理解のための設計書参照順序を案内します。

### 9.1 目的別ロードマップ

#### 全体像を把握したい場合
1. `README.md` - プロジェクト概要
2. `BUILDING.md` - ビルド手順
3. `doc/contributing/` - コントリビューションガイド
4. `lib/internal/bootstrap/node.js` - 起動フローのコメント

#### 特定機能を理解したい場合
1. `doc/api/xxx.md` - 対象APIのドキュメント
2. `lib/xxx.js` - パブリックAPI実装
3. `lib/internal/xxx.js` - 内部実装
4. `src/node_xxx.cc` - C++実装

#### 改修作業を行う場合
1. 対象機能の`doc/api/xxx.md`
2. 対象の`lib/`ファイル
3. `test/parallel/test-xxx-*.js` - 関連テスト
4. `CONTRIBUTING.md` - コントリビューションガイド

### 9.2 ドキュメント一覧

| ドキュメント | 概要 | 参照タイミング |
|-------------|------|---------------|
| `README.md` | プロジェクト概要 | 最初に読む |
| `BUILDING.md` | ビルド手順 | 開発環境構築時 |
| `CONTRIBUTING.md` | 貢献ガイド | PRを作成する前 |
| `doc/api/*.md` | APIリファレンス | 機能を理解したい時 |
| `onboarding.md` | 新規コントリビューター向け | 初回参加時 |
| `GOVERNANCE.md` | ガバナンスモデル | 意思決定プロセスを理解したい時 |

---

## 10. トラブルシューティング

> このセクションでは、コードリーディング時によくある問題と解決法を解説します。

### よくある疑問と回答

#### Q: primordialsとは何ですか？
A: ユーザーコードのモンキーパッチから保護された組み込みオブジェクトへの参照です。`lib/internal/per_context/primordials.js`で定義されています。`ArrayPrototypePush`は`Array.prototype.push.call`と同等ですが、ユーザーが`Array.prototype.push`を上書きしても影響を受けません。

#### Q: internalBindingとは何ですか？
A: C++で実装された内部モジュールにアクセスするための関数です。`lib/internal/bootstrap/realm.js`で定義され、`src/node_binding.h`で登録されたC++モジュールを呼び出します。

#### Q: ERR_XXXエラーコードはどこで定義されていますか？
A: `lib/internal/errors.js`で定義されています。例えば`ERR_INVALID_ARG_TYPE`は引数の型が不正な場合に使用されます。

#### Q: テストはどこにありますか？
A: `test/`ディレクトリにあります。特に`test/parallel/`には大部分のユニットテストが含まれています。

### デバッグのヒント

1. **console.logの代わりにprocess._rawDebug()を使用:**
   内部モジュールではconsole.logが使えない場合があります。

2. **--expose-internalsフラグ:**
   `node --expose-internals`でinternalモジュールにアクセス可能になります（開発目的のみ）。

3. **C++デバッグ:**
   `NODE_DEBUG`環境変数や`--debug`フラグを使用してデバッグ情報を出力できます。

---

## 付録

### A. 用語集

| 用語 | 説明 |
|-----|------|
| V8 | GoogleのJavaScriptエンジン、Node.jsのJS実行を担当 |
| libuv | 非同期I/Oライブラリ、イベントループを提供 |
| primordials | モンキーパッチ耐性のある組み込みオブジェクト参照 |
| internalBinding | C++バインディングへのアクセス関数 |
| Realm | 独立したJavaScript実行コンテキスト |
| Environment | Node.jsの実行環境を表すC++クラス |
| AsyncWrap | 非同期操作のラッパークラス |
| EventLoop | libuvが提供するイベント駆動の処理ループ |

### B. ファイル一覧

| ファイル/ディレクトリ | 説明 | 主な内容 |
|---------------------|------|---------|
| `lib/fs.js` | ファイルシステムAPI | readFile, writeFile, mkdir等 |
| `lib/http.js` | HTTPサーバー/クライアント | createServer, request等 |
| `lib/events.js` | イベントエミッター | EventEmitterクラス |
| `lib/internal/errors.js` | エラー定義 | ERR_XXXエラーコード |
| `lib/internal/validators.js` | バリデーション関数 | validateXxx関数群 |
| `lib/internal/bootstrap/node.js` | 起動初期化 | グローバル設定 |
| `src/node.cc` | C++エントリーポイント | main関数、初期化 |
| `src/env.h` | Environment定義 | 実行環境クラス |

### C. 参考資料

- [Node.js公式ドキュメント](https://nodejs.org/docs/)
- [V8 JavaScript Engine](https://v8.dev/)
- [libuv Documentation](http://docs.libuv.org/)
- [Contributing to Node.js](https://github.com/nodejs/node/blob/main/CONTRIBUTING.md)
- [Node.js API Reference](https://nodejs.org/api/)
