Whatever evil you can think of, JavaScript stack traces are worse.
After releasing a satisfactory version of CrashKit Python we've turned our attention to AJAX web applications and collection of bug reports from client-side JavaScript code. Unfortunately, whatever solutions we could find on the Web failed to collect enough information and did not suite our requirement of being browser-independent. We really wanted identical exceptions occurring in different browsers to be displayed as a single bug, which means that the topmost line of a stack trace has to be the same.
It turns out there are 3 ways to obtain a stack trace: ex.stack (Firefox-specific), ex.message (Opera-specific) and traversing a chain of arguments.callee.caller.caller.caller. The latter one is extremely limited, and overcoming some of its quirks is both hard and browser-specific.
In Firefox and Opera, the stack trace can be obtained from an exception object. This means we have to get a hold of the exceptions somehow. There is no global event loop or any other central place where a catch-all handler can be installed, so every event handler has to be wrapped in a try-catch block. JavaScript frameworks often make it easier by introducing a common place where event handlers are bound, and in fact we have an experimental jQuery support that wraps all handlers into try-catch blocks automatically.
Other browsers have to use the arguments-based approach, which has several big problems:
1) Because the arguments pseudo-variable corresponds to the current function and is not related to an exception in any way, the catch block has no way to know the function/line the exception has actually occurred at. It can only determine the callers of the function containing the catch block itself, thus the top of the stack trace will be missing.
2) The value of caller attribute is a function, not a stack frame, so the bottom of the stack trace will be missing if some function is called recursively.
3) The only thing we get by traversing the chain of callers is function bodies (the source code). No line numbers or URLs, and function names are only available in Safari, but not in IE.
Fortunately, Safari provides a line number and a URL for the topmost stack trace entry as ex.lineNumber and ex.sourceURL. Thus we can augment the partial stack trace with a correct topmost entry, which is the most important requirement for CrashKit bug grouping to work.
Internet Explorer (6.x–8.x) has no such properties in the exception object. Luckily, Internet Explorer has window.onerror event which is fired when it's too late to collect a stack trace, but does provide a line number and a URL for the topmost stack trace entry. Thus the strategy for handling IE is to collect a partial stack trace and re-throw the exception, hoping that noone would catch it and IE will end up raising onerror, allowing us to augment the stack trace with a correct topmost entry.
We also try to guess some missing information automatically. Given a function body, we use XMLHTTPRequest to download the source code of all included scripts and search for the body textually, which gives us a URL to add to the stack trace. Given a line number within a function, we look for constructs like xxx = function or 'xxx': function to guess a “real name” of an anonymous function.
We also collect a few lines of source code around the position of exception occurrence for the upcoming source code display feature in CrashKit.
The details of the described operations are quirky too. In Opera, some line numbers are relative to the start of a SCRIPT tag, so we have to adjust for that. Automatic semicolon insertion and whitespace differences interfere with the textual function body search, so we have to turn the body into a regular expression. Inline handlers like <button onclick="somecode()"> have to be treated specially for the purposes of stack trace collection (good news is that we can always determine line numbers for such one-line functions).
Another important thing to realize when coding in JavaScript is that Everything Changes. For example, both ex.stack and (of course!) ex.message are strings parsable with a few simple regular expressions, but their (undocumented) format may easily change in the future. New browser versions may be released which support or don't support something that we expect. That's why browser detection is widely recognized as an evil practise, and CrashKit JavaScript does not do any. Instead, it tries to use Firefox- and Opera-specific approaches and falls back to walking the call chain in case of any problems, so it's pretty future-proof.
You can grab the source code on GitHub: crashkit-javascript.js + sample. It defines two reusable functions, CrashKit.report and CrashKit.computeStackTrace, both documented pretty throughly. There has not been much testing yet, so consider this to be of beta quality. The post will be updated as the code matures. (And do check out the CrashKit itself, although it is in a limited beta mode at the moment.)

