Revisiting uncaught asynchronous errors in the Mozilla Platform
May 30, 2014 § Leave a comment
Consider the following feature and its xpcshell test:
// In a module Foo function doSomething() { // ... OS.File.writeAtomic("/an invalid path", "foo"); // ... } // In the corresponding unit test add_task(function*() { // ... Foo.doSomething(); // ... });
Function doSomething
is obviously wrong, as it performs a write operation that cannot succeed. Until we started our work on uncaught asynchronous errors, the test passed without any warning. A few months ago, we managed to rework Promise to ensure that the test at least produced a warning. Now, this test will actually fail with the following message:
A promise chain failed to handle a rejection – Error during operation ‘write’ at …
This is particularly useful for tracking subsystems that completely forget to handle errors or tasks that forget to call yield
.
Who is affected?
This change does not affect the runtime behavior of application, only test suites.
- xpcshell: landed as part of bug 976205;
- mochitest / devtools tests: waiting for all existing offending tests to be fixed, code is ready as part of bug 1016387;
- add-on sdk: no started, bug 998277.
This change only affects the use of Promise.jsm. Support for DOM Promise is in bug 989960.
Details
We obtain a rejected Promise by:
- throwing from inside a Task; or
- throwing from a Promise handler; or
- calling
Promise.reject
.
A rejection can be handled by any client of the rejected promise by registering a rejection handler. To complicate things, the rejection handler can be registered either before the rejection or after it.
In this series of patches, we cause a test failure if we end up with a Promise that is rejected and has no rejection handler either:
- immediately after the Promise is garbage-collected;
- at the end of the
add_task
during which the rejection took place; - at the end of the entire xpcshell test;
(whichever comes first).
Opting out
There are extremely few tests that should need to raise asynchronous errors and not catch them. So far, we have needed this two tests: one that tests the asynchronous error mechanism itself and another one that willingly crashes subprocesses to ensure that Firefox remains stable.
You should not need to opt out of this mechanism. However, if you absolutely need to, we have a mechanism for opting out. For more details, see object Promise.Debugging
in Promise.jsm.
Any question?
Feel free to contact either me or Paolo Amadini.
Leave a Reply