UPDATE: You’ll want to check out the updated post with new code, tests, and compatibility.
Chances are that if you’ve done any significant Javascript work, you’ve run into a situation where part of the debugging process could be much improved if you just had the function call stack.
I’m going to give you some ways of doing this with and without the popular Firebugextension and have some examples of their uses.
Sometimes s**t only happens in other browsers. Here’s how to create/log your own stack trace. Put this code in an accessible place in your Javascript file(s) and call theprintStackTrace() function inside any function.
function printStackTrace() { var callstack = []; var isCallstackPopulated = false; try { i.dont.exist+=0; //doesn't exist- that's the point } catch(e) { if (e.stack) { //Firefox var lines = e.stack.split('\n'); for (var i=0, len=lines.length; i<len; i++) { if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) { callstack.push(lines[i]); } } //Remove call to printStackTrace() callstack.shift(); isCallstackPopulated = true; } else if (window.opera && e.message) { //Opera var lines = e.message.split('\n'); for (var i=0, len=lines.length; i<len; i++) { if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) { var entry = lines[i]; //Append next line also since it has the file info if (lines[i+1]) { entry += " at " + lines[i+1]; i++; } callstack.push(entry); } } //Remove call to printStackTrace() callstack.shift(); isCallstackPopulated = true; } } if (!isCallstackPopulated) { //IE and Safari var currentFunction = arguments.callee.caller; while (currentFunction) { var fn = currentFunction.toString(); var fname = fn.substring(fn.indexOf("function") + 8, fn.indexOf('')) || 'anonymous'; callstack.push(fname); currentFunction = currentFunction.caller; } } output(callstack); } function output(arr) { //Optput however you want alert(arr.join('\n\n')); }
UPDATE: A few others have taken and upgraded the script with a bunch of new features. His changes and mine are now on GitHub. Contribute!
It’s ugly, but this works for the latest versions of IE, Firefox, Opera, and Safari. Firefox and Opera give you file names and line numbers when they can, but I couldn’t find a mechanism to get the same from IE and Opera. Hopefully the inline comments describe enough of what is going on. If not, ask :).
Give it a shot by clicking here. It will run the snippet below.
function foo() { var blah; bar("blah"); } function bar(blah) { var stuff; thing(); } function thing() { if (true) { //your error condition here printStackTrace(); } } foo();
You can easily get a stack trace at any time by calling console.trace()
in your Javascript or in the Firebug console.
ot only will it tell you which functions are on the stack, but it will include the value of each argument that was passed to each function.
This is obviously the best way to go if you are using Firefox.
Furthermore, these tools allow you to dig deeper. Of course, we can’t count on them for ALL situations.
I hope you find this useful. If you have any suggestions/improvements I’d like to hear them! Also all kidding aside, I worked pretty hard on this function, so I’d really appreciate if you’d help me share this with more people. Thanks!