A day in the office – useful findings on Web Development – debugging with Firebug (and a word on Google API Loader and ADF Faces RC)

This article does not present a smooth story, but the raw experience of a day on the job. Looking over the shoulders of various Web Developers I have picked some useful tips with regard to Web Development, JavaScript and web application debugging. I will share these with you in this blogpost, however it is primarily meant for my own reference. That explains the somewhat crude writing style.

Debugging with Firebug Console

Get hold of the source code of a particular JavaScript function: if you know that a function is being called somewhere in the code, but you may not know exactly where or when and using breakpoints is going to take a lot of hard work, there is a very easy way of getting an overview of the source of the function:

Click on the Firebug Console tab. In the right hand pane of the Console, type <functionname>.toString() and press the Run button. Since functions in JavaScript are objects that publish several methods, we can invoke the toString() method (function) on the function object; it will return the source in the left hand pane:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 001

 

In the code example you can see the line that says debugger;. That statement is used to programmatically define a breakpoint (alternative to locating the code in Firebug and adding a breakpoint). When the code is executed and hits that statement, the debugger will respond as if a breakpoint was added on that line of code:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 002

The statements

console.debug, console.info, console.warn and console.error

are used to write debug statements to the Firebug console with visual markings for info, warning and error. If you pass a string to the functions, this string is printed.

function preprocessName(value) {
    console.info("The value is before preprocessing "+value);
    return value;
}


function nameDerivation(value) {
  console.info("The value passed to nameDerivation "+value);
  tempvalue = value;
  tempvalue =  preprocessName(tempvalue);
  return tempvalue;
}

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 003

When you pass an object, the console will include a hyperlink to the current line of code in the object. That allows you to inspect the source of the object.

function preprocessName(value) {
    console.info(preprocessName);
    return value;
}
 

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 004

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 006

 

Use console.trace to write interactive stack trace of JavaScript execution at the point where it is called to the Firebug console – that includes the values of the arguments passed into each of the functions in the trace. You can click each function to take you to its source in the Script tab, and click each argument value to inspect it in the DOM or HTML tabs. (note: bug 796, fixed in Firebug 1.3, can be in the way).

Other Console operations include dir, assert, profile, timer, count. See http://getfirebug.com/console.html for more details, as well as http://getfirebug.com/logging.html.

Doing the Decorator Pattern on JavaScript functions – or: Replace a JavaScript function in the Firebug console

Sometimes the behavior of a JavaScript function your web application is using is not clear or perhaps not even correct. It would be convenient for analysis to know what went on in the function, or at least what went into it. However, it may be hard to find the line of code and set a breakpoint on it. And even if you could manage that, it would not enable you to easily try out an improved version of the function.

JavaScript allows us to define functions (objects) at run time. Those may override existing functions – or better put: a new function can become the target for the global reference to the original function (object). Since the orginal function is still there (just no longer referenced by the global reference) we can still access it.

That provides the pieces for dynamically replacing (wrapping, decorating) a function. Here we assume for example that function preprocessName is a function we need to know more about: what goes into it, what comes out of it and perhaps would the application function more accurately if we append the behavior of this function by only calling it conditionally or tweaking the result it returns.

With the following code snippet that we can execute in the Firebug Console, we replace the function by our own wrapper; we retain a reference to the original function so we can still call it for the wonderful functionality it provides to us:

oldFunctionpreprocessName = preprocessName;

function preprocessName(value) {

  debugger;

  console.log('Parameter value in function preprocessName = '+value);

  result = oldFunctionpreprocessName.call( this, value);

  console.log('Result after calling preprocessName : '+result);

  return result;

} 

Executing this snippet:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 007

Now we have effectively replaced the original function preprocessName.

When we change the name field in the HTML page, the onchange fires and eventually the control is passed to our wrapper function:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 008

Toggle to the Watch tab:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 009

The resulting output in the console:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 010

Note: without changing a single thing in our application, we now have more insight into what the decorated function is doing and how we may tweak that behavior.

Profiling in Firebug

When you feel that certain areas in the JavaScript in the application are not performing wonderfully well – but you cannot tell for sure – then there is a very easy way of finding out exactly where in your application’s JavaScript functions the time is spent.

Click on the Profile Tab in Firebug to start profiling. Performing the actions that trigger or run into the lousy performance. Then click the Profile Tab again to stop profiling and show the profile report. You will get something like this:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 011

 A list of the functions that have been called with the number of calls, the time spent inside the function itself and inside the functions called (higher up in the call stack) from this function. By far the top scorer (not) is the function yearValidation that showed an alert that took the user 2 seconds to react to. The most time spent on real computer work was done in nameDerivation (5 ms). Considering what it has to do , that is quite a lot of time.

Click on the hyperlink to go the function and see if we can understand why it takes up relatively much of the processing time:

A day in the office - useful findings on Web Development - debugging with Firebug (and a word on Google API Loader and ADF Faces RC) firebug 012

 

 

Google API Loader

Google API Loader: http://code.google.com/apis/ajax/documentation/ and http://googleajaxsearchapi.blogspot.com/2008/05/speed-up-access-to-your-favorite.html

 

ADF Faces RC

ADF compresses style class selectors in both the rendered HTML as well as the dynamically generated, skin based CSS stylesheets. However, when ADF Faces RC components are used as child elements for non-ADF Faces RC JSF components, the compression of the style class selector names in the CSS stylesheet gets confused and a mismatch results between the selectornames in the CSS and the generated HTML. The solutions seems to be to disable the compression altogether by setting the web.xml parameter DISABLE_CONTENT_COMPRESSION to true.

 

Resources

Firebug Tutorial

Firebug Console Commands

Simple Web Application used for this article: firebugtester

2 Comments

  1. Emiel Paasschens May 28, 2009
  2. Emiel Paasschens May 28, 2009