nodejs-core について
Node.js の内部実装やコアへの変更に取り組むコントリビューター向けのスキルです。各サブシステムの解説に加え、ビルド、Lint、テスト、コミットの要件をまとめています。
主な機能
- 01V8、libuv、コア内部の解説
- 02ネイティブアドオンの開発とデバッグ
- 03ビルド、テスト、Lintの手順
- 04Node.jsへの貢献とレビューの指針
活用シーン
- 01V8の性能や最適化解除の調査
- 02ネイティブアドオンのクラッシュやリークのデバッグ
- 03Node.jsコア変更のビルドとテスト
- 04コアへのコミットやプルリクエストの準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mcollina/ skills --skill nodejs-coreインストール後、Claude Code で/nodejs-coreを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonrules/build-and-test-workflow.mdbuild-system.mdchild-process-internals.mdcli-options.mdcommit-and-pr-guideline.mdconfigure.mdcontributing.mdcrypto-internals.mddebugging-native.mddocumentation.mdfs-internals.mdlibuv-async-io.mdlibuv-event-loop.mdlibuv-thread-pool.mdmemory-debugging.mdnapi.mdnative-memory.mdnet-internals.mdnode-addon-api.mdpre-commit-lint.mdprimordials.mdprofiling-v8.mdreviewing-prs.mdstreams-internals.mdv8-garbage-collection.mdv8-hidden-classes.mdv8-jit-compilation.mdworker-threads-internals.md詳細
使用する場面
Node.js の内部実装に関する深い専門知識が必要な場合は、このスキルを使用します。以下が該当します。
- C++ アドオンの開発
- V8 エンジンのデバッグ
- libuv イベントループの問題
- ビルドシステムの問題
- コンパイルエラー
- エンジンレベルでのパフォーマンス最適化
- Node.js コアアーキテクチャの理解
nodejs/nodeのコミットおよびプルリクエストの説明文の作成やレビュー
使用方法
詳しい説明やコード例については、個々のルールファイルを参照してください。
V8 エンジン
- rules/v8-garbage-collection.md - スカベンジャー、マークスイープ、マークコンパクト、世代別 GC
- rules/v8-hidden-classes.md - 隠しクラス、インラインキャッシュ、最適化
- rules/v8-jit-compilation.md - TurboFan、最適化/最適化解除のパターン
libuv
- rules/libuv-event-loop.md - イベントループのフェーズ、タイマー、I/O、アイドル、チェック、クローズ
- rules/libuv-thread-pool.md - スレッドプールのサイズ、ブロッキング処理、UV_THREADPOOL_SIZE
- rules/libuv-async-io.md - 非同期 I/O のパターン、ハンドル、リクエスト
ネイティブアドオン
- rules/napi.md - N-API 開発、ABI の安定性、非同期ワーカー
- rules/node-addon-api.md - C++ ラッパーのパターン、ベストプラクティス
- rules/native-memory.md - Buffer の処理、外部メモリ、メモリーリークの防止
コアモジュールの内部実装
- rules/streams-internals.md - Node.js のストリームが C++ レベルでどのように動作するか
- rules/net-internals.md - TCP/UDP の実装、ソケットの処理
- rules/fs-internals.md - libuv の fs 操作、同期処理と非同期処理
- rules/crypto-internals.md - OpenSSL の統合、パフォーマンスに関する考慮事項
- rules/child-process-internals.md - IPC、spawn、fork の実装
- rules/worker-threads-internals.md - SharedArrayBuffer、Atomics、MessageChannel
JavaScript の内部実装
- rules/primordials.md - プロトタイプ汚染を防ぐための primordials の使用(
lib/internal/では必須)
ビルドとコントリビューション
- rules/build-and-test-workflow.md - 編集・ビルド・lint・テストのサイクル(まずはこちら)
- rules/pre-commit-lint.md - すべてのコミットで必須となる lint、フォーマット、
core-validate-commitのゲート。CI を初回で通過させるために必要です - rules/configure.md - デバッグビルド、ASan、Ninja などのための
./configureフラグ - rules/build-system.md - gyp、ninja、make、クロスプラットフォームコンパイル
- rules/cli-options.md - CLI オプションの追加と実験的モジュールのゲート制御
- rules/contributing.md - Node.js コアへのコントリビュート方法とそのプロセス
- rules/commit-and-pr-guideline.md - コミットメッセージと PR 説明文のスタイル、トレーラー、DCO サインオフ、検証
- rules/reviewing-prs.md - 正確性、明瞭さ、コントリビューションの品質に関する PR のレビュー
ドキュメント
- rules/documentation.md - doc/api/*.md ファイルの更新:構成、リンクの順序、エラーのドキュメント、コード例の制約
デバッグとプロファイリング
- rules/debugging-native.md - gdb、lldb、C++ アドオンのデバッグ
- rules/profiling-v8.md - --prof、--trace-opt、--trace-deopt、フレームグラフ
- rules/memory-debugging.md - ヒープスナップショット、メモリーリークの検出
指示
Node.js へのコントリビューション文の作成
nodejs/node のコミットメッセージやプルリクエストの文面を作成するときは、
rules/commit-and-pr-guideline.md を読んでください。
サブシステム名を先頭に付けた簡潔なタイトルを使い、簡潔で事実に即した文章にしてください。まず具体的な動作を示し、変更の理由を説明してください。誇張表現、定型的な見出し、ファイルごとの説明、根拠のない主張は省いてください。
コントリビューターの DCO サインオフを含め、PR-URL: や Reviewed-By: は絶対に追加しないでください。これらは変更が取り込まれるときに追加されます。nodejs/node のチェックアウトで
npx core-validate-commit --no-validate-metadata <sha> を実行して、結果を検証してください。
必須:テストの前に再ビルドする
Node.js はコンパイル時に js2c を使って lib/ の JavaScript ファイルをバイナリに埋め込みます。**src/ または lib/ を変更した後は、テストを実行する前に必ず再ビルドしてください。**再ビルドしないと、テストは古いコードを対象に実行され、結果に意味がありません。
edit src/ or lib/ → make -j$(nproc) → make lint → then test
再ビルドの手順を絶対に省略しないでください。編集後、ビルドせずに ./node test/... を実行してはいけません。
作業を始める前に、ユーザーにビルド構成について確認してください(Make と Ninja のどちらを使うか、debug と release のどちらか、どの configure フラグを使うか)。特定の設定を前提にしてはいけません。多くの場合、すでに ./configure が実行されており、再ビルドには make -j$(nproc) だけが必要です。
必須:コミットの前に毎回 lint とフォーマットを実行する
Node.js はドラフトではないすべてのプルリクエストで Linters CI ワークフローを実行します。また、Unix では make test で lint は一切実行されません。CI の最初の実行で lint ジョブを通過し、強制プッシュともう一度の全工程に時間を費やさずに済むよう、各 git commit の前に make lint を実行してください。C++ の変更では make format-cpp も実行してください。
make -j$(nproc) # rebuild first
make lint # JS, C++, MD, docs, YAML
# C++ changes only — use the merge-base form, which is what CI checks:
CLANG_FORMAT_START="$(git merge-base HEAD upstream/main)" make format-cpp
git --no-pager diff --exit-code # must be empty
git add -A && git commit -s # -s is mandatory
npx core-validate-commit --no-validate-metadata HEAD
変更がささいに見えても、手順を省略してはいけません。また、「後で lint を直す」としてコミットしてはいけません。
**単独の make format-cpp では不十分です。**デフォルトでは CLANG_FORMAT_START=HEAD が使われ、フォーマットされるのは ステージ済み の変更だけです。一方、format-cpp CI ジョブはマージベース以降のすべてをフォーマットし、その結果差分が生じると失敗します。そのため、ブランチ内で以前にコミットした未フォーマットのコードはローカルでは通過しても、CI では失敗します。必ず、上記のマージベース形式を指定してください。
すべてのコミットは git commit -s で作成してください。-s フラグは、Developer Certificate of Origin を証明する Signed-off-by: トレーラーを追加します。これがないと core-validate-commit の signed-off-by ルールに失敗し、プルリクエストを取り込めません。サインオフには人間であるコントリビューター本人の名前とメールアドレスを使ってください。ツールや AI の識別情報でサインオフしたり、他人の情報を捏造したりしてはいけません。付け忘れた場合は、git commit --amend --signoff で修正してください。
make lint は lint-js、lint-cpp、lint-addon-docs、lint-md、lint-yaml を実行しますが、CI のすべての lint ジョブを対象にするわけではありません。Python(make lint-py)、シェル(tools/lint-sh.mjs .)、C++ のフォーマット、コミットメッセージの検証は別のジョブです。すべてのゲートと CI ジョブに対応するコマンドについては、rules/pre-commit-lint.md を参照してください。
すべてのコミットメッセージを core-validate-commit で検証してください。必ず --no-validate-metadata を指定してください。メタデータ検証はデフォルトで有効になっており、変更が取り込まれた後にのみ存在するトレーラーを要求するためです。**自分が作成するコミットに PR-URL: や Reviewed-By: を絶対に追加しないでください。**これらは変更が取り込まれるときに追加されます。
configure フラグ、lint のターゲット、テストコマンドを含むワークフロー全体については、rules/build-and-test-workflow.md を参照してください。
コア知識領域
以下の領域にわたって、Node.js 内部構造に関する深い知識を活用してください。
- コアアーキテクチャ:Node.js のコアモジュールとその C++ 実装、V8 の GC と JIT、libuv のイベントループの仕組み、スレッドプールの動作、起動/モジュール読み込みのライフサイクル
- ネイティブ開発:N-API、node-addon-api、NAN を使ったアドオン開発、V8 C++ API のハンドル管理、メモリ安全性、gdb/lldb を使ったネイティブデバッグ
- ビルドシステム:node-gyp、gyp、ninja、make、クロスプラットフォームコンパイル、リンカーエラー、依存関係の問題、プラットフォーム固有の考慮事項(Windows、macOS、Linux、組み込み環境)
- パフォーマンスとデバッグ:イベントループのプロファイリング、JS およびネイティブコードのメモリリーク検出、CPU フレームグラフ、V8 の最適化/最適化解除のトレース
デバッグ用クイックリファレンスコマンド
V8 の最適化トレース:
node --trace-opt --trace-deopt script.js
# Checkpoint: confirm no unexpected deoptimization warnings before proceeding to profiling
node --prof script.js && node --prof-process isolate-*.log > processed.txt
イベントループの遅延検出:
node --trace-event-categories v8,node,node.async_hooks script.js
ネイティブアドオンのデバッグ(gdb):
gdb --args node --napi-modules ./build/Release/addon.node
# Inside gdb:
run
bt # backtrace on crash
# Checkpoint: verify backtrace shows the expected call site before applying a fix
メモリリーク検出用ヒープスナップショット:
node --inspect script.js # then open chrome://inspect, take heap snapshot
# Checkpoint: compare two consecutive heap snapshots to confirm leak growth before and after the fix; run valgrind --leak-check=full node addon_test.js to confirm no native leaks remain
Node.js 固有の診断決定木
ネイティブアドオンのセグメンテーション違反/クラッシュ:
node --napi-modulesでクラッシュを再現できますか? →gdbを実行し、btを取得しますbtは V8 のハンドルスコープの問題を示していますか? → アドオンでのHandleScope/EscapableHandleScopeの使用状況を確認します- libuv のコールバックを示していますか? → 非同期ハンドルのライフタイムと
uv_close()の順序を調べます - 明確な C++ フレームがありませんか? → ネイティブバインディングに渡された JS 側の型の不一致を確認します
V8 の最適化解除/パフォーマンス低下:
--trace-opt --trace-deoptを実行します → 最適化解除された関数とその理由(例:「not a Smi」、「wrong map」)を特定します- 確認事項:実行ごとに同じ関数が一貫して最適化解除されることを確認します
- 隠しクラスの遷移(
--trace-ic)を調べ、プロパティの追加順序または型の不整合を修正します --trace-optを再実行し、関数が最適化されたことを確認します
ビルド失敗(node-gyp/binding.gyp):
- ヘッダーが不足していますか? →
binding.gypのinclude_dirsと Node.js ヘッダーのインストール状況を確認します - リンカーエラーですか? →
librariesとlink_settingsのエントリーを確認し、ABI の互換性を確かめます - プラットフォーム固有の問題ですか? → Windows/macOS/Linux の違いについて
rules/build-system.mdを参照します
JavaScript レベルとネイティブレベルの両方の原因を常に考慮し、パフォーマンスへの影響とトレードオフを説明し、取り上げる実験的機能の安定性ステータスを明示してください。コード例では Node.js 内部構造に関するパターンを示し、開発者が見落としがちな典型的なエッジケースにも配慮した、本番環境で使用できるコードにしてください。