Previous 1 2 3 4 5 6 Next

Meta comments

Meta comments is a way for you to embed breakpoints into your code. This is handy, if you're sitting and writing the code, and think you want a break point there. Also, it just plainly gives you flexibility in how you write code. And that's a Good Thing. The three different meta comments are as follows.

They're used in this fashion:

function x() {
    ... [script code]
    //@JSD_EVAL [script code]
    ... [script code]
}

It's important to realize, that, like breakpoints, meta comments are not executed while Venkman isn't running. And unlike the debugger keyword, this is a real JavaScript comment, and no browser will choke on it.

An example

In Mozilla, move to the next file, venkman_example_9.html. It's a horribly contrived example, but it shows the three different meta comments in one small file. When you just normally execute the script, it'll simply spit out the factorial for the numbers 0 through 9. Nothing amazing.

If you examine the code, you'll see that the factorial function doesn't check for negative numbers. If fac is given a negative number, it'll give back "1", which is incorrect for negative numbers (there is no factorial number, for negative numbers.)

Load Venkman up, and view the sourcefile.

Source code
Figure 55. Source code viewing venkman_example_9.html

Before the meta comments actually do something, you need to scan them in. Go to the Loaded scripts panel, and right click on venkman_example_9.html.

Scanning for meta comments
Figure 56. Right clicking, to scan for meta comments.

You'll right away notice, that the source code view now has breakpoints set, just like you've done before.

Venkman with breakpoints set
Figure 57. Using meta comments to automatically set breakpoints in your code (click for unscaled version).

As you can see, the breakpoints are indicated in both the Loaded Scripts panel (with the red dot), and in the Breakpoints panel, and as "B"'s in the source code panel.

Indeed, what meta comments really do, is simply make Venkman create hard breakpoints for you on the line just after the meta comment (remember, that using a breakpoint causes Venkman to stop just before executing the line it's on right?) You can right click, and select the properties for any of these breakpoints. Here, in figure 58, I've selected the properties for the breakpoint on line 6.

Breakpoint property sheet
Figure 58. An automatically generated breakpoint's property sheet.

Now that you've loaded all the meta comments, try running the script (by reloading Mozilla). Basically, the whole idea is, that once the meta comments have been scanned in, i will in the 7th loop be set to a negative number (which fac won't give a correct result on). But since a meta comment has also been scanned in as an conditional breakpoint, in fac, programmed to only halt execution, if the passed number is negative, you can change facN, once fac is passed a negative number.

Venkman halted
Figure 59. Venkman has halted, because n<0 was true. Here, I've asked what n is, and I'm about to set facN to "passed number was negative!" (click for unscaled version).

As can be seen from the screenshot, I've successfully stopped the show, and am about to return a "wrong number passed" type messege. Normally, 1 would have been returned, which is the incorrect factorial for -4 (there is no factorial for -4 of course). The above, gives the following in Mozilla:

factorial 0 = 1
factorial 1 = 1
factorial 2 = 2
factorial 3 = 6
factorial 4 = 24
factorial 5 = 120
factorial 6 = 720
factorial -4 = passed number was negative!
factorial 8 = 40320
factorial 9 = 362880

Of course, -4 was only passed to fac, because of our breakpoint code, but it shows the idea. Further, instead of just returning a string, we could have thrown an exception, testing how our code handled that.

Pretty print

Using "Pretty Print", lets you view a function, the way JavaScript sees it. This is practical for use, when the original function doesn't even exist in your code, say it was built using eval, or similar methods (setTimeout, etc). Also, another good usage is when the source code has been made deliberately hard to read (so called "source code protection"). In Mozilla, go to the file venkman_example_10.html, which shows some example of how to use "Pretty Print".

When you first load up Venkman, the various functions will look like this:

function foo() {
    var s = "function bar1(x) {debugger;return x+1;}";
    eval(s);
    return bar1(1);
}

function bar2(n) {
    while(n) n--;
    return "blah";
}

function fac(n){if(n<=0){return 1;}else{return n*fac(n-1);}}

Note, that the first function (foo), actually contains another nested function, called bar1. This will be one example of how Pretty Print lets you view functions that aren't "there". In this simple example, bar1 is simply made from a string I entered, in an actual code example, it could be any amount of code, generated from anything you wanted.

The second example is simpler, it shows a while loop, but you'll notice I didn't enter the optional curly braces. Lastly, I've written a recursive factorial function. As you can see, it's written in a compact way, thanks to BrainJar's JavaScript Crunchinator script, which basically makes code really compact (and hard to read!).

We will use the Pretty Print function to view the bar1, bar2 and fac functions. If you want to, examine the source code in Venkman. Especially notice how the string s (from which the function bar1 will be made) contains a debugger keyword. When you're ready, reload the page, Venkman should instantly stop at the debugger keyword.

Venkman halted at 'eval'
Figure 60. Venkman has halted at a function you cannot directly see, so it might look "wrong", but there's nothing wrong here. You can use the "Pretty Print" function, to view where Venkman has really stopped (click for unscaled version).

