An In-depth Look At The Future of Javascript Debugging With Firebug
What if you could say goodbye to alert and not-so-useful logger scripts and have a real debugging API to debug Javascript. While it hasn’t made it to the public yet, the next version of Joe Hewitt’s Firebug will finally give us an easy to use, full-featured debugging environment for Javascript. Fortunately, I’ve had the pleasure of being able to test the new version of Firebug and this post will outline some of what you can expect.
Before Joe’s efforts, we’ve used alert, and we’ve even tried to use the cool-but-cumbersome Venkman. This is a painful process to say the least. It shouldn’t be, and in the future it won’t be–Atleast while using Firefox. Hopefully Joe won’t mind if I elaborate a bit on what you’ll soon be able to do with the new Firebug.
Logging to the console
Have you ever written anything like this?
alert('width: ' + width + ' height: ' + height);
Thats a mess just to annoy you with a dialog box that shows width and height variables that are labeled; Concating strings together is messy, luckily Joe thinks this isn’t ideal as well. We can do the same thing using Firebugs console object.
console.log('width: %d height: %d', width, height);
Firebug uses printf-like formatting. I’m not exactly sure the language it’s based on so I linked to the Php manual because it has good examples.
The code above would output something like the image below in your console thats hidden snugly away at the bottom of your browser:

You’ll notice that our numbers print out in red signifying they are digits. We could’ve used %s and they would’ve been black. The log function is pretty robust and can be used in a number of ways. You don’t have to use formatted strings. Here are a few examples:
Printing Arrays
var myArray = ['item1', 'item2', 'item3'];
console.log(myArray);

Multiple Strings
var foo = 'This is foo';
console.log('This is 100% not formatted', foo);
Html Elements
console.log($('mycanvas'));

Info, Warnings, and Errors
Firebug also has different logging levels:
console.debug('I am debug');
console.info('I am info');
console.warn('I am a warning');
console.error('I am an error');

Scoped Timers
Trying to speed up your code? How fast does it take to execute line 10-20? These questions can be answered using the time and timeEnd methods.
importImages: function() {
console.time('Loading Images');
this.options.images.collect(function(image) {
var img = new Image();
img.src = this.options.filePath + image;
console.time('event binding');
Event.observe(img, 'load', this.onImageLoaded.bind(this, img));
console.timeEnd('event binding');
return img;
}.bind(this));
console.timeEnd('Loading Images');
},
This will print out the time in milliseconds it took to execute the code between time and timeEnd. Unfortunately it doesn’t print out the name of the scope, so if you have more than a few of these in your files, you’ll need to click on the blue links to the right in order to view the code and see which number comes from which timer. Update: Joe reports this has been fixed

Tracing Execution
What was called and where was it called from? Tracing gives us the ability to get this type of information. If you wanted to trace the flow of execution for a method you can use the trace method.
importImages: function() {
this.options.images.collect(function(image) {
var img = new Image();
img.src = this.options.filePath + image;
Event.observe(img, 'load', this.onImageLoaded.bind(this, img));
return img;
}.bind(this));
console.trace();
},
The image below shows us a complete trace of files and line numbers where we can trace this method all the way back to where the object was initialized in our html file.

