はじめに
これまでNode.jsで行番号や関数名を取得する際は、わざと例外を発生させてスタックトレースから値を拾ってくる方法がよく使われていました。
Node.js v22.9.0からは getCallSite()
というAPIが使えるようになったので、今後はこっちを使う方が良さそうです。
環境
- Node.js v22.9.0
- macOS Sonoma 14.6.1
サンプルコード
リリースノートに載っていたコードを参考に、以下のようなコードを書いて動かしてみます。
import util from 'node:util'; function main() { const callSites = util.getCallSite(); console.log('Call Sites:'); callSites.forEach((callSite, index) => { console.log(`CallSite ${index + 1}:`); console.log(`Function Name: ${callSite.functionName}`); console.log(`Script Name: ${callSite.scriptName}`); console.log(`Line Number: ${callSite.lineNumber}`); console.log(`Column Number: ${callSite.column}`); console.log('-------------------'); }); } main();
package.jsonに "type": "module"
と書いてESMとして実行すると、以下のような出力が得られます。
$ npm start > get-call-site-example@0.0.1 start > node main.js Call Sites: CallSite 1: Function Name: main Script Name: file:///Users/path/to/repository/node-get-call-site-example/main.js Line Number: 4 Column Number: 26 ------------------- CallSite 2: Function Name: Script Name: file:///Users/path/to/repository/node-get-call-site-example/main.js Line Number: 17 Column Number: 1 ------------------- CallSite 3: Function Name: run Script Name: node:internal/modules/esm/module_job Line Number: 262 Column Number: 25
どうやら getCallSite()
を呼ぶと、エントリーポイントを呼び出すNode.js側の処理からコールスタックが得られるようです。
Node.jsのコードを追ってみたところ、ESMでは以下のような順序でエントリーポイントの関数が実行されるようです。
おわりに
C言語では __LINE__
や __func__
のようなマクロを使って、ログに行番号や関数名を入れることができます。
一方で、Node.jsにはそのような情報を直接提供するAPIはこれまで存在せず、例外を発生させて prepareStackTrace
から取得するというハック的な方法がよく使われていました。
v22.9.0から getCallSite()
が使えるようになったことで、より分かりやすい形で行番号や関数名を取得できるようになります。
コードの可読性の観点からも、メリットが大きい機能だと感じました。