Wednesday, July 31, 2013

Off Topic: Supporting Javascript you didn't write

Hi everyone,

Today's topic doesn't deal with .NET / CLR topics at all. This blog tends to focus on that. But since most .NET developers I know tend to use JS/HTML/CSS with .NET (or ASP.NET), this post should be somewhat beneficial to the "usual" reader of this blog.

I am a support engineer. That means I often get asked to fix code I didn't write. If it's .NET code, I usually turn to debugger breakpoints and/or tracepoints (good info about those here if you are not familiar) or occasionally use a .NET profiler. The first goal behind these tools is often to answer the question "where am I in the code base?" By knowing what code at the function or line level is involved, you can narrow down what things might be broken as you troubleshoot.

And honestly, that is the name of the game with all debugging / troubleshooting, regardless of language or environment. We have a product with a fairly large javascript code base that is difficult for me to keep up with, because I only find myself troubleshooting problems related to it once every 3-6 months. As a result, I often have a large "learning curve" at the beginning of my support issue, as I find out what has changed and what has stayed the same in the code base. Tools like Firebug for Firefox or Chrome's JS debugger are certainly helpful, but sometimes it takes a lot of effort just to figure out what parts of the code base are involved when you click a button, or go to page xyz. You can always view the HTML and see what JS is running, but if the product is designed with a lot of architectural "fluff", you have a hard time deciphering what exactly is going to happen when you click the button. As an example, maybe the button runs a JS function named processAction() that takes a GUID: processCommand('12345-123-123-1234...');

Well that's just not helpful. :) How do I know what that GUID is related to? In our product, it changes every time you hit the page! Ugh.

Enter, JSCoverage. I recently found a great Chrome plugin that can be used to identify functions (or even lines of code) that execute whenever you navigate somehow in your product. This manual page gives you a rundown of how it works. It essentially boils down to these high level steps:

1) Instrument one or more .js source files. These are output in a folder of your choosing.
2) Make sure your output folder is hosted by a web server (such as IIS, aka mapped to a virtual directory, or in a subdir of a virtual directcory).
3) Navigate to the generated jscoverage.html file.
4) Use the Browser tab to launch your app in a separate window or tab.
5) The jscoverage.html tab lets you view live information about coverage as you perform actions in the app launched in step 4.

The architecture is fairly simple. There is a global object named _$jscoverage that contains counters for various JS source code files and different blocks within those files.

_$jscoverage['my-source-file.js'][123]

All of the counters start at 0 and go up from there. The great thing about this architecture is that you can exploit it in a way that the original author may or may not have intended! The _$jscoverage object is only initialized once. Subsequent loads of the page or JS actions/functions that execute just accumulate more hit counts on the counters. They don't clear out. QA people who are interested in *total* code coverage probably like this, but a support developer may be more interested in precise coverage of one or two behaviors instead of all behaviors performed in the web browsing session. So, we can use Chrome's Console to execute some ad-hoc javascript that clears the counters, like so:

for(var propName in _$jscoverage['my-source-file.js']) {
_$jscoverage['my-source-file.js'][propName] = 0;
}

Using this technique, we can clear the counters immediately prior to performing our action of interest. Then, once the action completes, switch back to the jscoverage pane to view coverage data for just that action. You may need to navigate off and back onto the Summary tab to see the results update.

For me, this technique greatly simplifies the support process. Now after reproducing my issue, I know that the problem lies within 10 functions instead of 1000 potential functions! That's a money maker, folks. Now, I know where to place breakpoints via Chrome's JS debugger to get the most mileage out of my support discovery process! Some days I just love my job. :)

Many thanks to the developers of JSCoverage.

Thursday, July 18, 2013

System.Xml ImportNode and the .NET Heap(s)

If you work with XML in .NET a lot, you have probably bumped into a scenario a few times in your career where you need to move or copy some XML fragment out of one document and into another. The typical coding sequence for that might look something like this:

XmlDocument source = new XmlDocument();
source.LoadXml("");

XmlDocument dest = new XmlDocument();
dest.LoadXml("");

//move from source to dest
XmlNode n = source.SelectSingleNode("/source/myxml");
XmlNode nImported = dest.ImportNode(n, true);
XmlNode nAppended = dest.DocumentElement.AppendChild(nImported);

I have often wondered (but, until today, been too lazy to investigate) why ImportNode() and AppendChild() return XmlNode objects, and what one is supposed to do with them? Are they the same? Clones of the same? Etc.

Well, IronPython happens to have this nice feature where it shows you the memory address of the .NET object you reference in an expression via the ipy console.

Excerpt from an IronPython Console session