Breakpoints
If your not familiar with breakpoint-style debugging, it’s extremely powerful. Imagine if your Javascript code was your favorite tune. Anytime during that tune, you could pause it on a certain area and find out what lyrics were being sung, what note was being played and at what pitch. You could essentially find out all you need to know about that particular part of the song and move on to other parts of it and do the same thing. Maybe not the best comparison, but it’s the best I have at the moment. ;-)
So essentially we can freeze the state of our scripts and inspect variables and objects that are in play at the moment. I’ve rambled enough, lets look at a couple examples.
The debugger keyword
var CoverFlow = Class.create();
CoverFlow.prototype = {
initialize: function(canvas, options) {
this.canvas = $(canvas);
this.context = this.canvas.getContext('2d');
this.currentX = 10;
this.options = Object.extend({
filePath: 'images/',
images: ['as-i-lay-dying.png', '36crazyfists.png', 'in-flames.png']
}, options || {});
this.importImages();
},
importImages: function() {
this.options.images.collect(function(image) {
var img = new Image();
debugger;
img.src = this.options.filePath + image;
Event.observe(img, 'load', this.onImageLoaded.bind(this, img));
return img;
}.bind(this));
},
onImageLoaded: function(img, event) {
var width = '10px';
var height = '20px';
this.context.drawImage(img, this.currentX, 10);
this.currentX += img.width + 10;
}
}
The above Prototype class is the entirety of the code we’ve been working with. All it really does is load up some album art and spit it out to a canvas element. The script itself really isn’t all that useful, but it’s more than enough to allow us to explore breakpoints.
Take special note of the debugger keyword in the importImages method. This will tell Firebug it should pause my script here and tell me a little bit about it. So now to refresh the page and see what happens.
Firebug encounters the debug keyword and instantly pops up the debug console, highlights the line in which the breakpoint was encountered, shows me the call stack, gives me an overview of local variables and my object, and finally pauses my script (in no particular order).
I can now get all kinds of information about my object (this) and inspect the img element that has been created and also see the local image variable thats available inside the loop.
As you can see from the image above, I can even go deeper into inspecting objects. If I were to expand the img object, we would see that the src attribute hasn’t been set yet. Also, we can use the Firebug command line to inspect the variables and objects in context now. If you look at the inspection pallet, you can see the local variable image is set to the string ”as-i-lay-dying.png”. Lets hope over to the command line (in the console tab) now and witness some awesomeness:
![]()
So we’ve frozen our script at a certain point and we can inspect to our hearts content. To continue the script execution until the next breakpoint press the play button in the debug console. If there isn’t another debugger statement in your code, your script should finish fully loading, otherwise it will pause again.
Stepping Over
Remember our img element from earlier whose src attribute has yet to be set. If you look at the next line of code in our class, you can see this is where it gets set. We don’t want to have to unpause our script and move the debugger statement lower, fortunately we don’t have too.
Stepping over allows us to single step into the next line of the current function. So if we wanted to keep moving along until our image’s src attribute was set, we’d press the ”Step Over” button a couple times until it has passed the line responsible for setting this.
When we go back to our console to inspect the image, here is what we get:
>>> img
<img src="images/as-i-lay-dying.png">
>>> img.src
"file:///Users/Caged/Sites/prototype/images/as-i-lay-dying.png"
Stepping Through
To single step into entering a function, we use the ”Step Into” button. So if we keep pressing this, you’ll see the script enter into the bind method of the Function object in Prototype, then from there it goes into the $A or Array.from method, so on, and so on.
Stepping Out
Stepping out allows our script to continue executing until our current function returns or another debugger statement is encountered.
The Bad News
I have nothing but good things to say about Firebug. It’s truly a blessing for Javascript developers, especially with the increase in the number of developers getting involved with Javascript. With that said, there are some negative side effects of Firebug that doesn’t really have much to do with Firebug itself.
Safari will crash
You may or may not know, but Safari also has a console.log command. It works pretty well until it encounters a printf style string. It will simply lock up and crash.
Not A Standard
I really wouldn’t care much about this point if it didn’t cause problems in other browsers.
Because the console object isn’t available to all browsers, anytime it or the debugger statement is used, it will result in a syntax error or something similar in anything but Firefox (excluding console.log in Safari).
This makes browser switching harder. It’s not a quick jump between Firefox and Safari to see if your script works in both browsers. You need to comment the Firebug specific keywords in order to view your script in another browser.
You could potentially create a wrapper around the console object to provide a fail-safe for other browsers.
Bittersweet
It would be great if we had a Firebug for all browsers. Unfortunately I don’t see this happening anytime soon. I found a post last week (which I can no longer find) of someone who was doing something like this for Safari, but I think it has since been abandoned.
Summing Up
There is much more to come in Firebug than what I’ve covered here. If you want to keep your eyes pealed for the new release along with some useful tips on Firebug, check out Joe’s blog.
Also, the mozilla site has a better explination of the step over, step into, step out stuff that you might be interested in.
Until next time…
Sorry, comments are closed for this article.




