访问V8 JavaScript中的行号(Chrome&Node.js)

Accessing line number in V8 JavaScript (Chrome & Node.js)

本文关键字:amp Node js Chrome JavaScript V8 访问      更新时间:2023-09-26

在C等语言中花费时间的JavaScript开发人员经常无法使用某些类型的内省,如日志行号,以及从什么方法调用当前方法。如果您使用的是V8(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);

以上内容将记录19

arguments.callee.caller相结合,您可以通过宏更接近于在C中获得的有用日志记录类型。

接受的答案IMO的问题是,当你想打印一些东西时,你可能正在使用记录器,在这种情况下,使用接受的解决方案将始终打印同一行:)

一些小的改变将有助于避免这种情况!

在我们的案例中,我们使用Winston进行日志记录,因此代码如下所示(请注意下面的代码注释):

/**
 * 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;
    }
};