A Survey of Data Display in JavaScript Debuggers

History

2009-07-02 - Patrick Mueller - initial write-up

Introduction

I thought it would be interesting to compare the methods used to display data in JavaScript debuggers. I surveyed:

Firebug 1.4.0b4 on FireFox 3.5

Web Inspector in WebKit nightly r45193

Dragonfly in Opera 10.00.6477

I suppose I should test Internet Explorer as well, but I don't think I have the requisite tooling installed to use the debugger (if someone wants to contact me offline about how to set up IE for debugging without having a for-pay version of Visual Studio installed, please do).

I also included Eclipse's Java debugger in the survey.

For the test, I constructed an HTML file with some JavaScript code that created a set of data, and then compared how this data was displayed in the various debuggers.

The Data

The data used in the tests was constructed as local variables within a function which was programmatically invoked. Note, this paper includes a link (below) to run the test.

First a set of basic objects is created:

var anInteger = 42; var aFloat = 6.66; var aBoolean = true; var aString = "Lorem ipsum dolor sit amet,..."; // 180 chars total var aNull = null; var anUndefined = undefined; var aNaN = 1/undefined; var anObject = {x: 5, y: 25}; var aPrintableObject = {x: 5, y: 25}; var aMap = {}; var anArray = []; var anArguments = arguments; var anElement = document.getElementById("body_title")

Then, the aMap object has a number of properties added; a property with the name of each of the variables above is added, with the value being the variable's value. Then, the anArray object has a number of elements added; each of the variable's value above is added to the list. The aPrintableObject object is augmented with a toString() method which displays the values of it's properties.

For Java, a method similar to this function is created as a static main for a class.

Note that initial attempts at creating recursive versions of anArray and aMap by adding those objects to themselves resulted in "odd behavior" in some browsers and even the Eclipse debugger. This should be further investigated, but for the purposes of this exercise, the immediately recursive structures were not used.

To run the test yourself, bring up the JavaScript debugger for your browser, and then click here. Because there is a debugger statement in the run() function which is invoked, you typically won't need to set a breakpoint to get to the point where all the variables are set, however, you will likely need to display and/or enable the debugger before traversing the link.

JavaScript source: test.js

Java source: Test.java

Initial unexpanded variable list

This is the list of variables that the debugger initially displays when it hits the breakpoint.

Notes:

Firebug's list is unusually larger than the others, looks like it could set the line height a bit smaller.

This beta release of Firebug is currently printing the object representation as undefined . In previous releases, instead of seeing undefined , you'd see the result of the object's toString() method, or the name of the object's constructor. Presumably this is a bug in the beta release which will get fixed eventually.

In addition to the toString() representation, or class name, Firebug also displays additional information beside a variable. For instance, the this variable shows the base name of the url the window is diplaying. For the aMap variable, it shows some of they key/value pairs in the map.

Although it's not shown here, because it's not the default behavior, Eclipse can be configured to show the toString() representation of a value instead of the class name and (useless) id value.

All of the debuggers use trees to display nested structures, using "disclosure triangle" or "squared plus" glyphs. Firebug and Eclipse additionally separate the variables and values, keeping the values left aligned to themselves. We'll see this causes problems later when the nested structures expand and the values need to be shifted to the right.

Dragonfly's "squared plus" glyphs for nested structures align with non-nested property names. Messy.

Firebug and Dragonfly make use of color and font for different values. Firebug also displays some special values in a "reverse video" style - null and undefined , but not NaN .

Dragonfly makes no attempt at displaying at least the class name for an object, unlike the other debuggers, it just always displays "object".

Web Inspector and Eclipse only display a small amount of the string. Dragonfly displays a bit more, but it spills into a second line, messily. Firebug displays the entire line. Wonder how long of a string they'll display?

Firebug shows the anArguments variable as an array, but no structure, and Web Inspector and Dragonfly show it only as an object. Having both would be nice, in terms of being able to view it as an array, but also see the properties if expanded.

Though it's not displayed, expanding the aMap variable results in a sublist for each of the debuggers which is similar to this list itself. For Eclipse, well, let's not go there.

Firebug

Web Inspector

Dragonfly

Eclipse

aPrintableObject expanded

In this set of images, we see the aPrintableObject expanded.

Firebug does not display the toString() method, Web Inspector only shows the first line of the function (pretty useless), and Dragonfly shows it as an object.

Worth nothing again that Firebug would typically display the result of the toString invocation beside the aPrintableObject variable, but doesn't for this beta release, incorrectly showing undefined instead.

We show the additional area below the variable list for Eclipse in this image. In this case, we see the toString() representation. And again, Eclipse can be configured to show this in the variable display, but it's not the default.

Firebug

Web Inspector

Dragonfly

Eclipse

anArray expanded

In this set of images, we see the anArray variable expanded. No big surprises based on anything we've so far. Except that Web Inspector appears to be sorting the key names alphabetically, which is confusing.

Firebug

Web Inspector

Dragonfly

Eclipse

anElement expanded

The main point in showing this set of images is to demonstrate how generally useless it is. Rather than display a large number of nested value whose values, it might be nice to optionally filter this list somehow.

The Firebug display has grown significantly wider, presumably to accommodate longer property names after expansion. This is not a good thing.

Firebug

Web Inspector

Dragonfly

Eclipse

REPL

Each of the JavaScript debuggers supports a REPL in some form. For this set of images, I sequentially evaluated the variable names aMap , anArray , and anElement .

The results are pretty much what we would expect given what we've seen so far, with some surprises.

For Firebug and Web Inspector, when anElement is evaluated by itself, it renders an HTML source rendition of the element. For Web Inspector, the HTML source rendition is also displayed for the element within the anArray variable.

Web Inspector also provides disclosure triangles for nested objects within the console display. The second Web Inspector image shows the result of clicking on a disclosure triangle; the results are displayed inline within the console. Nifty!

Firebug

Web Inspector

Web Inspector with expanded Object

Dragonfly

Summary / Thoughts

As noted, Firebug has a bug or two to work out, but is considered the gold standard of JavaScript debuggers. Primarily because it's the only debugger that developers even realize exist today. But it also currently wins on features alone, including:

displaying toString() representations where appropriate

representations where appropriate use of color to distinguish data types

Dragonfly is the newest of the debuggers, and has some room for growth. Once some of the styling issues are resolved, it really just needs to add toString() representations where appropriate.

Web Inspector could make use of styling data types ala Firebug and Dragonfly, adding toString() representations where appropriate, and it will then be pretty much up-to-snuff.

General issues concerning all the debuggers is dealing with objects which you'd like to see different representations. Web Inspector and Firebug both display nice renderings of HTML elements, but only in the console. And frankly, this is too browser specific. Need to think wider, as more folks start to look at using JavaScript on the server. How can we accommodate application- or user- specific renderings for objects to make debugging that much nicer of an environment.

One feature I didn't show was Eclipse's Detail Formatters. A Detail Formatter provides a runtime override of the toString() method for a particular class. These are stored persistently in your workspace, so you don't need to edit them every time.

This feature is nice, as it allows you to extend runtime behavior just while debugging - no code was harmed or edited while debugging. Such a feature would be nice to provide for JavaScript as well.