Discussion
The debugger keyword works in IE6 if I’m not mistaken. I’ve used it in conjunction with the reasonably useful Microsoft Script Editor (included with Office).
This will be a huge benefit for those who have to write a lot of custom Javascript code.
My favorite thing about Firebug 0.4 is pretty simple: the console now executes the statements you type in the context of the window. This means I can use it as a pure JavaScript shell (and finally retire Jesse’s venerable bookmarklet).
I think an interactive console right in the browser will be an excellent tool for JavaScript tutorials, since it means that readers will be able to follow along. (I’ve used the “follow along in your browser” technique in one article already.)
Thanks for the summary! As someone who has historically written quite a lot of “alert” statements to debug JavaScript, the advent of tools like these are a welcome change. This is definately something I’m going to play around with!
I have been waiting for such a tool for nearly 5 years now.
No doubt Firebug is going to be very very useful to all those who write lot of custom javascript code like me.
Eagerly waiting for the release of the next version of firebug
Wow! Thanks so much for posting this. I’ve been using Firebug, myself (actually, it has become essential). But I haven’t had the time to investigate its full capabilities. I really didn’t know it could do all of this.
You made my day!
Curt, those features are in Firebug 0.4 which is not available to public.
Justin, this Safari issue is pretty daunting – enough for me not to use the feature at all (no, I’m not going to comment debugging out for production). Is there any chance of Firebug API being changed?
Larry, I believe your right about IE and the debugger keyword.
Andrew: Nice technique on the article. It’s great to be able to engage people in an exercise.
MisLav: I think there is little chance in the firebug API being changed. If all your wanting to do is prevent Safari from crashing, just overwrite console.log for it. It’d be pretty easy to mimic simple printf syntax for Safari and then call the normal console.log with a preformatted string.
Justin, I think I’m finally going to give in to the JavaScript debugging crowd and review this post as a solid reference to using a “real” tool to debug my JavaScript. Although I haven’t had a real reason to dig too deep into finding a JavaScript debugger, I think the more complicated my applications get, the more I wish I had a good one.
I’ve generally just took the approach of writing my own inline debugger and calling a custom logger function that i wrote which outputs errors onto the page and populates a ‘logger’ div element. Nothing too fancy, and seems to have got me where I am, but thanks for posting this. I’ll look into Firebug a bit more. I just hope it doesn’t turn out to be another tool that sucks up all my system resources.
Dustin, I used to do the same thing in regards to using a custom logger.
It’s hard to pass up something like Firebug though and it didn’t take long before I was singing it’s praises. There are some things that it can, and will eventually do-
you’d almost have to be a little loopy to roll your own. That, or your knocking back the Coronas when making the decision. ;)If you’re testing in more than just Firefox I’d recommend using log4javascript (http://www.timdown.co.uk/log4javascript/) for JavaScript logging. It’s based on log4j, has searchable, filterable pop-up or in-page consoles, Ajax logging, and has all the formatting of log4j’s PatternLayout. It also works in all recent, major browsers (IE 5+, Mozilla, Safari 1.2+, Opera 7.5+). I’ve found it extremely useful for cross-browser JavaScript debugging.
I just found that on Digg.com. It includes a very good JS-debugger that doesn’t need additional scripting. Additionaly you can type something in to the console and evaluate it whille running. It looks to me like Xcode.
0.4 version is fantastic. So long, Venkman. Not only that, but it’s got so many intuitive features that it is now my most indispensable FF plugin… I’m doing a bunch of async calls that come back and can ping-pong events – this is invaluable.
re: using a debugger. I don’t tend to crack one open myself often, but NOW, even catching errors which are automatically thrown to the debugger is fantastic. traps state. wow.
After modifying a js script, don’t you need to clear your firefox cache for it to reload the script?
Liu: a simple refresh on the same page will make Firefox check the scripts (among other things) using HTTP conditional requests for changes and download if necessary. You can always force downloading everything on the page by hitting CTRL+F5 (override cache). This should work locally, too. Always clearing the whole cache is cumbersome and it clears cached data from other pages, too; you should avoid it.
Great article … I’ve been back a few times for reference. Just wondering if you know of any way to open/close the Firebug console window using the keyboard?
Aaron: F12 on your keyboard will toggle Firebug open or closed.
This extension is so cool, and indespensible. Combine it with the Web Developer’s Toolbar and you have an awsome development enviornment. Especially when you combine WDT’s Edit CSS with Firebug’s Inspector, which also alows you to edit your id and class names.
Just a pity something similar isn’t
I’ve written a little wrapper around this object that simply converts the console.log() method into an alert() in other non Firebug enabled browsers. It’s simple and can easily be added to:
dbug = { firebug: false, log: function(msg) { alert("debug: " + msg); } } if (typeof console != "undefined") { // safari, firebug if (typeof console.debug != "undefined") { // firebug dbug.log = console.debug; dbug.firebug = true; } }I should add that instead of calling console.log, you’d call dbug.log(), which works in all browsers that I’ve tried it in so far.
I put this at the top of my javascript to deal with IE not having a “console.” I don’t know if this would work for safari.
“noop()” is a mochikit function meaning “function() {}” but apperently IE can leak on that particular phrase so we use “noop” instead.
Finally, I really only use console.log and console.error, so you might need to add the others:
var console; if (console == undefined) console = new function() { this.error = function(src) { alert("Error ---\n\n" + src); }; this.log = noop(); }g8 article and also if firebug support for all browser then really nice, though for a workaround we can keep console and debugger objects in mozilla firefox specific code.
good article
BTW, I noticed and error here: urchinTracker is not defined (line 11)
gr8 article. Here is a firebug tutorial screencast that is good as well.
http://www.digitalmediaminute.com/screencast/firebug-js/