It might look a bit funny, that Venkman has halted on the eval line (since that's not the line with the debugger keyword.) But what's really happening is, that eval has evaluated and declared the bar1 function, and then, when on line 7, bar1 is invoked, it goes back up to where the function was defined (line 6, the eval), and there, it halts for the debugger keyword. In order to see the function bar1 properly, press "Pretty Print".

bar1's source code
Figure 61. Using Pretty Print to reveal bar1's real source code, decompiled from how the JavaScript engine sees it (click for unscaled version).

You'll notice, that you can also set breakpoints in this code, and if you do so, the breakpoints will also be reflected in the "normal" sourcecode view. For now, try stepping out (using "Step out") of the function, and then set a breakpoint on line 11, and then step into the bar2 function. A new tab should popup, to display the Pretty Print version of bar2.

Also, while the debugger isn't active, you can also view the Pretty Print version of functions, merely check the button (notice the green check?), and then doubleclick the function name in the Loaded Scripts panel. Of course, when the script isn't running, Venkman can't show you Pretty Print versions of functions that doesn't exist yet (such as the eval example).

bar2's source code
Figure 62. bar2's source code, decompiled from the internal JavaScript representation.

facs's source code
Figure 63. fac's source code, decompiled from the internal JavaScript representation.

The last is especially a lot more legible then

function fac(n){if(n<=0){return 1;}else{return n*fac(n-1);}}

Using Pretty Print is a great way to view badly written code. Unfortunately it also removes comments. You can further step, set breakpoints, and anything else you could do in normal code. But when using it to peer into code written and declared inside and eval, it might be all you even have (at runtime). Also note, that the eval concept equally applies to the various setTimeouts there are in clientside JavaScript.

Excluding eval code

While this should technically have been in the basic debugging section, I feel it makes more sense to have here (or it's better understood, hopefully.) Venkman basicly allows you to skip eval code, if you do not wish to be bothered with it. In Mozilla, go to the next file, venkman_example_exclude_eval.html. You'll notice two places, where eval calls, contains the debugger keyword. So we want to skip these, this time around. Doing this is as simple as finding the file, from which you want to exclude eval code (or any of the related categories, setTimeout etc.) You merely right click on the file as in figure 64.

File submenu
Figure 64. Excluding eval type code from the debugger (click for unscaled version).

If you reload Mozilla (with Venkman running), you'll notice that Venkman doesn't come up, as it would normally have, with scripts containing the debugger keyword.

Another even more salient point, is that if you have "Pretty Print" enabled, and "Exclude eval code" from a file, you don't get the many little jumps, into the eval code (this does seem a bit buggy though. If you test it with my venkman_example_10.html file, you'll notice that bar1 does appear.)

Profiling

Profiling means measuring how fast your program runs. And Venkman's "Profile" button does just this. Traditionally, the way to measure ones script's performance, was to embed a lot of Date objects in ones code, and do some math like that.

function foo() {
    var startDate = new Date();
    var startTime = startDate.getTime();
    
    // do time consuming stuff
    
    var endDate = new Date();
    var endTime = endDate.getTime();
    
    // total script execution time (in milliseconds):
    var totalTime = endTime - startTime;
}

This is still fine for small snippets of code, or for seeing if "this works". But to profile large pieces of code, it's prohibitive.

To showcase the Profile feature, I've created a DHTML table, using my Date script. Basically, what happens is that I create a random time, and then use all the switches that my script allows, building up a table row with the output, and then building up 100 rows like this. And finally, we'll sort the table, so it goes from oldest, to newest (to JavaScript pros: the example is deliberately badly written, bear with me?). You can load the script at venkman_example_11.html (warning, might take a while to execute!)

You again start up Venkman, and you simply click the "Profile" button, so it becomes active.

Profiling activated
Figure 65. Profiling has been activated, and Venkman is keeping score of everything that's happening.

Right now, Venkman is measuring everything, that is happening. You can then go back to Mozilla, and reload the page. Once it's all done, go back to Venkman, and stop it from profiling. Then in the "File" menu, select "Save Profile Date as ...", and enter a file you wish to save it in. It's also important you enter a file type, as Venkman can save in a whole bunch of formats. HTML is the easiest accessible. You can access the profiling report I made (the bars might look a little wonky.)

Here, in the report, you can see all sorts of information about all the functions, such as how many times they were called, how long the calls lasted in average, the longest call, the shortest, total call time, and so on. Note, that if one function, say foo, calls another function bar, foo gets counted for both foo's own time, and for bar's time.

Another handy thing to know, is that you can exclude both files, and individual functions from your profile report. Simply click on the file or function you don't want included, and right click on it.

Functions options submenu
Figure 66. How to exclude a function from being profiled.

File options submenu
Figure 67. How to exclude a whole file (and the functions it contains) from being profiled.

All in all, profiling allows you to pin point where a script is experiencing bottle necks. But of course, no table of statistics will give you fast running code. You will have to know how to fix the speed problems.

Once you're done profiling, don't forget to clear the data accumulated so far. If you don't, and you forgot you already profiled data, your next measurement will include the earlier data (most likely not what you intended.)

Venkman menu
Figure 68. Clearing profiled data is important, to reset the data pool.

You can also clear the data of individual functions and files, by following the same procedure listed in the next section, but simply picking "Clear Profile Data" instead.

A last thing that's neat to know about profiling, is that once you've profiled something, like say the script given earlier and you decide, that you really didn't want everything, you can still just get the profile data for the functions and/or files you want.

Venkman file/function submenu
Figure 69. Saving profiled data for either individual functions, or for whole files (and the functions contained therein) (click for unscaled version).

The end

Phew, a long read I suspect? Well yes, judging from my server logs few people make it this far! Since you did, I'd love to hear what comments you might have, if you found any errors, or anything else, which you feel could be better.

You should, no matter how poorly my guide was written, now be able to use Venkman to find really hairy JavaScript bugs. I still often (and mainly) use alert boxes to do debugging. They are really quick, and most bugs are not that complex. But it does happen that a tricky one surfaces, or if you're dealing with very large code pieces (I thankfully don't do that often), this knowlegde should come in handy, and let you debug code like any pro out there.

Thanks

I'd like to thank a few people, first off, Robert Ginda, for answering my barrage of questions on the more obscure sides of some Venkman features, plus Doron Rosenberg for getting me listed on a ton of sites, and also to the people who wrote back with feedback, to the first revision of the walkthrough!

Previous 1 2 3 4 5 6 Next