A Javascript stacktrace in any browser

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 Firebug extension 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 the printStackTrace() function inside any function.

function printStackTrace() {
    var callstack = [];
    var isCallstackPopulated = false;
    try {
        i.dont.exist+=0; //does not 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();
            //If we can't get the function name set to "anonymous"
            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: Luke Smith has taken and upgraded the script with a bunch of new features. I encourage you to check out his code here. Thanks, Luke!

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("blah");
}

function bar(blah) {
    var stuff;
    thing();
}

function thing() {
    if (true) { //your error condition here
        printStackTrace();
    }
}

foo();

Obvious easy way: Firebug (eventually 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.

Not 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!

Get sed savvy - part 3

We will learn about the sed delete (d), read (r) and write (w) commands today to round out your sed toolbox. The major parts I am covering should help you through 99% of the cases where sed is your best option.

Soon we’ll be looking at awk and other tools to continue the quest for command-line fluency. If you haven’t already, install Cygwin and check out part 1 and part 2.

Tutorial

One of the best ways to crank out code quickly is by using templates. Using the Stream EDitor, you can streamline the use of templates.

Suppose we have a template HTML file that we want to reuse often. Maybe it looks like this:

<html>
    <head>
        <title>template.html</title>
     </head>
    <body>
        <div id="nav">Navigation here</div>
        <div id="content">
%%CONTENT%%
        </div>
    </body>
</html>

Now we want to replace "%%CONTENT%%" with the contents of an HTML Fragment file. The syntax is simple: ‘/<pattern>/r’:

sed '/^%%CONTENT%%/r fragment.htmlf' template.html

The above script will append the contents of fragment.htmlf immediately after "%%CONTENT%%". So we can use the delete command to fix that:

sed -e '/^%%CONTENT%%/r fragment.htmlf' -e '/^%%CONTENT%%/d' template.html > whole.html

This might seem slightly useless, but the power here is in the simplicity. Many times I’m generating bits of Wiki code or HTML, and this has been invaluable.

OK, now for one more command: write (w). Suppose we have a CSV file that we want to split into several files depending on the value in the last cell. We could do this with grep, or awk (coming soon), but with sed we can do it with more efficiently:

#sedscript file
/\,[0-9]+$/w numbers.csv
/\,[A-Za-z]+/w letters.csv
/\,[^A-Za-z0-9]+/w symbols.csv

sed -r -f sedscript original.csv

Now numbers.csv will contain all rows that the last cell containing numbers, and so on for letters.csv and symbols.csv. A neat application for this might be sorting your giant contacts list into different files based on some criteria. This is a simple example, but you can probably think of a more useful scenario where you’d want to filter and split a file.

Other Examples

#Print everything outside the <html> tag (check DOCTYPES)
sed '/<html>/,/<\/html>/d' myfile.html

#Convert \r\n (DOS) to UNIX \n
sed 's/$//' myfile        #Windows
sed 's/.$//' myfile       #Linux/UNIX

Conclusion

You have now learned several sed commands and patterns you can use to make editing files and some searching tasks much more efficient, and even better, scriptable so they can be automated in a process. One cool application would be to get comments from a set of files and post them to a wiki. It would sure make collaboration slick, right?

Obviously, you can bookmark this stuff but you’ll really get good at it only if you just try it out. Keep sharing your experiences and command lists, they’re great!

This month in bookmarks: July 2008

Here are some of my best Delicious bookmarks from this July. Some especially good Javascript tidbits, and you’ll also notice some shell scripting goodness. Expect see it more often. I’m not trying to pick the most popular articles here, just the ones you might have missed.

Share your best link of July in the comments!

Shell

  • Working With History in Bash [TextMate Blog] - Allan Odgaard wrote a hugely useful tutorial to help us master bash history. I found this very useful and I’m sure you will, too.
  • Job scheduling with cron and at [IBM] - Automating repetitive tasks is obviously a huge productivity booster. Here is a good intro to scheduling tasks in Linux. You’ll want to stay tuned, though, as I’ll probably give you some better examples in an upcoming post ;)
  • Top 10 Command Line Tools [Lifehacker] - Some nifty tips here, especially in the comments. Please forgive the shameless plug as I did write 2 of the 10 articles mentioned, but hey I’m frickin’ proud of it, ok?

Mozilla

Firebug Logo

  • Firebug Lite 1.2 [Get Firebug] - Firebug Lite just got a lot cooler for IE, Opera, and Safari. You can use it to inspect HTML, CSS and JavaScript, keep track of your XHRs, and of course use the console. If you haven’t been using it then give it a try until Dragonfly/Drosera/etc. are done.
  • hyperstruct [MozLab] - I’ve been considering making some Firefox extensions for some time, and this suite of tools is exactly what will help. If you need some extra debugging power in Mozilla apps, you’re just an extension away now.
  • Firefox 3 features you may not know [Mozilla Links] - 8 really interesting features baked into Firefox 3 that I had no idea about. I love these little easter egg bits.

Productivity

Web Design

Script & Style

Javascript

  • DOM DocumentFragments [John Resig] - John yet again pulls out some arcane, forgotten Javascript feature and makes it useful. DocumentFragments dramatically decrease the time required to insert many DOM nodes into a document and are supported by IE6+ which means you can use it now!
  • What’s the Fastest Way to Code a Loop in JavaScript? [Gregory Reimer's Weblog] - An incredibly thorough set of tests for coding Javascript loop iteration for performance. I definitely learned a lot from all the examples given and now know the fastest way to iterate different collections etc. in different situations.
  • JavaScript Event Delegation is Easier than You Think [SitePoint] - I find that good knowledge of event handling is unfortunately rare in the web programmer world, since it is such a useful construct to know. SitePoint does a great job of introducing event bubbling and targeting here, something that you should give a read even if you think you have it down.