In versions of Firefox prior to Firefox 3, all JavaScript exceptions were always logged into the Error Console if they remained unhandled at the time execution returned back into C++ code. As a result, if, for example, C++ code called a JavaScript component, which threw an exception, that exception would be logged to the console before control was returned to the C++ caller.

This had the unintended consequence of logging "expected" errors at length into the console. JavaScript code is sometimes designed to throw exceptions to report a result condition back to the C++ caller. These might be perfectly normal circumstances, but the exceptions were dutifully logged nonetheless.

Exception reporting in Firefox 3

Firefox 3 improves reporting of unhandled exceptions by establishing a set of rules that determines whether or not an exception is worth reporting:

  1. Any methods on interfaces annotated with the [function] attribute in IDL (see, for example, nsIDomEventListener) that throw exceptions always report those exceptions into the Error Console.
  2. Any exceptions that are generated by XPConnect -- that is, those exceptions whose result codes are defined in nsIXPConnect.idl -- are always logged into the Error Console.
  3. The NS_NOINTERFACE error is never reported when returned by a JavaScript object's QueryInterface() method on the nsISupports interface.
  4. The NS_NOINTERFACE error is never reported when returned by a JavaScript object's GetInterface() method on the nsIInterfaceRequestor interface.
  5. All other errors are reported when the last JavaScript frame on the stack returns to a C++ caller without handling the exception.

That last point deserves clarification. Consider this call chain:

Image:Exception-logging.png

Here we see C++ code calling JavaScript, which calls back into C++, which then calls back into JavaScript.

If the JavaScript in frame 4 throws an exception, the exception is returned as an error code to the C++ in frame 3. No exception will be logged to the Error Console in this case. That C++ may handle the error, generate a different error, or simply pass it straight back to the JS in frame 2. If the JavaScript in frame 2 either receives an exception from frame 3 or generates its own exception, and that exception remains unandled, then the exception will always be logged to the Error Console before control returns to the C++ in frame 1.

In other words, all unhandled JavaScript exceptions (except those in rules 3 and 4 above) will be logged before control returns to the outermost C++ caller.

Forcing logging of exceptions in inner JS frames

Sometimes you might actually want to see all exceptions from inner JavaScript frames logged (in the call chain above that would be when an exception is unhandled in frame 4). Note that the following will have no effect on the NS_NOINTERFACE exceptions outlined in rules 3 and 4 above - those exceptions will not be reported in any case.

There are two ways you can accomplish this.

First, you can set the boolean preference dom.report_all_js_exceptions. If this preference is true, all exceptions from inner frames will be logged.

Alternatively, you can set the environment variable MOZ_REPORT_ALL_JS_EXCEPTIONS. It doesn't matter what value you set this to (it can even be 0). If the variable exists, all exceptions from inner frames will be reported.

See also