`
netcome
  • 浏览: 466563 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

A Javascript stacktrace in any browser

阅读更多

 

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.

Without Firebug and friends? Using IE?

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 += &quot; at &quot; + 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(&quot;function&quot;) + 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 :).

Try it out

Give it a shot by clicking here. It will run the snippet below.

function foo() {
    var blah;
    bar(&quot;blah&quot;);
}
 
function bar(blah) {
    var stuff;
    thing();
}
 
function thing() {
    if (true) { //your error condition here
        printStackTrace();
    }
}
 
foo();
 

Obvious easy way: Firebug (and Drosera and Dragonfly)

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.

Conclusion

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!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics