JavaScript Callstacks

September 4, 2012

Today I’m going to share a cool method for generating a JavaScript callstack from any point in your code.  JavaScript doesn’t offer this functionality, but we can tease it out pretty easily, especially in V8 (very useful for Node programmers).

The closest thing JavaScript has to a callstack is the 10-frame backtrace that comes along whenever an error is generated.  So we can use that to our advantage, by generating an error on-demand, catching the response, and examining the #stack attribute of the thrown error object:

function callstack() {
  try { capture.error } catch (e) {
    return e.stack;
  }
}

Normally we’d have to stop there, and if we wanted to access that data programatically we’d have to parse the pre-formatted String that comes back.  But with V8 we have a better option!  V8 gives us access to the method that prepares the preformatted response, so by temporarily replacing it – we can return the original data instead.  Check it out, here’s a small node.js module:

var replacementPreparer = function (error, trace) {
  return trace;
};

module.exports = function () {
  var capture;
  var oldPreparer = Error.prepareStackTrace;
  Error.prepareStackTrace = replacementPreparer;
  try { capture.error } catch (e) {
    capture = e.stack;
  }
  Error.prepareStackTrace = oldPreparer;
  return capture;
};

And the usage:

var callstack = require('./path/to/callstack/js');
for (var i = 0; i < 1000; i++) {
  callstack(); // use this anywhere in your code
}

When you call `callstack`, you’ll get back an array of CallSite objects upon which you can call methods from the V8 API to get at all the juicy details: http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi