node icon indicating copy to clipboard operation
node copied to clipboard

[22.9.0] `util.getCallSite()` doesn't report original line number for TS files

Open bruce-c-liu opened this issue 5 months ago • 6 comments

What is the problem this feature will solve?

Lot of people use tools like ts-node or tsx when developing locally or even in production. The new util.getCallSite() function doesn't seem to report the line number from the original typescript file. Rather, it reports the transformed version of the file (e.g. by tsx) with types stripped out/minified/etc?

Example

expected: line 20, col 12 received: line 1, col 15123

What is the feature you are proposing to solve the problem?

Have util.getCallSite() report original line number for TS files.

What alternatives have you considered?

I currently have a custom function that does report the correct line number for the original typescript file. However, I would like to use the Node version if possible so I don't have to maintain this.

const ORIGINAL_STACK_TRACE_LIMIT = Error.stackTraceLimit;

/**
 * Returns information about the indicated frame in the stack trace.
 * frameIndex = 0 corresponds to the function that calls stackedTrace().
 *
 * Below sample values assume frameIndex = 1.
 * Inspiration: https://www.npmjs.com/package/callsites/v/3.1.0
 */
export function stackTrace(frameIndex = 0) {
  // Optimization: Adjust stackTraceLimit to the minimum depth required to get the desired frameIndex.
  // This significantly reduces the depth of the produced stack trace. (Node 22's default limit is 10)
  Error.stackTraceLimit = frameIndex + 1;
  const error = { stack: "" };

  // https://nodejs.org/api/errors.html#errorcapturestacktracetargetobject-constructoropt
  // Creates a `.stack` property on provided object
  Error.captureStackTrace(
    error,
    stackTrace // don't include the stackTrace() function itself in the trace
  );
  Error.stackTraceLimit = ORIGINAL_STACK_TRACE_LIMIT; // restore original stackTraceLimit

  // "Error
  //   at DerivedLogger.logger.<computed> (/Users/bruce.liu/Desktop/ai-search/server/logging/logger.ts:50:20)
  //   at Server.<anonymous> (/Users/bruce.liu/Desktop/ai-search/server/index.ts:58:12)"
  const stackErrorMsg = error.stack;

  // [
  //   "at DerivedLogger.logger.<computed> (/Users/bruce.liu/Desktop/ai-search/server/logging/logger.ts:50:20)",
  //   "at Server.<anonymous> (/Users/bruce.liu/Desktop/ai-search/server/index.ts:58:12)"
  // ]
  const frames = stackErrorMsg.split("\n").slice(1);

  // "at Server.<anonymous> (/Users/bruce.liu/Desktop/ai-search/server/index.ts:58:12)"
  let frameOfInterest = frames[frameIndex]!;

  // "at Server.<anonymous> /Users/bruce.liu/Desktop/ai-search/server/index.ts:58:12"
  frameOfInterest = frameOfInterest.replace(/[()]/g, ""); // remove "(" and ")"

  // "/Users/bruce.liu/Desktop/ai-search/server/index.ts:58:12"
  frameOfInterest = frameOfInterest.split(" ").at(-1)!;

  return frameOfInterest;
}

bruce-c-liu avatar Sep 24 '24 21:09 bruce-c-liu