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:
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:
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; }
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; }
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:
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:
Toggle to the Watch tab:
The resulting output in the console:
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 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:
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
Simple Web Application used for this article: firebugtester
Ow not to forget, the Auto Copy add-on can be found at:
http://autocopy.mozdev.org/
Nice! Especially the decoration pattern usage in Firebug, very useful!
My personal tip for FF:
Also a nice quite small FF add-on I like a lot is the Auto Copy extension.
When you select text in FF, the text is autocopied to your clipboard (so no need to press Ctrl-C).
I’ve also changed a setting, so the text is also deselected immediately.
When do you want text to be selected in a browser except for copying to clipboard?
(->for smart ones who want to print selected text, with one mouse click on the Auto Copy icon, Auto Copy toggles between disabled and enabled).
Also with the mouse middle click, you can also paste anywhere in FF. E.g. into input field or into the navigation bar or an input field (especially handy for url’s).