Accessing line number in V8 JavaScript (Chrome & Node.js)
Object.defineProperty(global, '__stack', { get: function(){ var orig = Error.prepareStackTrace; Error.prepareStackTrace = function(_, stack){ return stack; }; var err = new Error; Error.captureStackTrace(err, arguments.callee); var stack = err.stack; Error.prepareStackTrace = orig; return stack; }});Object.defineProperty(global, '__line', { get: function(){ return __stack[1].getLineNumber(); }});console.log(__line);
The above will log 19
.
Combined with arguments.callee.caller
you can get closer to the type of useful logging you get in C via macros.
The problem with the accepted answer, IMO, is that when you want to print something you might be using a logger, and when that is the case, using the accepted solution will always print the same line :)
Some minor changes will help avoiding such a case!
In our case, we're using Winston for logging, so the code looks like this (pay attention to the code-comments below):
/** * Use CallSite to extract filename and number, for more info read: https://v8.dev/docs/stack-trace-api#customizing-stack-traces * @returns {string} filename and line number separated by a colon */const getFileNameAndLineNumber = () => { const oldStackTrace = Error.prepareStackTrace; try { // eslint-disable-next-line handle-callback-err Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace; Error.captureStackTrace(this); // in this example I needed to "peel" the first CallSites in order to get to the caller we're looking for // in your code, the number of stacks depends on the levels of abstractions you're using // in my code I'm stripping frames that come from logger module and winston (node_module) const callSite = this.stack.find(line => line.getFileName().indexOf('/logger/') < 0 && line.getFileName().indexOf('/node_modules/') < 0); return callSite.getFileName() + ':' + callSite.getLineNumber(); } finally { Error.prepareStackTrace = oldStackTrace; }};