mozilla

Revision 169502 of Exception logging in JavaScript

  • Revision slug: Exception_logging_in_JavaScript
  • Revision title: Exception logging in JavaScript
  • Revision id: 169502
  • Created:
  • Creator: Bent
  • Is current revision? No
  • Comment

Revision Content

{{template.Fx_minversion_header(3)}}

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 {{mediawiki.external('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 all exceptions to be logged

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).

There are two ways you can accomplish this.

First, you can set the environment variable <tt>MOZ_REPORT_ALL_JS_EXCEPTIONS</tt>. 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.

Alternately, you can set the boolean preference <tt>dom.report_all_js_exceptions</tt>. If this preference is true, all exceptions from inner frames will be logged.

See also

Revision Source

<p>{{template.Fx_minversion_header(3)}}
</p><p>In versions of Firefox prior to Firefox 3, all JavaScript exceptions were always logged into the <a href="en/Error_Console">Error Console</a> 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.
</p><p>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.
</p>
<h3 name="Exception_reporting_in_Firefox_3">Exception reporting in Firefox 3</h3>
<p>Firefox 3 improves reporting of unhandled exceptions by establishing a set of rules that determines whether or not an exception is worth reporting:
</p>
<ol><li> Any methods on interfaces annotated with the <code>{{mediawiki.external('function')}}</code> attribute in IDL (see, for example, <code><a class="external" href="http://mxr.mozilla.org/seamonkey/source/dom/public/idl/events/nsIDOMEventListener.idl">nsIDomEventListener</a></code>) that throw exceptions always report those exceptions into the Error Console.
</li><li> Any exceptions that are generated by <a href="en/XPConnect">XPConnect</a> -- that is, those exceptions whose result codes are defined in <a class="external" href="http://mxr.mozilla.org/seamonkey/source/js/src/xpconnect/idl/nsIXPConnect.idl">nsIXPConnect.idl</a> -- are always logged into the Error Console.
</li><li> The <code>NS_NOINTERFACE</code> error is never reported when returned by a JavaScript object's <code>QueryInterface()</code> method on the <code>nsISupports</code> interface.
</li><li> The <code>NS_NOINTERFACE</code> error is never reported when returned by a JavaScript object's <code>GetInterface()</code> method on the <code>nsIInterfaceRequestor</code> interface.
</li><li> All other errors are reported when the last JavaScript frame on the stack returns to a C++ caller without handling the exception.
</li></ol>
<p>That last point deserves clarification.  Consider this call chain:
</p><p><img alt="Image:Exception-logging.png" src="File:en/Media_Gallery/Exception-logging.png">
</p><p>Here we see C++ code calling JavaScript, which calls back into C++, which then calls back into JavaScript.
</p><p>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 <a href="en/Error_Console">Error Console</a> 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 <a href="en/Error_Console">Error Console</a> before control returns to the C++ in frame 1.
</p><p>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.
</p>
<h3 name="Forcing_all_exceptions_to_be_logged">Forcing all exceptions to be logged</h3>
<p>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). 
</p><p>There are two ways you can accomplish this.
</p><p>First, you can set the environment variable <tt>MOZ_REPORT_ALL_JS_EXCEPTIONS</tt>.  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.
</p><p>Alternately, you can set the boolean preference <tt>dom.report_all_js_exceptions</tt>.  If this preference is <code>true</code>, all exceptions from inner frames will be logged.
</p>
<h3 name="See_also">See also</h3>
<ul><li> <a href="en/Error_Console">Error Console</a>
</li><li> {{template.Bug(415498)}}
</li></ul>
Revert to this revision