Bug 1362970 - Part 2 - Script-generated patch to convert .then(null, ...) to .catch(...). r=florian draft
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Fri, 16 Jun 2017 11:00:29 +0100
changeset 595534 c1e03e2ff8205675a4debb03ee41e8a857df840a
parent 595533 6435ce97453176775a6dda71710f2c47063bc286
child 595535 eb61cf8f77d22f0cf026056615a475c2e04f932a
push id64344
push userpaolo.mozmail@amadzone.org
push dateFri, 16 Jun 2017 10:19:08 +0000
reviewersflorian
bugs1362970
milestone56.0a1
Bug 1362970 - Part 2 - Script-generated patch to convert .then(null, ...) to .catch(...). r=florian MozReview-Commit-ID: 1buqgX1EP4P
addon-sdk/source/lib/sdk/addon/runner.js
addon-sdk/source/lib/sdk/l10n/loader.js
addon-sdk/source/test/addons/page-mod-debugger-post/main.js
addon-sdk/source/test/addons/page-mod-debugger-pre/main.js
addon-sdk/source/test/addons/places/lib/test-places-host.js
addon-sdk/source/test/addons/private-browsing-supported/test-selection.js
addon-sdk/source/test/addons/private-browsing-supported/test-sidebar.js
addon-sdk/source/test/addons/private-browsing-supported/test-window-tabs.js
addon-sdk/source/test/addons/private-browsing-supported/test-windows.js
addon-sdk/source/test/tabs/test-firefox-tabs.js
addon-sdk/source/test/test-addon-window.js
addon-sdk/source/test/test-child_process.js
addon-sdk/source/test/test-native-loader.js
addon-sdk/source/test/test-panel.js
addon-sdk/source/test/test-promise.js
addon-sdk/source/test/test-ui-toggle-button.js
addon-sdk/source/test/test-window-utils-private-browsing.js
browser/base/content/aboutaccounts/aboutaccounts.js
browser/base/content/browser.js
browser/base/content/sanitizeDialog.js
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/content/panelUI.js
browser/components/downloads/DownloadsCommon.jsm
browser/components/downloads/DownloadsTaskbar.jsm
browser/components/nsBrowserGlue.js
browser/components/places/content/browserPlacesViews.js
browser/components/places/content/controller.js
browser/components/places/content/menu.xml
browser/components/places/content/moveBookmarks.js
browser/components/places/content/places.js
browser/components/places/content/treeView.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
browser/components/uitour/UITour.jsm
browser/components/uitour/test/browser_UITour.js
browser/components/uitour/test/browser_UITour2.js
browser/experiments/test/addons/experiment-racybranch/bootstrap.js
browser/extensions/pdfjs/content/web/viewer.js
browser/extensions/pocket/content/main.js
browser/extensions/screenshots/webextension/background/takeshot.js
browser/modules/AboutHome.jsm
devtools/client/canvasdebugger/panel.js
devtools/client/canvasdebugger/test/head.js
devtools/client/commandline/test/helpers.js
devtools/client/debugger/panel.js
devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
devtools/client/debugger/test/mochitest/browser_dbg_auto-pretty-print-02.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-01.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-02.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-03.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-04.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-05.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-06.js
devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-07.js
devtools/client/debugger/test/mochitest/browser_dbg_breadcrumbs-access.js
devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
devtools/client/debugger/test/mochitest/browser_dbg_clean-exit-window.js
devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js
devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
devtools/client/debugger/test/mochitest/browser_dbg_editor-contextmenu.js
devtools/client/debugger/test/mochitest/browser_dbg_editor-mode.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
devtools/client/debugger/test/mochitest/browser_dbg_iframes.js
devtools/client/debugger/test/mochitest/browser_dbg_interrupts.js
devtools/client/debugger/test/mochitest/browser_dbg_jump-to-function-definition.js
devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
devtools/client/debugger/test/mochitest/browser_dbg_no-page-sources.js
devtools/client/debugger/test/mochitest/browser_dbg_optimized-out-vars.js
devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-01.js
devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-02.js
devtools/client/debugger/test/mochitest/browser_dbg_paused-keybindings.js
devtools/client/debugger/test/mochitest/browser_dbg_pretty-print-11.js
devtools/client/debugger/test/mochitest/browser_dbg_promises-allocation-stack.js
devtools/client/debugger/test/mochitest/browser_dbg_promises-chrome-allocation-stack.js
devtools/client/debugger/test/mochitest/browser_dbg_promises-fulfillment-stack.js
devtools/client/debugger/test/mochitest/browser_dbg_promises-rejection-stack.js
devtools/client/debugger/test/mochitest/browser_dbg_reload-preferred-script-03.js
devtools/client/debugger/test/mochitest/browser_dbg_search-basic-02.js
devtools/client/debugger/test/mochitest/browser_dbg_search-basic-03.js
devtools/client/debugger/test/mochitest/browser_dbg_search-global-01.js
devtools/client/debugger/test/mochitest/browser_dbg_search-global-03.js
devtools/client/debugger/test/mochitest/browser_dbg_search-global-04.js
devtools/client/debugger/test/mochitest/browser_dbg_search-global-05.js
devtools/client/debugger/test/mochitest/browser_dbg_search-global-06.js
devtools/client/debugger/test/mochitest/browser_dbg_search-popup-jank.js
devtools/client/debugger/test/mochitest/browser_dbg_search-sources-01.js
devtools/client/debugger/test/mochitest/browser_dbg_search-sources-02.js
devtools/client/debugger/test/mochitest/browser_dbg_search-sources-03.js
devtools/client/debugger/test/mochitest/browser_dbg_search-symbols.js
devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-01.js
devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-02.js
devtools/client/debugger/test/mochitest/browser_dbg_source-maps-01.js
devtools/client/debugger/test/mochitest/browser_dbg_source-maps-02.js
devtools/client/debugger/test/mochitest/browser_dbg_source-maps-03.js
devtools/client/debugger/test/mochitest/browser_dbg_source-maps-04.js
devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-01.js
devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-02.js
devtools/client/debugger/test/mochitest/browser_dbg_sources-keybindings.js
devtools/client/debugger/test/mochitest/browser_dbg_stack-contextmenu-02.js
devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-accessibility.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-01.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-02.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-01.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-02.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-watch.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-01.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-02.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-03.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-04.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-05.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-01.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-02.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-03.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-with.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-large-array-buffer.js
devtools/client/debugger/test/mochitest/browser_dbg_variables-view-webidl.js
devtools/client/debugger/test/mochitest/browser_dbg_watch-expressions-02.js
devtools/client/debugger/test/mochitest/doc_promise-get-allocation-stack.html
devtools/client/debugger/test/mochitest/doc_promise.html
devtools/client/debugger/views/variable-bubble-view.js
devtools/client/devtools-startup.js
devtools/client/framework/test/browser_toolbox_custom_host.js
devtools/client/framework/test/browser_toolbox_raise.js
devtools/client/framework/test/browser_toolbox_sidebar.js
devtools/client/framework/test/browser_toolbox_sidebar_events.js
devtools/client/framework/toolbox.js
devtools/client/inspector/computed/computed.js
devtools/client/inspector/fonts/fonts.js
devtools/client/inspector/inspector.js
devtools/client/inspector/markup/markup.js
devtools/client/inspector/markup/views/element-editor.js
devtools/client/inspector/markup/views/text-editor.js
devtools/client/inspector/rules/models/element-style.js
devtools/client/inspector/rules/rules.js
devtools/client/inspector/shared/highlighters-overlay.js
devtools/client/netmonitor/src/har/har-exporter.js
devtools/client/scratchpad/scratchpad.js
devtools/client/scratchpad/test/browser_scratchpad_pprint-02.js
devtools/client/scratchpad/test/browser_scratchpad_pprint.js
devtools/client/shadereditor/panel.js
devtools/client/shadereditor/shadereditor.js
devtools/client/shadereditor/test/head.js
devtools/client/shared/developer-toolbar.js
devtools/client/shared/redux/middleware/task.js
devtools/client/sourceeditor/autocomplete.js
devtools/client/styleeditor/StyleEditorUI.jsm
devtools/client/styleeditor/StyleSheetEditor.jsm
devtools/client/webaudioeditor/panel.js
devtools/client/webconsole/console-output.js
devtools/client/webconsole/test/browser_console_optimized_out_vars.js
devtools/client/webconsole/test/browser_webconsole_split.js
devtools/client/webide/content/webide.js
devtools/client/webide/modules/app-manager.js
devtools/client/webide/test/test_device_preferences.html
devtools/client/webide/test/test_device_runtime.html
devtools/client/webide/test/test_duplicate_import.html
devtools/client/webide/test/test_import.html
devtools/server/actors/script.js
devtools/server/actors/source.js
devtools/server/actors/utils/TabSources.js
devtools/server/main.js
devtools/server/tests/mochitest/inspector-helpers.js
devtools/server/tests/unit/test_actor-registry-actor.js
devtools/server/tests/unit/test_blackboxing-06.js
devtools/server/tests/unit/test_promise_state-03.js
devtools/server/tests/unit/test_promises_client_getdependentpromises.js
devtools/server/tests/unit/test_protocol_children.js
devtools/server/tests/unit/test_protocol_longstring.js
devtools/server/tests/unit/test_protocol_simple.js
devtools/server/tests/unit/test_sourcemaps-10.js
devtools/server/tests/unit/test_sourcemaps-11.js
devtools/shared/apps/app-actor-front.js
devtools/shared/fronts/device.js
devtools/shared/gcli/templater.js
devtools/shared/protocol.js
devtools/shared/tests/mochitest/test_eventemitter_basic.html
devtools/shared/tests/unit/test_async-utils.js
devtools/shared/transport/tests/unit/test_client_server_bulk.js
dom/crypto/test/test_WebCrypto.html
dom/promise/tests/test_on_promise_settled.html
dom/promise/tests/test_on_promise_settled_duplicates.html
dom/promise/tests/test_promise.html
dom/promise/tests/unit/test_monitor_uncaught.js
dom/security/test/csp/file_service_worker.html
dom/workers/test/promise_worker.js
mobile/android/chrome/content/aboutDownloads.js
mobile/android/chrome/content/browser.js
mobile/android/components/AddonUpdateService.js
mobile/android/components/Snippets.js
netwerk/protocol/http/UserAgentUpdates.jsm
netwerk/test/mochitests/test_user_agent_updates.html
security/manager/ssl/tests/mochitest/mixedcontent/test_bug383369.html
services/fxaccounts/FxAccounts.jsm
services/fxaccounts/tests/xpcshell/test_accounts.js
services/fxaccounts/tests/xpcshell/test_oauth_grant_client.js
services/fxaccounts/tests/xpcshell/test_profile_client.js
services/sync/modules/browserid_identity.js
services/sync/modules/engines/history.js
services/sync/tps/extensions/tps/resource/modules/bookmarks.jsm
testing/modules/Assert.jsm
toolkit/components/asyncshutdown/AsyncShutdown.jsm
toolkit/components/jsdownloads/src/DownloadCore.jsm
toolkit/components/jsdownloads/src/DownloadIntegration.jsm
toolkit/components/jsdownloads/src/DownloadLegacy.js
toolkit/components/jsdownloads/src/DownloadList.jsm
toolkit/components/jsdownloads/test/unit/head.js
toolkit/components/osfile/modules/osfile_async_front.jsm
toolkit/components/passwordmgr/LoginManagerContent.jsm
toolkit/components/passwordmgr/nsLoginManager.js
toolkit/components/places/Bookmarks.jsm
toolkit/components/places/PlacesUtils.jsm
toolkit/components/places/UnifiedComplete.js
toolkit/components/places/tests/unit/test_bookmarks_restore_notification.js
toolkit/components/thumbnails/PageThumbs.jsm
toolkit/content/contentAreaUtils.js
toolkit/modules/DeferredTask.jsm
toolkit/modules/ZipUtils.jsm
toolkit/mozapps/downloads/nsHelperAppDlg.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/DeferredSave.jsm
toolkit/mozapps/extensions/internal/AddonRepository.jsm
toolkit/mozapps/extensions/internal/GMPProvider.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/internal/XPIProviderUtils.js
toolkit/mozapps/extensions/test/browser/head.js
--- a/addon-sdk/source/lib/sdk/addon/runner.js
+++ b/addon-sdk/source/lib/sdk/addon/runner.js
@@ -65,28 +65,28 @@ function startup(reason, options) {
 
     // NOTE: Module is intentionally required only now because it relies
     // on existence of hidden window, which does not exists until startup.
     let { ready } = require('../addon/window');
     // Load localization manifest and .properties files.
     // Run the addon even in case of error (best effort approach)
     require('../l10n/loader').
       load(rootURI).
-      then(null, function failure(error) {
+      catch(function failure(error) {
         if (!isNative)
           console.info("Error while loading localization: " + error.message);
       }).
       then(function onLocalizationReady(data) {
         // Exports data to a pseudo module so that api-utils/l10n/core
         // can get access to it
         definePseudo(options.loader, '@l10n/data', data ? data : null);
         return ready;
       }).then(function() {
         run(options);
-      }).then(null, console.exception);
+      }).catch(console.exception);
     return void 0; // otherwise we raise a warning, see bug 910304
   });
 }
 
 function run(options) {
   try {
     // Try initializing HTML localization before running main module. Just print
     // an exception in case of error, instead of preventing addon to be run.
--- a/addon-sdk/source/lib/sdk/l10n/loader.js
+++ b/addon-sdk/source/lib/sdk/l10n/loader.js
@@ -10,17 +10,17 @@ module.metadata = {
 const { Cc, Ci } = require("chrome");
 lazyRequire(this, "./locale", "getPreferedLocales", "findClosestLocale");
 lazyRequire(this, "../net/url", "readURI");
 lazyRequire(this, "../core/promise", "resolve");
 
 function parseJsonURI(uri) {
   return readURI(uri).
     then(JSON.parse).
-    then(null, function (error) {
+    catch(function (error) {
       throw Error("Failed to parse locale file:\n" + uri + "\n" + error);
     });
 }
 
 // Returns the array stored in `locales.json` manifest that list available
 // locales files
 function getAvailableLocales(rootURI) {
   let uri = rootURI + "locales.json";
--- a/addon-sdk/source/test/addons/page-mod-debugger-post/main.js
+++ b/addon-sdk/source/test/addons/page-mod-debugger-post/main.js
@@ -38,17 +38,17 @@ exports.testDebugger = function(assert, 
           then(_ => { assert.pass('attachTabActorForUrl called'); return _; }).
           then(attachThread).
           then(testDebuggerStatement).
           then(_ => { assert.pass('testDebuggerStatement called') }).
           then(closeConnection).
           then(_ => { assert.pass('closeConnection called') }).
           then(_ => { tab.close() }).
           then(done).
-          then(null, aError => {
+          catch(aError => {
             ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
           });
       }
     });
   });
 }
 
 function attachThread([aGrip, aResponse]) {
--- a/addon-sdk/source/test/addons/page-mod-debugger-pre/main.js
+++ b/addon-sdk/source/test/addons/page-mod-debugger-pre/main.js
@@ -45,17 +45,17 @@ exports.testDebugger = function(assert, 
           then(_ => { assert.pass('attachTabActorForUrl called'); return _; }).
           then(attachThread).
           then(testDebuggerStatement).
           then(_ => { assert.pass('testDebuggerStatement called') }).
           then(closeConnection).
           then(_ => { assert.pass('closeConnection called') }).
           then(_ => { tab.close() }).
           then(done).
-          then(null, aError => {
+          catch(aError => {
             ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
           });
       }
     });
   });
 }
 
 function attachThread([aGrip, aResponse]) {
--- a/addon-sdk/source/test/addons/places/lib/test-places-host.js
+++ b/addon-sdk/source/test/addons/places/lib/test-places-host.js
@@ -61,17 +61,17 @@ exports.testBookmarksCreateFail = functi
     type: 'bookmark'
   }, {
     type: 'group',
     group: bmsrv.bookmarksMenuFolder
   }, {
     group: bmsrv.unfiledBookmarksFolder
   }];
   all(items.map(function (item) {
-    return send('sdk-places-bookmarks-create', item).then(null, function (reason) {
+    return send('sdk-places-bookmarks-create', item).catch(function (reason) {
       assert.ok(reason, 'bookmark create should fail');
     });
   })).then(done);
 };
 
 exports.testBookmarkLastUpdated = function (assert, done) {
   let timestamp;
   let item;
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-selection.js
+++ b/addon-sdk/source/test/addons/private-browsing-supported/test-selection.js
@@ -228,24 +228,24 @@ exports["test PWPB Selection Listener"] 
           assert.ok(isFocused(window), "the window is focused");
           assert.ok(isPrivate(window), "the window should be a private window");
 
           assert.equal(selection.text, "fo");
 
           closeWindow(window).
             then(loader.unload).
             then(done).
-            then(null, assert.fail);
+            catch(assert.fail);
         });
       });
       return window;
     }).
     then(selectContentFirstDiv).
     then(dispatchSelectionEvent).
-    then(null, assert.fail);
+    catch(assert.fail);
 };
 
 exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
   let loader = Loader(module);
   let selection = loader.require("sdk/selection");
 
   open(URL, {private: true, title: "PWPB OnSelect Listener"}).
     then(function(window) {
@@ -258,24 +258,24 @@ exports["test PWPB Textarea OnSelect Lis
 
         // window should be focused, but force the focus anyhow.. see bug 841823
         focus(window).then(function() {
           assert.equal(selection.text, "noodles");
 
           closeWindow(window).
             then(loader.unload).
             then(done).
-            then(null, assert.fail);
+            catch(assert.fail);
         });
       });
       return window;
     }).
     then(selectTextarea).
     then(dispatchOnSelectEvent).
-    then(null, assert.fail);
+    catch(assert.fail);
 };
 
 exports["test PWPB Single DOM Selection"] = function(assert, done) {
   let loader = Loader(module);
   let selection = loader.require("sdk/selection");
 
   open(URL, {private: true, title: "PWPB Single DOM Selection"}).
     then(selectFirstDiv).
@@ -299,17 +299,17 @@ exports["test PWPB Single DOM Selection"
         assert.equal(sel.html, "<div>foo</div>",
           "iterable selection.html with single DOM Selection works.");
       }
 
       assert.equal(selectionCount, 1,
         "One iterable selection");
 
       return closeWindow(window);
-    }).then(loader.unload).then(done).then(null, assert.fail);
+    }).then(loader.unload).then(done).catch(assert.fail);
 }
 
 exports["test PWPB Textarea Selection"] = function(assert, done) {
   let loader = Loader(module);
   let selection = loader.require("sdk/selection");
 
   open(URL, {private: true, title: "PWPB Textarea Listener"}).
     then(selectTextarea).
@@ -335,17 +335,17 @@ exports["test PWPB Textarea Selection"] 
         assert.strictEqual(sel.html, null,
           "iterable selection.html with Textarea Selection works.");
       }
 
       assert.equal(selectionCount, 1,
         "One iterable selection");
 
       return closeWindow(window);
-    }).then(loader.unload).then(done).then(null, assert.fail);
+    }).then(loader.unload).then(done).catch(assert.fail);
 };
 
 exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
   let loader = Loader(module);
   let selection = loader.require("sdk/selection");
 
   open(URL, {private: true, title: "PWPB Set HTML in Multiple DOM Selection"}).
     then(selectAllDivs).
@@ -375,17 +375,17 @@ exports["test PWPB Set HTML in Multiple 
 
         selectionCount++;
       }
 
       assert.equal(selectionCount, 2,
         "Two iterable selections");
 
       return closeWindow(window);
-    }).then(loader.unload).then(done).then(null, assert.fail);
+    }).then(loader.unload).then(done).catch(assert.fail);
 };
 
 exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
   let loader = Loader(module);
   let selection = loader.require("sdk/selection");
 
   open(URL, {private: true, title: "test PWPB Set Text in Textarea Selection"}).
     then(selectTextarea).
@@ -412,17 +412,17 @@ exports["test PWPB Set Text in Textarea 
         assert.strictEqual(sel.html, null,
           "iterable selection.html with Textarea Selection works.");
       }
 
       assert.equal(selectionCount, 1,
         "One iterable selection");
 
       return closeWindow(window);
-    }).then(loader.unload).then(done).then(null, assert.fail);
+    }).then(loader.unload).then(done).catch(assert.fail);
 };
 
 // If the platform doesn't support the PBPW, we're replacing PBPW tests
 if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
   module.exports = {
     "test PBPW Unsupported": function Unsupported (assert) {
       assert.pass("Private Window Per Browsing is not supported on this platform.");
     }
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-sidebar.js
+++ b/addon-sdk/source/test/addons/private-browsing-supported/test-sidebar.js
@@ -35,17 +35,17 @@ exports.testSideBarIsInNewPrivateWindows
       assert.ok(isPrivate(window), 'the new window is private');
       assert.ok(!!ele, 'sidebar element was added');
 
       sidebar.destroy();
       assert.ok(!window.document.getElementById(makeID(testName)), 'sidebar id DNE');
       assert.ok(!startWindow.document.getElementById(makeID(testName)), 'sidebar id DNE');
 
       return close(window);
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 }
 
 // Disabled in order to land other fixes, see bug 910647 for further details.
 /*
 exports.testSidebarIsOpenInNewPrivateWindow = function(assert, done) {
   const { Sidebar } = require('sdk/ui/sidebar');
   let testName = 'testSidebarIsOpenInNewPrivateWindow';
   let window = getMostRecentBrowserWindow();
@@ -137,18 +137,18 @@ exports.testDestroyEdgeCaseBugWithPrivat
           assert.equal(isSidebarShowing(window), false, 'the sidebar is not showing');
 
           done();
         }
       })
 
       sidebar.show();
       assert.pass('showing the sidebar');
-    }).then(null, assert.fail);
-  }).then(null, assert.fail);
+    }).catch(assert.fail);
+  }).catch(assert.fail);
 }
 
 exports.testShowInPrivateWindow = function(assert, done) {
   const { Sidebar } = require('sdk/ui/sidebar');
   let testName = 'testShowInPrivateWindow';
   let window1 = getMostRecentBrowserWindow();
   let url = 'data:text/html;charset=utf-8,'+testName;
 
@@ -183,22 +183,22 @@ exports.testShowInPrivateWindow = functi
                   'the menuitem on the new window dne');
 
         // test old window state
         assert.equal(isSidebarShowing(window1), false, 'the old window sidebar is not showing');
         assert.equal(window1.document.getElementById(menuitemID),
                      null,
                      'the menuitem on the old window dne');
 
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       },
       function bad() {
         assert.fail('a successful show should not happen here..');
       });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 // If the module doesn't support the app we're being run in, require() will
 // throw.  In that case, remove all tests above from exports, and add one dummy
 // test that passes.
 try {
   require('sdk/ui/sidebar');
 }
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-window-tabs.js
+++ b/addon-sdk/source/test/addons/private-browsing-supported/test-window-tabs.js
@@ -13,63 +13,63 @@ exports.testOpenTabWithPrivateActiveWind
 
   windowPromise(window, 'load').then(focus).then(function (window) {
     assert.ok(isPrivate(window), 'new window is private');
 
     tabs.open({
       url: 'about:blank',
       onOpen: function(tab) {
         assert.ok(isPrivate(tab), 'new tab is private');
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     })
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 exports.testOpenTabWithNonPrivateActiveWindowNoIsPrivateOption = function(assert, done) {
   let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
 
   windowPromise(window, 'load').then(focus).then(function (window) {
     assert.equal(isPrivate(window), false, 'new window is not private');
 
     tabs.open({
       url: 'about:blank',
       onOpen: function(tab) {
         assert.equal(isPrivate(tab), false, 'new tab is not private');
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     })
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 exports.testOpenTabWithPrivateActiveWindowWithIsPrivateOptionTrue = function(assert, done) {
   let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: true });
 
   windowPromise(window, 'load').then(focus).then(function (window) {
     assert.ok(isPrivate(window), 'new window is private');
 
     tabs.open({
       url: 'about:blank',
       isPrivate: true,
       onOpen: function(tab) {
         assert.ok(isPrivate(tab), 'new tab is private');
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     })
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 exports.testOpenTabWithNonPrivateActiveWindowWithIsPrivateOptionFalse = function(assert, done) {
   let window = getMostRecentBrowserWindow().OpenBrowserWindow({ private: false });
 
   windowPromise(window, 'load').then(focus).then(function (window) {
     assert.equal(isPrivate(window), false, 'new window is not private');
 
     tabs.open({
       url: 'about:blank',
       isPrivate: false,
       onOpen: function(tab) {
         assert.equal(isPrivate(tab), false, 'new tab is not private');
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     })
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
--- a/addon-sdk/source/test/addons/private-browsing-supported/test-windows.js
+++ b/addon-sdk/source/test/addons/private-browsing-supported/test-windows.js
@@ -69,17 +69,17 @@ exports.testWindowTrackerIgnoresPrivateW
       assert.pass('private window was closed');
 
       return makeEmptyBrowserWindow().then(function(window) {
         myNonPrivateWindowId = getInnerId(window);
         assert.notEqual(myPrivateWindowId, myNonPrivateWindowId, 'non private window was opened');
         return close(window);
       });
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // Test setting activeWIndow and onFocus for private windows
 exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
   let browserWindow = WM.getMostRecentWindow("navigator:browser");
   let testSteps;
 
   assert.equal(winUtils.activeBrowserWindow, browserWindow,
@@ -141,17 +141,17 @@ exports.testSettingActiveWindowDoesNotIg
         continueAfterFocus(winUtils.activeWindow = browserWindow);
       },
       function() {
         assert.strictEqual(winUtils.activeBrowserWindow, browserWindow,
                           "Correct active browser window when pb mode is supported [4]");
         assert.strictEqual(winUtils.activeWindow, browserWindow,
                           "Correct active window when pb mode is supported [4]");
 
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     ];
 
     function nextTest() {
       let args = arguments;
       if (testSteps.length) {
         require('sdk/timers').setTimeout(function() {
           (testSteps.shift()).apply(null, args);
@@ -231,10 +231,10 @@ exports.testWindowIteratorPrivateDefault
     assert.equal(isPrivate(winUtils.activeWindow), isWindowPBSupported);
     assert.equal(isPrivate(getMostRecentWindow()), isWindowPBSupported);
     assert.equal(isPrivate(browserWindows.activeWindow), isWindowPBSupported);
 
     assert.equal(browserWindows.length, 2, '2 windows open');
     assert.equal(windows(null, { includePrivate: true }).length, 2);
 
     return close(window);
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 };
--- a/addon-sdk/source/test/tabs/test-firefox-tabs.js
+++ b/addon-sdk/source/test/tabs/test-firefox-tabs.js
@@ -70,17 +70,17 @@ exports.testBrowserWindowCreationOnActiv
   tabs.once('activate', function onActivate(eventTab) {
     assert.ok(windows.activeWindow, "Is able to fetch activeWindow");
     gotActivate = true;
   });
 
   open().then(function(window) {
     assert.ok(gotActivate, "Received activate event");
     return close(window);
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 }
 
 // TEST: tab unloader
 exports.testAutomaticDestroyEventOpen = function(assert, done) {
   let called = false;
   let loader = Loader(module);
   let tabs2 = loader.require("sdk/tabs");
   tabs2.on('open', _ => called = true);
@@ -171,17 +171,17 @@ exports.testTabPropertiesInNewWindow = f
   });
 
   let tabs = loader.require('sdk/tabs');
   let { viewFor } = loader.require('sdk/view/core');
 
   let count = 0;
   function onReadyOrLoad (tab) {
     if (count++) {
-      close(getOwnerWindow(viewFor(tab))).then(done).then(null, assert.fail);
+      close(getOwnerWindow(viewFor(tab))).then(done).catch(assert.fail);
     }
   }
 
   let url = "data:text/html;charset=utf-8,<html><head><title>foo</title></head><body>foo</body></html>";
   tabs.open({
     inNewWindow: true,
     url: url,
     onReady: function(tab) {
@@ -264,17 +264,17 @@ exports.testTabContentTypeAndReload = fu
       url: url,
       onReady: function(tab) {
         if (tab.url === url) {
           assert.equal(tab.contentType, "text/html");
           tab.url = urlXML;
         }
         else {
           assert.equal(tab.contentType, "text/xml");
-          close(window).then(done).then(null, assert.fail);
+          close(window).then(done).catch(assert.fail);
         }
       }
     });
   });
 };
 
 // TEST: tabs iterator and length property
 exports.testTabsIteratorAndLength = function(assert, done) {
@@ -289,34 +289,34 @@ exports.testTabsIteratorAndLength = func
     tabs.open({
       url: url,
       onOpen: function(tab) {
         let count = 0;
         for (let t of tabs) count++;
         assert.equal(count, startCount + 3, "iterated tab count matches");
         assert.equal(startCount + 3, tabs.length, "iterated tab count matches length property");
 
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     });
   });
 };
 
 // TEST: tab.url setter
 exports.testTabLocation = function(assert, done) {
   open().then(focus).then(function(window) {
     let url1 = "data:text/html;charset=utf-8,foo";
     let url2 = "data:text/html;charset=utf-8,bar";
 
     tabs.on('ready', function onReady(tab) {
       if (tab.url != url2)
         return;
       tabs.removeListener('ready', onReady);
       assert.pass("tab.load() loaded the correct url");
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     });
 
     tabs.open({
       url: url1,
       onOpen: function(tab) {
         tab.url = url2
       }
     });
@@ -360,20 +360,20 @@ exports.testTabMove = function(assert, d
     let url = "data:text/html;charset=utf-8,foo";
 
     tabs.open({
       url: url,
       onOpen: function(tab) {
         assert.equal(tab.index, 1, "tab index before move matches");
         tab.index = 0;
         assert.equal(tab.index, 0, "tab index after move matches");
-        close(window).then(done).then(null, assert.fail);
+        close(window).then(done).catch(assert.fail);
       }
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testIgnoreClosing = function*(assert) {
   let url = "data:text/html;charset=utf-8,foobar";
   let originalWindow = getMostRecentBrowserWindow();
 
   let window = yield open().then(focus);
 
@@ -476,17 +476,17 @@ exports.testOpenInNewWindow = function(a
 
       onFocus(newWindow).then(function() {
         assert.equal(getMostRecentBrowserWindow(), newWindow, "new window is active");
         assert.equal(tab.url, url, "URL of the new tab matches");
         assert.equal(newWindow.content.location, url, "URL of new tab in new window matches");
         assert.equal(tabs.activeTab.url, url, "URL of activeTab matches");
 
         return close(newWindow).then(done);
-      }).then(null, assert.fail);
+      }).catch(assert.fail);
     }
   });
 
 }
 
 // Test tab.open inNewWindow + onOpen combination
 exports.testOpenInNewWindowOnOpen = function(assert, done) {
   let startWindowCount = windows().length;
@@ -497,17 +497,17 @@ exports.testOpenInNewWindowOnOpen = func
     inNewWindow: true,
     onOpen: function(tab) {
       let newWindow = getOwnerWindow(viewFor(tab));
 
       onFocus(newWindow).then(function() {
         assert.equal(windows().length, startWindowCount + 1, "a new window was opened");
         assert.equal(getMostRecentBrowserWindow(), newWindow, "new window is active");
 
-        close(newWindow).then(done).then(null, assert.fail);
+        close(newWindow).then(done).catch(assert.fail);
       });
     }
   });
 };
 
 // TEST: onOpen event handler
 exports.testTabsEvent_onOpen = function(assert, done) {
   open().then(focus).then(window => {
@@ -520,21 +520,21 @@ exports.testTabsEvent_onOpen = function(
     };
     tabs.on('open', listener1);
 
     // add listener via collection add
     tabs.on('open', function listener2(tab) {
       assert.equal(++eventCount, 2, "both listeners notified");
       tabs.removeListener('open', listener1);
       tabs.removeListener('open', listener2);
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     });
 
     tabs.open(url);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // TEST: onClose event handler
 exports.testTabsEvent_onClose = function*(assert) {
   let window = yield open().then(focus);
   let url = "data:text/html;charset=utf-8,onclose";
   let eventCount = 0;
 
@@ -616,17 +616,17 @@ exports.testTabsEvent_onCloseWindow = fu
       onClose: endTest
     });
 
     tabs.open({
       url: "data:text/html;charset=utf-8,tab4",
       onOpen: testCasePossiblyLoaded,
       onClose: endTest
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 // TEST: onReady event handler
 exports.testTabsEvent_onReady = function(assert, done) {
   open().then(focus).then(window => {
     let url = "data:text/html;charset=utf-8,onready";
     let eventCount = 0;
 
@@ -640,17 +640,17 @@ exports.testTabsEvent_onReady = function
     tabs.on('ready', function listener2(tab) {
       assert.equal(++eventCount, 2, "both listeners notified");
       tabs.removeListener('ready', listener1);
       tabs.removeListener('ready', listener2);
       close(window).then(done);
     });
 
     tabs.open(url);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // TEST: onActivate event handler
 exports.testTabsEvent_onActivate = function(assert, done) {
   open().then(focus).then(window => {
     let url = "data:text/html;charset=utf-8,onactivate";
     let eventCount = 0;
 
@@ -660,21 +660,21 @@ exports.testTabsEvent_onActivate = funct
     };
     tabs.on('activate', listener1);
 
     // add listener via collection add
     tabs.on('activate', function listener2(tab) {
       assert.equal(++eventCount, 2, "both listeners notified");
       tabs.removeListener('activate', listener1);
       tabs.removeListener('activate', listener2);
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     });
 
     tabs.open(url);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // onDeactivate event handler
 exports.testTabsEvent_onDeactivate = function*(assert) {
   let window = yield open().then(focus);
 
   let url = "data:text/html;charset=utf-8,ondeactivate";
   let eventCount = 0;
@@ -721,21 +721,21 @@ exports.testTabsEvent_pinning = function
       tabs.removeListener('pinned', onPinned);
       assert.ok(tab.isPinned, "notified tab is pinned");
       tab.unpin();
     });
 
     tabs.on('unpinned', function onUnpinned(tab) {
       tabs.removeListener('unpinned', onUnpinned);
       assert.ok(!tab.isPinned, "notified tab is not pinned");
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     });
 
     tabs.open(url);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // TEST: per-tab event handlers
 exports.testPerTabEvents = function*(assert) {
   let window = yield open().then(focus);
   let eventCount = 0;
 
   let tab = yield new Promise(resolve => {
@@ -835,19 +835,19 @@ exports.testAttachOnMultipleDocuments = 
     });
 
     function checkEnd() {
       if (detachEventCount != 2)
         return;
 
       assert.pass("Got all detach events");
 
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     }
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 
 exports.testAttachWrappers = function (assert, done) {
   // Check that content script has access to wrapped values by default
   open().then(focus).then(window => {
     let document = "data:text/html;charset=utf-8,<script>var globalJSVar = true; " +
                    "                       document.getElementById = 3;</script>";
@@ -861,22 +861,22 @@ exports.testAttachWrappers = function (a
                          '  self.postMessage(!("globalJSVar" in window));' +
                          '  self.postMessage(typeof window.globalJSVar == "undefined");' +
                          '} catch(e) {' +
                          '  self.postMessage(e.message);' +
                          '}',
           onMessage: function (msg) {
             assert.equal(msg, true, "Worker has wrapped objects ("+count+")");
             if (count++ == 1)
-              close(window).then(done).then(null, assert.fail);
+              close(window).then(done).catch(assert.fail);
           }
         });
       }
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 /*
 // We do not offer unwrapped access to DOM since bug 601295 landed
 // See 660780 to track progress of unwrap feature
 exports.testAttachUnwrapped = function (assert, done) {
   // Check that content script has access to unwrapped values through unsafeWindow
   openBrowserWindow(function(window, browser) {
@@ -926,34 +926,34 @@ exports['test window focus changes activ
 
           function whenReady(tab) {
             assert.pass("activate was called on windows focus change.");
             assert.equal(tab.url, url1, 'the activated tab url is correct');
 
             return close(win2).then(function() {
               assert.pass('window 2 was closed');
               return close(win1);
-            }).then(done).then(null, assert.fail);
+            }).then(done).catch(assert.fail);
           }
         });
 
         win1.focus();
       });
     }, "data:text/html;charset=utf-8,test window focus changes active tab</br><h1>Window #2");
   }, url1);
 };
 
 exports['test ready event on new window tab'] = function(assert, done) {
   let uri = encodeURI("data:text/html;charset=utf-8,Waiting for ready event!");
 
   require("sdk/tabs").on("ready", function onReady(tab) {
     if (tab.url === uri) {
       require("sdk/tabs").removeListener("ready", onReady);
       assert.pass("ready event was emitted");
-      close(window).then(done).then(null, assert.fail);
+      close(window).then(done).catch(assert.fail);
     }
   });
 
   let window = openBrowserWindow(function(){}, uri);
 };
 
 exports['test unique tab ids'] = function(assert, done) {
   var windows = require('sdk/windows').browserWindows;
--- a/addon-sdk/source/test/test-addon-window.js
+++ b/addon-sdk/source/test/test-addon-window.js
@@ -11,12 +11,12 @@ exports.testReady = function(assert, don
   let windowIsReady = false;
 
   ready.then(function() {
     assert.equal(windowIsReady, false, 'ready promise was resolved only once');
     windowIsReady = true;
 
     loader.unload();
     done();
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 require('sdk/test').run(exports);
--- a/addon-sdk/source/test/test-child_process.js
+++ b/addon-sdk/source/test/test-child_process.js
@@ -61,17 +61,17 @@ exports.testExecOptionsEnvironment = fun
       env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
     }, function (err, stdout, stderr) {
       assert.equal(stderr, '', 'stderr is empty');
       assert.ok(!err, 'received `cwd` option');
       assert.ok(/my-value-test/.test(stdout),
         'receives environment option');
       done();
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testExecOptionsTimeout = function (assert, done) {
   let count = 0;
   getScript('wait').then(script => {
     let child = exec(script, { timeout: 100 }, (err, stdout, stderr) => {
       assert.equal(err.killed, true, 'error has `killed` property as true');
       assert.equal(err.code, null, 'error has `code` as null');
@@ -99,29 +99,29 @@ exports.testExecOptionsTimeout = functio
     child.on('exit', exitHandler);
     child.on('close', closeHandler);
 
     function complete () {
       child.off('exit', exitHandler);
       child.off('close', closeHandler);
       done();
     }
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testExecFileCallbackSuccess = function (assert, done) {
   getScript('args').then(script => {
     execFile(script, ['--myargs', '-j', '-s'], { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
       assert.ok(!err, 'no errors found');
       assert.equal(stderr, '', 'stderr is empty');
       // Trim output since different systems have different new line output
       assert.equal(stdout.trim(), '--myargs -j -s'.trim(), 'passes in correct arguments');
       done();
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testExecFileCallbackError = function (assert, done) {
   execFile('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
     assert.ok(/Executable not found/.test(err.message),
       `error '${err.message}' contains error message`);
     assert.ok(err.lineNumber >= 0, 'error contains lineNumber');
     assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName');
@@ -138,17 +138,17 @@ exports.testExecFileOptionsEnvironment =
       env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
     }, function (err, stdout, stderr) {
       assert.equal(stderr, '', 'stderr is empty');
       assert.ok(!err, 'received `cwd` option');
       assert.ok(/my-value-test/.test(stdout),
         'receives environment option');
       done();
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testExecFileOptionsTimeout = function (assert, done) {
   let count = 0;
   getScript('wait').then(script => {
     let child = execFile(script, { timeout: 100 }, (err, stdout, stderr) => {
       assert.equal(err.killed, true, 'error has `killed` property as true');
       assert.equal(err.code, null, 'error has `code` as null');
@@ -176,17 +176,17 @@ exports.testExecFileOptionsTimeout = fun
     child.on('exit', exitHandler);
     child.on('close', closeHandler);
 
     function complete () {
       child.off('exit', exitHandler);
       child.off('close', closeHandler);
       done();
     }
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 /**
  * Not necessary to test for both `exec` and `execFile`, but
  * it is necessary to test both when the buffer is larger
  * and smaller than buffer size used by the subprocess library (1024)
  */
 exports.testExecFileOptionsMaxBufferLargeStdOut = function (assert, done) {
@@ -199,17 +199,17 @@ exports.testExecFileOptionsMaxBufferLarg
       assert.ok(/stdout maxBuffer exceeded/.test(err.toString()),
         'error contains stdout maxBuffer exceeded message');
       assert.ok(stdout.length >= 50, 'stdout has full buffer');
       assert.equal(stderr, '', 'stderr is empty');
       if (++count === 3) complete();
     });
     stdoutChild.on('exit', exitHandler);
     stdoutChild.on('close', closeHandler);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 
   function exitHandler (code, signal) {
     assert.equal(code, null, 'Exit code is null in exit handler');
     assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
     if (++count === 3) complete();
   }
 
   function closeHandler (code, signal) {
@@ -234,17 +234,17 @@ exports.testExecFileOptionsMaxBufferLarg
       assert.ok(/stderr maxBuffer exceeded/.test(err.toString()),
         'error contains stderr maxBuffer exceeded message');
       assert.ok(stderr.length >= 50, 'stderr has full buffer');
       assert.equal(stdout, '', 'stdout is empty');
       if (++count === 3) complete();
     });
     stderrChild.on('exit', exitHandler);
     stderrChild.on('close', closeHandler);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 
   function exitHandler (code, signal) {
     assert.equal(code, null, 'Exit code is null in exit handler');
     assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
     if (++count === 3) complete();
   }
 
   function closeHandler (code, signal) {
@@ -275,17 +275,17 @@ exports.testExecFileOptionsMaxBufferSmal
       assert.ok(/stdout maxBuffer exceeded/.test(err.toString()),
         'error contains stdout maxBuffer exceeded message');
       assert.ok(stdout.length >= 50, 'stdout has full buffer');
       assert.equal(stderr, '', 'stderr is empty');
       if (++count === 3) complete();
     });
     stdoutChild.on('exit', exitHandler);
     stdoutChild.on('close', closeHandler);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 
   function exitHandler (code, signal) {
     // Sometimes the buffer limit is hit before the process closes successfully
     // on both OSX/Windows
     if (code === null) {
       assert.equal(code, null, 'Exit code is null in exit handler');
       assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
     }
@@ -326,17 +326,17 @@ exports.testExecFileOptionsMaxBufferSmal
       assert.ok(/stderr maxBuffer exceeded/.test(err.toString()),
         'error contains stderr maxBuffer exceeded message');
       assert.ok(stderr.length >= 50, 'stderr has full buffer');
       assert.equal(stdout, '', 'stdout is empty');
       if (++count === 3) complete();
     });
     stderrChild.on('exit', exitHandler);
     stderrChild.on('close', closeHandler);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 
   function exitHandler (code, signal) {
     // Sometimes the buffer limit is hit before the process closes successfully
     // on both OSX/Windows
     if (code === null) {
       assert.equal(code, null, 'Exit code is null in exit handler');
       assert.equal(signal, 'SIGTERM', 'Signal is SIGTERM in exit handler');
     }
@@ -372,17 +372,17 @@ exports.testChildExecFileKillSignal = fu
   getScript('wait').then(script => {
     execFile(script, {
       killSignal: 'beepbeep',
       timeout: 10
     }, function (err, stdout, stderr) {
       assert.equal(err.signal, 'beepbeep', 'correctly used custom killSignal');
       done();
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 exports.testChildProperties = function (assert, done) {
   getScript('check-env').then(script => {
     let child = spawn(script, {
       env: { CHILD_PROCESS_ENV_TEST: 'my-value-test' }
     });
 
@@ -503,17 +503,17 @@ exports.testSpawnOptions = function (ass
     cwdChild = spawn(checkPwd, { cwd: PROFILE_DIR });
 
     // Do these need to be unbound?
     envChild.stdout.on('data', data => envStdout += data);
     cwdChild.stdout.on('data', data => cwdStdout += data);
 
     envChild.on('close', envClose);
     cwdChild.on('close', cwdClose);
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 
   function envClose () {
     assert.equal(envStdout.trim(), 'my-value-test', 'spawn correctly passed in ENV');
     if (++count === 2) complete();
   }
 
   function cwdClose () {
     // Check for PROFILE_DIR in the output because
--- a/addon-sdk/source/test/test-native-loader.js
+++ b/addon-sdk/source/test/test-native-loader.js
@@ -232,17 +232,17 @@ for (let variant of variants) {
         manifest: manifest,
         isNative: true
       });
 
       let program = main(loader);
       testLoader(program, assert);
       unload(loader);
       done();
-    }).then(null, (reason) => console.error(reason));
+    }).catch((reason) => console.error(reason));
   };
 
   exports[`test require#resolve with relative, dependencies (${variant.description})`] = function(assert, done) {
     getJSON('/fixtures/native-addon-test/package.json').then(manifest => {
       let rootURI = variant.getRootURI('native-addon-test');
       let loader = Loader({
         paths: makePaths(rootURI),
         rootURI: rootURI,
@@ -260,17 +260,17 @@ for (let variant of variants) {
       assert.equal(program.require.resolve("modules/Promise.jsm"), "resource://gre/modules/Promise.jsm", "works with path lookups");
 
       // TODO bug 1050422, handle loading non JS/JSM file paths
       // assert.equal(program.require.resolve("test-assets/styles.css"), fixtureRoot + "node_modules/test-assets/styles.css",
       // "works with different file extension lookups in dependencies");
 
       unload(loader);
       done();
-    }).then(null, (reason) => console.error(reason));
+    }).catch((reason) => console.error(reason));
   };
 }
 
 before(exports, () => {
   for (let fixture of fixtures) {
     let url = `jar:${root}/fixtures/${fixture}.xpi!/`;
 
     resProto.setSubstitution(fixture, NetUtil.newURI(url));
@@ -304,17 +304,17 @@ exports['test JSM loading'] = function (
       program.isLoadedAbsolute(20),
       program.isLoadedJSAbsolute(30)
     ]).then(([path, absolute, jsabsolute]) => {
       assert.equal(path, 10, 'JSM files resolved from path work');
       assert.equal(absolute, 20, 'JSM files resolved from full resource:// work');
       assert.equal(jsabsolute, 30, 'JS files resolved from full resource:// work');
     }).then(done, console.error);
 
-  }).then(null, console.error);
+  }).catch(console.error);
 };
 
 function testLoader (program, assert) {
   // Test 'main' entries
   // no relative custom main `lib/index.js`
   assert.equal(program.customMainModule, 'custom entry file',
     'a node_module dependency correctly uses its `main` entry in manifest');
   // relative custom main `./lib/index.js`
@@ -383,12 +383,12 @@ function loadAddon (uri, map) {
       rootURI: rootURI,
       manifest: manifest,
       isNative: true,
       modules: {
         '@test/options': testOptions
       }
     });
     let program = main(loader);
-  }).then(null, console.error);
+  }).catch(console.error);
 }
 
 require('sdk/test').run(exports);
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -1016,17 +1016,17 @@ exports['test panel CSS'] = function(ass
       assert.equal(div.offsetHeight, 120,
         "Panel contentStyleFile worked");
 
       assert.equal(window.getComputedStyle(div).borderTopStyle, "dashed",
         "Panel contentStyleFile with relative path worked");
 
         loader.unload();
         done();
-      }).then(null, assert.fail);
+      }).catch(assert.fail);
     }
   });
 
   panel.show();
 };
 
 exports['test panel contentScriptFile'] = function(assert, done) {
   const { merge } = require("sdk/util/object");
--- a/addon-sdk/source/test/test-promise.js
+++ b/addon-sdk/source/test/test-promise.js
@@ -112,22 +112,22 @@ exports['test error recovery with promis
     let deferred = defer();
     deferred.resolve('recovery');
     return deferred.promise;
   }).then(function(actual) {
     assert.equal(actual, 'recovery', 'recorvered via promise');
     let deferred = defer();
     deferred.reject('error');
     return deferred.promise;
-  }).then(null, function(actual) {
+  }).catch(function(actual) {
     assert.equal(actual, 'error', 'rejected via promise');
     let deferred = defer();
     deferred.reject('end');
     return deferred.promise;
-  }).then(null, function(actual) {
+  }).catch(function(actual) {
     assert.equal(actual, 'end', 'rejeced via promise');
     done();
   });
 
   deferred.reject('reason');
 };
 
 exports['test propagation'] = function(assert, done) {
@@ -145,27 +145,27 @@ exports['test propagation'] = function(a
 
 exports['test chaining'] = function(assert, done) {
   let boom = Error('boom'), brax = Error('braxXXx');
   let deferred = defer();
 
   deferred.promise.then().then().then(function(actual) {
     assert.equal(actual, 2, 'value propagates unchanged');
     return actual + 2;
-  }).then(null, function(reason) {
+  }).catch(function(reason) {
     assert.fail('should not reject');
   }).then(function(actual) {
     assert.equal(actual, 4, 'value propagates through if not handled');
     throw boom;
   }).then(function(actual) {
     assert.fail('exception must reject promise');
-  }).then().then(null, function(actual) {
+  }).then().catch(function(actual) {
     assert.equal(actual, boom, 'reason propagates unchanged');
     throw brax;
-  }).then().then(null, function(actual) {
+  }).then().catch(function(actual) {
     assert.equal(actual, brax, 'reason changed becase of exception');
     return 'recovery';
   }).then(function(actual) {
     assert.equal(actual, 'recovery', 'recovered from error');
     done();
   });
 
   deferred.resolve(2);
@@ -236,17 +236,17 @@ exports['test promised error handling'] 
 exports['test errors in promise resolution handlers are propagated'] = function(assert, done) {
   var expected = Error('Boom');
   var { promise, resolve } = defer();
 
   promise.then(function() {
     throw expected;
   }).then(function() {
     return undefined;
-  }).then(null, function(actual) {
+  }).catch(function(actual) {
     assert.equal(actual, expected, 'rejected as expected');
   }).then(done, assert.fail);
 
   resolve({});
 };
 
 exports['test return promise form promised'] = function(assert, done) {
   let f = promised(function() {
@@ -440,17 +440,17 @@ function testEnvironment ({all, resolve,
   all([resolve(5), resolve(10), 925]).then(val => {
     assert.equal(val[0], 5, 'promise#all works ' + type);
     assert.equal(val[1], 10, 'promise#all works ' + type);
     assert.equal(val[2], 925, 'promise#all works ' + type);
     return resolve(1000);
   }).then(value => {
     assert.equal(value, 1000, 'promise#resolve works ' + type);
     return reject('testing reject');
-  }).then(null, reason => {
+  }).catch(reason => {
     assert.equal(reason, 'testing reject', 'promise#reject works ' + type);
     let deferred = defer();
     setTimeout(() => deferred.resolve('\\m/'), 10);
     return deferred.promise;
   }).then(value => {
     assert.equal(value, '\\m/', 'promise#defer works ' + type);
     return promised(x => x * x)(5);
   }).then(value => {
--- a/addon-sdk/source/test/test-ui-toggle-button.js
+++ b/addon-sdk/source/test/test-ui-toggle-button.js
@@ -1200,17 +1200,17 @@ exports['test button checked'] = functio
           'clicked:foo', 'changed:foo:false', 'clicked:foo', 'changed:foo:true'
         ],
         'button change events works');
 
       close(window).
         then(loader.unload).
         then(done, assert.fail);
     })
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 }
 
 exports['test button is checked on window level'] = function(assert, done) {
   let loader = Loader(module);
   let { ToggleButton } = loader.require('sdk/ui');
   let { browserWindows } = loader.require('sdk/windows');
   let tabs = loader.require('sdk/tabs');
 
@@ -1262,17 +1262,17 @@ exports['test button is checked on windo
           'window state, checked is `false`.');
 
         tab.close(()=> {
           close(window).
             then(loader.unload).
             then(done, assert.fail);
         })
       }).
-      then(null, assert.fail);
+      catch(assert.fail);
     }
   });
 
 };
 
 exports['test button click do not messing up states'] = function(assert) {
   let loader = Loader(module);
   let { ToggleButton } = loader.require('sdk/ui');
--- a/addon-sdk/source/test/test-window-utils-private-browsing.js
+++ b/addon-sdk/source/test/test-window-utils-private-browsing.js
@@ -74,17 +74,17 @@ exports.testWindowTrackerIgnoresPrivateW
 
     return close(window).then(function() {
       return makeEmptyBrowserWindow().then(function(window) {
         myNonPrivateWindow = window;
         assert.pass('opened new window');
         return close(window);
       });
     });
-  }).then(null, assert.fail);
+  }).catch(assert.fail);
 };
 
 // Test setting activeWIndow and onFocus for private windows
 exports.testSettingActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
   let browserWindow = WM.getMostRecentWindow("navigator:browser");
 
   assert.equal(windowUtils.activeBrowserWindow, browserWindow,
                "Browser window is the active browser window.");
@@ -137,17 +137,17 @@ exports.testSettingActiveWindowDoesNotIg
     }).then(_ => {
       assert.strictEqual(windowUtils.activeBrowserWindow, browserWindow,
                          "Correct active browser window when pb mode is supported [4]");
       assert.strictEqual(windowUtils.activeWindow, browserWindow,
                          "Correct active window when pb mode is supported [4]");
 
       return close(window);
     })
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 };
 
 exports.testActiveWindowDoesNotIgnorePrivateWindow = function(assert, done) {
   // make a new private window
   makeEmptyBrowserWindow({
     private: true
   }).then(function(window) {
     // PWPB case
@@ -177,17 +177,17 @@ exports.testActiveWindowDoesNotIgnorePri
                    "active window is not private");
       assert.equal(isPrivate(windowUtils.activeBrowserWindow), false,
                    "active browser window is not private");
       assert.equal(isWindowPrivate(window), false, "window is not private");
       assert.equal(isPrivate(window), false, "window is not private");
     }
 
     return close(window);
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 }
 
 exports.testWindowIteratorIgnoresPrivateWindows = function(assert, done) {
   // make a new private window
   makeEmptyBrowserWindow({
     private: true
   }).then(function(window) {
     // PWPB case
@@ -199,12 +199,12 @@ exports.testWindowIteratorIgnoresPrivate
     // Global case
     else {
       assert.equal(isWindowPrivate(window), false, "window is not private");
       assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) > -1,
                 "window is in windowIterator()");
     }
 
     return close(window);
-  }).then(done).then(null, assert.fail);
+  }).then(done).catch(assert.fail);
 };
 
 require("sdk/test").run(exports);
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -440,31 +440,31 @@ function migrateToDevEdition(urlParams) 
     let accountData = JSON.parse(text).accountData;
     updateDisplayedEmail(accountData);
     return fxAccounts.setSignedInUser(accountData);
   }).then(() => {
     return fxAccounts.promiseAccountsForceSigninURI().then(url => {
       show("remote");
       wrapper.init(url, urlParams);
     });
-  }).then(null, error => {
+  }).catch(error => {
     log("Failed to migrate FX Account: " + error);
     show("stage", "intro");
     // load the remote frame in the background
     fxAccounts.promiseAccountsSignUpURI().then(uri => {
       wrapper.init(uri, urlParams)
     }).catch(e => {
       console.log("Failed to load signup page", e);
       setErrorPage("configError");
     });
   }).then(() => {
     // Reset the pref after migration.
     Services.prefs.setBoolPref("identity.fxaccounts.migrateToDevEdition", false);
     return true;
-  }).then(null, err => {
+  }).catch(err => {
     Cu.reportError("Failed to reset the migrateToDevEdition pref: " + err);
     return false;
   });
 }
 
 // Helper function that returns the path of the default profile on disk. Will be
 // overridden in tests.
 function getDefaultProfilePath() {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1669,17 +1669,17 @@ var gBrowserInit = {
       Cu.reportError("Could not end startup crash tracking: " + ex);
     }
 
     // Delay this a minute into the idle time because there's no rush.
     requestIdleCallback(() => {
       this.gmpInstallManager = new GMPInstallManager();
       // We don't really care about the results, if someone is interested they
       // can check the log.
-      this.gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
+      this.gmpInstallManager.simpleCheckAndInstall().catch(() => {});
     }, {timeout: 1000 * 60});
 
     SessionStore.promiseInitialized.then(() => {
       // Bail out if the window has been closed in the meantime.
       if (window.closed) {
         return;
       }
 
--- a/browser/base/content/sanitizeDialog.js
+++ b/browser/base/content/sanitizeDialog.js
@@ -98,19 +98,19 @@ var gSanitizePromptDialog = {
     let docElt = document.documentElement;
     let acceptButton = docElt.getButton("accept");
     acceptButton.disabled = true;
     acceptButton.setAttribute("label",
                               this.bundleBrowser.getString("sanitizeButtonClearing"));
     docElt.getButton("cancel").disabled = true;
 
     try {
-      s.sanitize().then(null, Components.utils.reportError)
+      s.sanitize().catch(Components.utils.reportError)
                   .then(() => window.close())
-                  .then(null, Components.utils.reportError);
+                  .catch(Components.utils.reportError);
       return false;
     } catch (er) {
       Components.utils.reportError("Exception during sanitize: " + er);
       return true; // We *do* want to close immediately on error.
     }
   },
 
   /**
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -421,17 +421,17 @@ CustomizeMode.prototype = {
           this.panelUIContents.setAttribute("showoutline", "true");
         }
         delete this._enableOutlinesTimeout;
       }, 0);
 
       if (!this._wantToBeInCustomizeMode) {
         this.exit();
       }
-    })().then(null, e => {
+    })().catch(e => {
       log.error("Error entering customize mode", e);
       // We should ensure this has been called, and calling it again doesn't hurt:
       window.PanelUI.endBatchUpdate();
       this._handler.isEnteringCustomizeMode = false;
       // Exit customize mode to ensure proper clean-up when entering failed.
       this.exit();
     });
   },
@@ -591,17 +591,17 @@ CustomizeMode.prototype = {
       this._transitioning = false;
       this._handler.isExitingCustomizeMode = false;
       CustomizableUI.dispatchToolboxEvent("aftercustomization", {}, window);
       CustomizableUI.notifyEndCustomizing(window);
 
       if (this._wantToBeInCustomizeMode) {
         this.enter();
       }
-    })().then(null, e => {
+    })().catch(e => {
       log.error("Error exiting customize mode", e);
       if (!gPhotonStructure) {
         // We should ensure this has been called, and calling it again doesn't hurt:
         window.PanelUI.endBatchUpdate();
       }
       this._handler.isExitingCustomizeMode = false;
     });
   },
@@ -861,17 +861,17 @@ CustomizeMode.prototype = {
         } else if (provider == CustomizableUI.PROVIDER_SPECIAL) {
           this.visiblePalette.removeChild(paletteChild);
         }
 
         paletteChild = nextChild;
       }
       this.visiblePalette.hidden = false;
       this.window.gNavToolbox.palette = this._stowedPalette;
-    })().then(null, log.error);
+    })().catch(log.error);
   },
 
   isCustomizableItem(aNode) {
     return aNode.localName == "toolbarbutton" ||
            aNode.localName == "toolbaritem" ||
            aNode.localName == "toolbarseparator" ||
            aNode.localName == "toolbarspring" ||
            aNode.localName == "toolbarspacer";
@@ -1067,17 +1067,17 @@ CustomizeMode.prototype = {
     let target = CustomizableUI.getCustomizeTargetForArea(aArea, this.window);
     if (!target || this.areas.has(target)) {
       return null;
     }
 
     this._addDragHandlers(target);
     for (let child of target.children) {
       if (this.isCustomizableItem(child) && !this.isWrappedToolbarItem(child)) {
-        await this.deferredWrapToolbarItem(child, CustomizableUI.getPlaceForItem(child)).then(null, log.error);
+        await this.deferredWrapToolbarItem(child, CustomizableUI.getPlaceForItem(child)).catch(log.error);
       }
     }
     this.areas.add(target);
     return target;
   },
 
   _wrapToolbarItemSync(aArea) {
     let target = CustomizableUI.getCustomizeTargetForArea(aArea, this.window);
@@ -1144,17 +1144,17 @@ CustomizeMode.prototype = {
         for (let toolbarItem of target.children) {
           if (this.isWrappedToolbarItem(toolbarItem)) {
             await this.deferredUnwrapToolbarItem(toolbarItem);
           }
         }
         this._removeDragHandlers(target);
       }
       this.areas.clear();
-    })().then(null, log.error);
+    })().catch(log.error);
   },
 
   _removeExtraToolbarsIfEmpty() {
     let toolbox = this.window.gNavToolbox;
     for (let child of toolbox.children) {
       if (child.hasAttribute("customindex")) {
         let placements = CustomizableUI.getWidgetIdsInArea(child.id);
         if (!placements.length) {
@@ -1200,17 +1200,17 @@ CustomizeMode.prototype = {
       this._updateResetButton();
       this._updateUndoResetButton();
       this._updateEmptyPaletteNotice();
       this._showPanelCustomizationPlaceholders();
       this.resetting = false;
       if (!this._wantToBeInCustomizeMode) {
         this.exit();
       }
-    })().then(null, log.error);
+    })().catch(log.error);
   },
 
   undoReset() {
     this.resetting = true;
 
     return (async () => {
       this._removePanelCustomizationPlaceholders();
       await this.depopulatePalette();
@@ -1224,17 +1224,17 @@ CustomizeMode.prototype = {
       this.populatePalette();
 
       this.persistCurrentSets(true);
 
       this._updateResetButton();
       this._updateUndoResetButton();
       this._updateEmptyPaletteNotice();
       this.resetting = false;
-    })().then(null, log.error);
+    })().catch(log.error);
   },
 
   _onToolbarVisibilityChange(aEvent) {
     let toolbar = aEvent.target;
     if (aEvent.detail.visible && toolbar.getAttribute("customizable") == "true") {
       toolbar.setAttribute("customizing", "true");
     } else {
       toolbar.removeAttribute("customizing");
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -439,17 +439,17 @@ const PanelUI = {
           CustomizableUI.registerMenuPanel(this.contents, CustomizableUI.AREA_PANEL);
         } finally {
           this.endBatchUpdate();
         }
       }
       this._updateQuitTooltip();
       this.panel.hidden = false;
       this._isReady = true;
-    })().then(null, Cu.reportError);
+    })().catch(Cu.reportError);
 
     return this._readyPromise;
   },
 
   /**
    * Switch the panel to the main view if it's not already
    * in that view.
    */
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -462,17 +462,17 @@ this.DownloadsCommon = {
         aFile.launch();
       } catch (ex) {
         // If launch fails, try sending it through the system's external "file:"
         // URL handler.
         Cc["@mozilla.org/uriloader/external-protocol-service;1"]
           .getService(Ci.nsIExternalProtocolService)
           .loadUrl(NetUtil.newURI(aFile));
       }
-    }).then(null, Cu.reportError);
+    }).catch(Cu.reportError);
   },
 
   /**
    * Show a downloaded file in the system file manager.
    *
    * @param aFile
    *        a downloaded file.
    */
@@ -669,17 +669,17 @@ function DownloadsDataCtor(aPrivate) {
 DownloadsDataCtor.prototype = {
   /**
    * Starts receiving events for current downloads.
    */
   initializeDataLink() {
     if (!this._dataLinkInitialized) {
       let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
                                                           : Downloads.PUBLIC);
-      promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
+      promiseList.then(list => list.addView(this)).catch(Cu.reportError);
       this._dataLinkInitialized = true;
     }
   },
   _dataLinkInitialized: false,
 
   /**
    * Iterator for all the available Download objects. This is empty until the
    * data has been loaded using the JavaScript API for downloads.
@@ -703,17 +703,17 @@ DownloadsDataCtor.prototype = {
 
   /**
    * Asks the back-end to remove finished downloads from the list.
    */
   removeFinished() {
     let promiseList = Downloads.getList(this._isPrivate ? Downloads.PRIVATE
                                                         : Downloads.PUBLIC);
     promiseList.then(list => list.removeFinished())
-               .then(null, Cu.reportError);
+               .catch(Cu.reportError);
     let indicatorData = this._isPrivate ? PrivateDownloadsIndicatorData
                                         : DownloadsIndicatorData;
     indicatorData.attention = DownloadsCommon.ATTENTION_NONE;
   },
 
   // Integration with the asynchronous Downloads back-end
 
   onDownloadAdded(download) {
--- a/browser/components/downloads/DownloadsTaskbar.jsm
+++ b/browser/components/downloads/DownloadsTaskbar.jsm
@@ -105,17 +105,17 @@ this.DownloadsTaskbar = {
       Downloads.getSummary(Downloads.ALL).then(summary => {
         // In case the method is re-entered, we simply ignore redundant
         // invocations of the callback, instead of keeping separate state.
         if (this._summary) {
           return undefined;
         }
         this._summary = summary;
         return this._summary.addView(this);
-      }).then(null, Cu.reportError);
+      }).catch(Cu.reportError);
     }
   },
 
   /**
    * On Windows, attaches the taskbar indicator to the specified browser window.
    */
   _attachIndicator(aWindow) {
     // Activate the indicator on the specified window.
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1208,17 +1208,17 @@ BrowserGlue.prototype = {
       }
       if (newProfile) {
         // We don't want a default profile with Developer Edition settings, an
         // empty profile directory will do. The profile service of the other
         // Firefox will populate it with its own stuff.
         let newProfilePath = newProfile.rootDir.path;
         OS.File.removeDir(newProfilePath).then(() => {
           return OS.File.makeDir(newProfilePath);
-        }).then(null, e => {
+        }).catch(e => {
           Cu.reportError("Could not empty profile 'default': " + e);
         });
       }
     }
   },
 
   _onQuitRequest: function BG__onQuitRequest(aCancelQuit, aQuitType) {
     // If user has already dismissed quit request, then do nothing
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -1637,17 +1637,17 @@ PlacesToolbar.prototype = {
   },
 
   _onDrop: function PT__onDrop(aEvent) {
     PlacesControllerDragHelper.currentDropTarget = aEvent.target;
 
     let dropPoint = this._getDropPoint(aEvent);
     if (dropPoint && dropPoint.ip) {
       PlacesControllerDragHelper.onDrop(dropPoint.ip, aEvent.dataTransfer)
-                                .then(null, Components.utils.reportError);
+                                .catch(Components.utils.reportError);
       aEvent.preventDefault();
     }
 
     this._cleanupDragDetails();
     aEvent.stopPropagation();
   },
 
   _onDragExit: function PT__onDragExit(aEvent) {
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -212,40 +212,40 @@ PlacesController.prototype = {
 
   doCommand: function PC_doCommand(aCommand) {
     switch (aCommand) {
     case "cmd_undo":
       if (!PlacesUIUtils.useAsyncTransactions) {
         PlacesUtils.transactionManager.undoTransaction();
         return;
       }
-      PlacesTransactions.undo().then(null, Components.utils.reportError);
+      PlacesTransactions.undo().catch(Components.utils.reportError);
       break;
     case "cmd_redo":
       if (!PlacesUIUtils.useAsyncTransactions) {
         PlacesUtils.transactionManager.redoTransaction();
         return;
       }
-      PlacesTransactions.redo().then(null, Components.utils.reportError);
+      PlacesTransactions.redo().catch(Components.utils.reportError);
       break;
     case "cmd_cut":
     case "placesCmd_cut":
       this.cut();
       break;
     case "cmd_copy":
     case "placesCmd_copy":
       this.copy();
       break;
     case "cmd_paste":
     case "placesCmd_paste":
-      this.paste().then(null, Components.utils.reportError);
+      this.paste().catch(Components.utils.reportError);
       break;
     case "cmd_delete":
     case "placesCmd_delete":
-      this.remove("Remove Selection").then(null, Components.utils.reportError);
+      this.remove("Remove Selection").catch(Components.utils.reportError);
       break;
     case "placesCmd_deleteDataHost":
       var host;
       if (PlacesUtils.nodeIsHost(this._view.selectedNode)) {
         var queries = this._view.selectedNode.getQueries();
         host = queries[0].domain;
       } else
         host = NetUtil.newURI(this._view.selectedNode.uri).host;
@@ -281,17 +281,17 @@ PlacesController.prototype = {
       break;
     case "placesCmd_moveBookmarks":
       this.moveSelectedBookmarks();
       break;
     case "placesCmd_reload":
       this.reloadSelectedLivemark();
       break;
     case "placesCmd_sortBy:name":
-      this.sortFolderByName().then(null, Components.utils.reportError);
+      this.sortFolderByName().catch(Components.utils.reportError);
       break;
     case "placesCmd_createBookmark":
       let node = this._view.selectedNode;
       PlacesUIUtils.showBookmarkDialog({ action: "add"
                                        , type: "bookmark"
                                        , hiddenRows: [ "description"
                                                      , "keyword"
                                                      , "location"
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -358,17 +358,17 @@
       ]]></handler>
 
       <handler event="drop"><![CDATA[
         PlacesControllerDragHelper.currentDropTarget = event.target;
 
         let dropPoint = this._getDropPoint(event);
         if (dropPoint && dropPoint.ip) {
           PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer)
-                                    .then(null, Components.utils.reportError);
+                                    .catch(Components.utils.reportError);
           event.preventDefault();
         }
 
         this._cleanupDragDetails();
         event.stopPropagation();
       ]]></handler>
 
       <handler event="dragover"><![CDATA[
--- a/browser/components/places/content/moveBookmarks.js
+++ b/browser/components/places/content/moveBookmarks.js
@@ -49,17 +49,17 @@ var gMoveBookmarksDialog = {
       let newParentGuid = await PlacesUtils.promiseItemGuid(selectedFolderId);
       for (let node of this._nodes) {
         // Nothing to do if the node is already under the selected folder.
         if (node.parent.itemId == selectedFolderId)
           continue;
         await PlacesTransactions.Move({ guid: node.bookmarkGuid
                                       , newParentGuid }).transact();
       }
-    }).then(null, Components.utils.reportError);
+    }).catch(Components.utils.reportError);
   },
 
   newFolder: function MBD_newFolder() {
     // The command is disabled when the tree is not focused
     this.foldersTree.focus();
     goDoCommand("placesCmd_new:folder");
   }
 };
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -369,17 +369,17 @@ var PlacesOrganizer = {
    * Open a file-picker and import the selected file into the bookmarks store
    */
   importFromFile: function PO_importFromFile() {
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     let fpCallback = function fpCallback_done(aResult) {
       if (aResult != Ci.nsIFilePicker.returnCancel && fp.fileURL) {
         Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
         BookmarkHTMLUtils.importFromURL(fp.fileURL.spec, false)
-                         .then(null, Components.utils.reportError);
+                         .catch(Components.utils.reportError);
       }
     };
 
     fp.init(window, PlacesUIUtils.getString("SelectImport"),
             Ci.nsIFilePicker.modeOpen);
     fp.appendFilters(Ci.nsIFilePicker.filterHTML);
     fp.open(fpCallback);
   },
@@ -388,17 +388,17 @@ var PlacesOrganizer = {
    * Allows simple exporting of bookmarks.
    */
   exportBookmarks: function PO_exportBookmarks() {
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     let fpCallback = function fpCallback_done(aResult) {
       if (aResult != Ci.nsIFilePicker.returnCancel) {
         Components.utils.import("resource://gre/modules/BookmarkHTMLUtils.jsm");
         BookmarkHTMLUtils.exportToFile(fp.file.path)
-                         .then(null, Components.utils.reportError);
+                         .catch(Components.utils.reportError);
       }
     };
 
     fp.init(window, PlacesUIUtils.getString("EnterExport"),
             Ci.nsIFilePicker.modeSave);
     fp.appendFilters(Ci.nsIFilePicker.filterHTML);
     fp.defaultString = "bookmarks.html";
     fp.open(fpCallback);
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -1352,17 +1352,17 @@ PlacesTreeView.prototype = {
 
   drop: function PTV_drop(aRow, aOrientation, aDataTransfer) {
     // We are responsible for translating the |index| and |orientation|
     // parameters into a container id and index within the container,
     // since this information is specific to the tree view.
     let ip = this._getInsertionPoint(aRow, aOrientation);
     if (ip) {
       PlacesControllerDragHelper.onDrop(ip, aDataTransfer)
-                                .then(null, Components.utils.reportError);
+                                .catch(Components.utils.reportError);
     }
 
     PlacesControllerDragHelper.currentDropTarget = null;
   },
 
   getParentIndex: function PTV_getParentIndex(aRow) {
     let [, parentRow] = this._getParentByChildRow(aRow);
     return parentRow;
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_c.js
@@ -73,17 +73,17 @@ function test() {
          "LastDir should be the expected last dir");
       // gDownloadLastDir should be usable outside of private windows
       is(gDownloadLastDir.file.path, aGlobalLastDir.path,
          "gDownloadLastDir should be the expected global last dir");
 
       gDownloadLastDir.cleanupPrivateFile();
       aWin.close();
       aCallback();
-    }).then(null, function() { ok(false); });
+    }).catch(function() { ok(false); });
   }
 
   testOnWindow(false, function(win, downloadDir) {
     testDownloadDir(win, downloadDir, file1, tmpDir, dir1, dir1, function() {
       testOnWindow(true, function(win1, downloadDir1) {
         testDownloadDir(win1, downloadDir1, file2, dir1, dir1, dir2, function() {
           testOnWindow(false, function(win2, downloadDir2) {
             testDownloadDir(win2, downloadDir2, file3, dir1, dir3, dir3, finish);
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -645,17 +645,17 @@ this.UITour = {
             let onPopupShown = () => {
               searchbar.textbox.popup.removeEventListener("popupshown", onPopupShown);
               this.sendPageCallback(messageManager, data.callbackID);
             };
 
             searchbar.textbox.popup.addEventListener("popupshown", onPopupShown);
             searchbar.openSuggestionsPanel();
           }
-        }).then(null, Cu.reportError);
+        }).catch(Cu.reportError);
         break;
       }
 
       case "ping": {
         if (typeof data.callbackID == "string")
           this.sendPageCallback(messageManager, data.callbackID);
         break;
       }
--- a/browser/components/uitour/test/browser_UITour.js
+++ b/browser/components/uitour/test/browser_UITour.js
@@ -154,17 +154,17 @@ var tests = [
         gContentAPI.showHighlight("appMenu");
         waitForElementToBeVisible(highlight, function() {
           isnot(PanelUI.panel.state, "closed",
                 "Panel should remain open since UITour didn't open it in the first place");
           gContentAPI.hideMenu("appMenu");
           done();
         }, "Highlight should move to the appMenu button");
       }, "Highlight should be shown after showHighlight() for fixed panel items");
-    }).then(null, Components.utils.reportError);
+    }).catch(Components.utils.reportError);
   },
   function test_highlight_effect(done) {
     function waitForHighlightWithEffect(highlightEl, effect, next, error) {
       return waitForCondition(() => highlightEl.getAttribute("active") == effect,
                               next,
                               error);
     }
     function checkDefaultEffect() {
--- a/browser/components/uitour/test/browser_UITour2.js
+++ b/browser/components/uitour/test/browser_UITour2.js
@@ -58,17 +58,17 @@ var tests = [
                 ok(!PanelUI.panel.hasAttribute("noautohide"), "@noautohide on the menu panel should have been cleaned up on close");
                 done();
               });
               gContentAPI.hideMenu("appMenu");
             }, "Info should move to the appMenu button");
           });
         }, "Info should be shown after showInfo() for fixed menu panel items");
       });
-    }).then(null, Components.utils.reportError);
+    }).catch(Components.utils.reportError);
   },
   taskify(async function test_bookmarks_menu() {
     let bookmarksMenuButton = document.getElementById("bookmarks-menu-button");
 
     is(bookmarksMenuButton.open, false, "Menu should initially be closed");
     gContentAPI.showMenu("bookmarks");
 
     await waitForConditionPromise(() => {
--- a/browser/experiments/test/addons/experiment-racybranch/bootstrap.js
+++ b/browser/experiments/test/addons/experiment-racybranch/bootstrap.js
@@ -21,14 +21,14 @@ function realstartup() {
   let experiment = experiments._getActiveExperiment();
   if (experiment.branch) {
     Cu.reportError("Found pre-existing branch: " + experiment.branch);
     return;
   }
 
   let branch = "racy-set";
   experiments.setExperimentBranch(experiment.id, branch)
-    .then(null, Cu.reportError);
+    .catch(Cu.reportError);
 }
 
 function shutdown() { }
 function install() { }
 function uninstall() { }
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -1294,17 +1294,17 @@ var PDFViewerApplication = {
     }
     if (!this.downloadComplete) {
       downloadByUrl();
       return;
     }
     this.pdfDocument.getData().then(function getDataSuccess(data) {
       var blob = (0, _pdfjsLib.createBlob)(data, 'application/pdf');
       downloadManager.download(blob, url, filename);
-    }, downloadByUrl).then(null, downloadByUrl);
+    }, downloadByUrl).catch(downloadByUrl);
   },
   fallback: function pdfViewFallback(featureId) {
     if (this.fellback) {
       return;
     }
     this.fellback = true;
     this.externalServices.fallback({
       featureId,
--- a/browser/extensions/pocket/content/main.js
+++ b/browser/extensions/pocket/content/main.js
@@ -559,17 +559,17 @@ var pktUI = (function() {
     function isInOverflowMenu() {
         var subview = getSubview();
         return !!subview;
     }
 
     function getFirefoxAccountSignedInUser(callback) {
         fxAccounts.getSignedInUser().then(userData => {
             callback(userData);
-        }).then(null, error => {
+        }).catch(error => {
             callback();
         });
     }
 
     function getUILocale() {
         return Services.locale.getAppLocaleAsLangTag();
     }
 
--- a/browser/extensions/screenshots/webextension/background/takeshot.js
+++ b/browser/extensions/screenshots/webextension/background/takeshot.js
@@ -42,18 +42,17 @@ this.takeshot = (function() {
       shot.abTests = shotAbTests;
     }
     return catcher.watchPromise(capturePromise.then(() => {
       return browser.tabs.create({url: shot.creatingUrl})
     }).then((tab) => {
       openedTab = tab;
       return uploadShot(shot);
     }).then(() => {
-      return browser.tabs.update(openedTab.id, {url: shot.viewUrl}).then(
-        null,
+      return browser.tabs.update(openedTab.id, {url: shot.viewUrl}).catch(
         (error) => {
           // FIXME: If https://bugzilla.mozilla.org/show_bug.cgi?id=1365718 is resolved,
           // use the errorCode added as an additional check:
           if ((/invalid tab id/i).test(error)) {
             // This happens if the tab was closed before the upload completed
             return browser.tabs.create({url: shot.viewUrl});
           }
           throw error;
--- a/browser/modules/AboutHome.jsm
+++ b/browser/modules/AboutHome.jsm
@@ -182,14 +182,14 @@ var AboutHome = {
       }
 
       if (target && target.messageManager) {
         target.messageManager.sendAsyncMessage("AboutHome:Update", data);
       } else {
         let mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
         mm.broadcastAsyncMessage("AboutHome:Update", data);
       }
-    }).then(null, function onError(x) {
+    }).catch(function onError(x) {
       Cu.reportError("Error in AboutHome.sendAboutHomeData: " + x);
     });
   },
 
 };
--- a/devtools/client/canvasdebugger/panel.js
+++ b/devtools/client/canvasdebugger/panel.js
@@ -45,17 +45,17 @@ CanvasDebuggerPanel.prototype = {
         this.panelWin.gFront = new CanvasFront(this.target.client, this.target.form);
         return this.panelWin.startupCanvasDebugger();
       })
       .then(() => {
         this.isReady = true;
         this.emit("ready");
         return this;
       })
-      .then(null, function onError(aReason) {
+      .catch(function onError(aReason) {
         DevToolsUtils.reportException("CanvasDebuggerPanel.prototype.open", aReason);
       });
   },
 
   // DevToolPanel API
 
   get target() {
     return this._toolbox.target;
--- a/devtools/client/canvasdebugger/test/head.js
+++ b/devtools/client/canvasdebugger/test/head.js
@@ -121,17 +121,17 @@ function ifTestingSupported() {
 
 function ifTestingUnsupported() {
   todo(false, "Skipping test because some required functionality isn't supported.");
   finish();
 }
 
 function test() {
   let generator = isTestingSupported() ? ifTestingSupported : ifTestingUnsupported;
-  Task.spawn(generator).then(null, handleError);
+  Task.spawn(generator).catch(handleError);
 }
 
 function createCanvas() {
   return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 }
 
 function isTestingSupported() {
   if (!gRequiresWebGL) {
--- a/devtools/client/commandline/test/helpers.js
+++ b/devtools/client/commandline/test/helpers.js
@@ -129,17 +129,17 @@ var { helpers, assert } = (function () {
     options.tab = tabbrowser.addTab();
     tabbrowser.selectedTab = options.tab;
     options.browser = tabbrowser.getBrowserForTab(options.tab);
     options.target = TargetFactory.forTab(options.tab);
 
     var loaded = helpers.listenOnce(options.browser, "load", true).then(function (ev) {
       var reply = callback.call(null, options);
 
-      return Promise.resolve(reply).then(null, function (error) {
+      return Promise.resolve(reply).catch(function (error) {
         ok(false, error);
       }).then(function () {
         tabbrowser.removeTab(options.tab);
 
         delete options.target;
         delete options.browser;
         delete options.tab;
 
@@ -325,17 +325,17 @@ var { helpers, assert } = (function () {
 
       return win.DeveloperToolbar.show(true).then(function () {
         var toolbar = win.DeveloperToolbar;
         innerOptions.automator = createDeveloperToolbarAutomator(toolbar);
         innerOptions.requisition = toolbar.requisition;
 
         var reply = callback.call(null, innerOptions);
 
-        return Promise.resolve(reply).then(null, function (error) {
+        return Promise.resolve(reply).catch(function (error) {
           ok(false, error);
           console.error(error);
         }).then(function () {
           win.DeveloperToolbar.hide().then(function () {
             delete innerOptions.automator;
           });
         });
       });
--- a/devtools/client/debugger/panel.js
+++ b/devtools/client/debugger/panel.js
@@ -64,17 +64,17 @@ DebuggerPanel.prototype = {
 
           let keyShortcut = this.translateToKeyShortcut(keycode, modifiers);
           this._toolbox.useKeyWithSplitConsole(keyShortcut, handler, "jsdebugger");
         }
         this.isReady = true;
         this.emit("ready");
         return this;
       })
-      .then(null, function onError(aReason) {
+      .catch(function onError(aReason) {
         DevToolsUtils.reportException("DebuggerPanel.prototype.open", aReason);
       });
   },
 
   /**
    * Translate a VK_ keycode, with modifiers, to a key shortcut that can be used with
    * shared/key-shortcut.
    *
--- a/devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_addonactor.js
@@ -26,17 +26,17 @@ function test() {
     installAddon()
       .then(attachAddonActorForId.bind(null, gClient, ADDON3_ID))
       .then(attachAddonThread)
       .then(testDebugger)
       .then(testSources)
       .then(() => gClient.close())
       .then(uninstallAddon)
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function installAddon() {
   return addTemporaryAddon(ADDON3_PATH).then(aAddon => {
     gAddon = aAddon;
--- a/devtools/client/debugger/test/mochitest/browser_dbg_auto-pretty-print-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_auto-pretty-print-02.js
@@ -55,17 +55,17 @@ function test() {
       yield selectFirstSource();
       testFirstSourceLabel();
       testPrettyPrintButtonOn();
 
       // Disable auto pretty printing so it does not affect the following tests.
       yield disableAutoPrettyPrint();
 
       closeDebuggerAndFinish(gPanel)
-        .then(null, aError => {
+        .catch(aError => {
           ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
         });
     });
 
     function selectSecondSource() {
       let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN, 2);
       gSources.selectedIndex = 1;
       return finished;
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-01.js
@@ -19,17 +19,17 @@ function test() {
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
 
     testBlackBoxSource()
       .then(testBlackBoxReload)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testBlackBoxSource() {
   const bbButton = getBlackBoxButton(gPanel);
   ok(!bbButton.checked, "Should not be black boxed by default");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-02.js
@@ -23,17 +23,17 @@ function test() {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
 
     testBlackBoxSource()
       .then(testBlackBoxStack)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testBlackBoxSource() {
   return toggleBlackBoxing(gPanel).then(source => {
     ok(source.isBlackBoxed, "The source should be black boxed now.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-03.js
@@ -25,17 +25,17 @@ function test() {
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceAndCaretAndScopes(gPanel, ".html", 21)
       .then(testBlackBoxStack)
       .then(testBlackBoxSource)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "runTest");
   });
 }
 
 function testBlackBoxStack() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-04.js
@@ -24,17 +24,17 @@ function test() {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gSources = gDebugger.DebuggerView.Sources;
 
     blackBoxSources()
       .then(testBlackBoxStack)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function blackBoxSources() {
   let finished = waitForThreadEvents(gPanel, "blackboxchange", 3);
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-05.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-05.js
@@ -25,17 +25,17 @@ function test() {
     gDeck = gDebugger.document.getElementById("editor-deck");
 
     testSourceEditorShown();
     toggleBlackBoxing(gPanel)
       .then(testBlackBoxMessageShown)
       .then(clickStopBlackBoxingButton)
       .then(testSourceEditorShownAgain)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testSourceEditorShown() {
   is(gDeck.selectedIndex, "0",
     "The first item in the deck should be selected (the source editor).");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-06.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-06.js
@@ -22,17 +22,17 @@ function test() {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForCaretAndScopes(gPanel, 21)
       .then(testBlackBox)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "runTest");
   });
 }
 
 function testBlackBox() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-07.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_blackboxing-07.js
@@ -19,17 +19,17 @@ function test() {
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
 
     testBlackBoxSource()
       .then(testBlackBoxReload)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testBlackBoxSource() {
   const bbButton = getBlackBoxButton(gPanel);
   ok(bbButton.checked, "Should be black boxed by default");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_breadcrumbs-access.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_breadcrumbs-access.js
@@ -24,17 +24,17 @@ function test() {
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6)
       .then(checkNavigationWhileNotFocused)
       .then(focusCurrentStackFrame)
       .then(checkNavigationWhileFocused)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 
   function checkNavigationWhileNotFocused() {
     checkState({ frame: 1, source: 1, line: 6 });
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-01.js
@@ -28,17 +28,17 @@ function test() {
       .then(setupGlobals)
       .then(pauseDebuggee)
       .then(testBreakOnAll)
       .then(testBreakOnDisabled)
       .then(testBreakOnNone)
       .then(testBreakOnClick)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function setupGlobals(aThreadClient) {
   gThreadClient = aThreadClient;
   gInput = content.document.querySelector("input");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_break-on-dom-event-02.js
@@ -26,17 +26,17 @@ function test() {
 
     addTab(TAB_URL)
       .then(() => attachThreadActorForUrl(gClient, TAB_URL))
       .then(aThreadClient => gThreadClient = aThreadClient)
       .then(pauseDebuggee)
       .then(testBreakOnClick)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee() {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_chrome-debugging.js
@@ -30,17 +30,17 @@ function test() {
   gClient = new DebuggerClient(transport);
   gClient.connect().then(([aType, aTraits]) => {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     promise.all([gAttached.promise, gNewGlobal.promise, gNewChromeSource.promise])
       .then(resumeAndCloseConnection)
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     testChromeActor();
   });
 }
 
 function testChromeActor() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_clean-exit-window.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_clean-exit-window.js
@@ -17,17 +17,17 @@ function test() {
     .then(([aTab, aDebuggee, aPanel, aWindow]) => {
       gDebuggee = aDebuggee;
       gPanel = aPanel;
       gDebugger = gPanel.panelWin;
       gWindow = aWindow;
 
       return testCleanExit();
     })
-    .then(null, aError => {
+    .catch(aError => {
       ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
     });
 }
 
 function testCleanExit() {
   let deferred = promise.defer();
 
   ok(!!gWindow, "Second window created.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_closure-inspection.js
@@ -16,17 +16,17 @@ function test() {
   };
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
 
     testClosure()
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function testClosure() {
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
 
     return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_debugger-statement.js
@@ -28,17 +28,17 @@ function test() {
       .then((aTab) => {
         gTab = aTab;
         return attachTabActorForUrl(gClient, TAB_URL);
       })
       .then(testEarlyDebuggerStatement)
       .then(testDebuggerStatement)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testEarlyDebuggerStatement([aGrip, aResponse]) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_editor-contextmenu.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_editor-contextmenu.js
@@ -20,17 +20,17 @@ function test() {
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gContextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
 
-    waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest).then(null, info);
+    waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest).catch(info);
     callInTab(gTab, "firstCall");
   });
 
   function performTest() {
     is(gDebugger.gThreadClient.state, "paused",
       "Should only be getting stack frames while paused.");
     is(gSources.itemCount, 2,
       "Found the expected number of sources.");
@@ -45,17 +45,17 @@ function test() {
     ok(gContextMenu,
       "The source editor's context menupopup is available.");
     ok(gEditor.getOption("readOnly"),
       "The source editor is read only.");
 
     gEditor.focus();
     gEditor.setSelection({ line: 1, ch: 0 }, { line: 1, ch: 10 });
 
-    once(gContextMenu, "popupshown").then(testContextMenu).then(null, info);
+    once(gContextMenu, "popupshown").then(testContextMenu).catch(info);
     gContextMenu.openPopup(gEditor.container, "overlap", 0, 0, true, false);
   }
 
   function testContextMenu() {
     let document = gDebugger.document;
 
     ok(document.getElementById("editMenuCommands"),
       "#editMenuCommands found.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_editor-mode.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_editor-mode.js
@@ -25,17 +25,17 @@ function test() {
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
 
     waitForSourceAndCaretAndScopes(gPanel, "code_test-editor-mode", 1)
       .then(testInitialSource)
       .then(testSwitch1)
       .then(testSwitch2)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function testInitialSource() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-01.js
@@ -28,17 +28,17 @@ function test() {
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-02.js
@@ -29,17 +29,17 @@ function test() {
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_event-listeners-03.js
@@ -29,17 +29,17 @@ function test() {
       .then((aTab) => {
         gTab = aTab;
         return attachThreadActorForUrl(gClient, TAB_URL);
       })
       .then(pauseDebuggee)
       .then(testEventListeners)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function pauseDebuggee(aThreadClient) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_iframes.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_iframes.js
@@ -25,17 +25,17 @@ function test() {
     gIframe = gDebuggee.frames[0];
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
 
     checkIframeSource();
     checkIframePause()
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function checkIframeSource() {
     is(gDebugger.gThreadClient.paused, false,
       "Should be running after starting the test.");
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_interrupts.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_interrupts.js
@@ -29,17 +29,17 @@ function test() {
     gResumeKey = gDebugger.document.getElementById("resumeKey");
 
     gTarget.on("thread-paused", failOnPause);
     addBreakpoints()
       .then(() => { gTarget.off("thread-paused", failOnPause); })
       .then(testResumeButton)
       .then(testResumeKeyboard)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function failOnPause() {
     ok(false, "A pause was sent, but it shouldn't have been");
   }
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_jump-to-function-definition.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_jump-to-function-definition.js
@@ -21,17 +21,17 @@ function test() {
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSources = gDebugger.DebuggerView.Sources;
 
     jumpToFunctionDefinition()
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function jumpToFunctionDefinition() {
     let callLocation = {line: 5, ch: 0};
     let editor = gDebugger.DebuggerView.editor;
     let coords = editor.getCoordsFromPosition(callLocation);
--- a/devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_listaddons.js
@@ -27,17 +27,17 @@ function test() {
 
     promise.resolve(null)
       .then(testFirstAddon)
       .then(testSecondAddon)
       .then(testRemoveFirstAddon)
       .then(testRemoveSecondAddon)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstAddon() {
   let addonListChanged = false;
   gClient.addOneTimeListener("addonListChanged", () => {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_listtabs-01.js
@@ -26,17 +26,17 @@ function test() {
 
     promise.resolve(null)
       .then(testFirstTab)
       .then(testSecondTab)
       .then(testRemoveTab)
       .then(testAttachRemovedTab)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstTab() {
   return addTab(TAB1_URL).then(aTab => {
     gTab1 = aTab;
--- a/devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_multiple-windows.js
@@ -30,17 +30,17 @@ function test() {
       .then(() => addTab(TAB1_URL))
       .then(testFirstTab)
       .then(() => addWindow(TAB2_URL))
       .then(testNewWindow)
       .then(testFocusFirst)
       .then(testRemoveTab)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testFirstTab(aTab) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_navigation.js
@@ -24,17 +24,17 @@ function test() {
     is(aType, "browser",
       "Root actor should identify itself as a browser.");
 
     addTab(TAB1_URL)
       .then(() => attachTabActorForUrl(gClient, TAB1_URL))
       .then(testNavigate)
       .then(testDetach)
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testNavigate([aGrip, aResponse]) {
   let outstanding = [promise.defer(), promise.defer()];
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_no-page-sources.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_no-page-sources.js
@@ -21,17 +21,17 @@ function test() {
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     const constants = gDebugger.require("./content/constants");
 
     reloadActiveTab(gPanel);
     waitForNavigation(gPanel)
       .then(testSourcesEmptyText)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testSourcesEmptyText() {
   is(gSources.itemCount, 0,
       "Found no entries in the sources widget.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_optimized-out-vars.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_optimized-out-vars.js
@@ -39,12 +39,12 @@ function test() {
 
     let argVar = outerScope.get("arg");
     is(argVar.target.querySelector(".name").getAttribute("value"), "arg",
       "Should have the right property name for |arg|.");
     is(argVar.target.querySelector(".value").getAttribute("value"), 44,
       "Should have the right property value for |arg|.");
 
     yield resumeDebuggerThenCloseAndFinish(panel);
-  }).then(null, aError => {
+  }).catch(aError => {
     ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
   });
 }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-01.js
@@ -34,17 +34,17 @@ function test() {
 
     testPauseOnExceptionsDisabled()
       .then(enablePauseOnExceptions)
       .then(disableIgnoreCaughtExceptions)
       .then(testPauseOnExceptionsEnabled)
       .then(disablePauseOnExceptions)
       .then(enableIgnoreCaughtExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testPauseOnExceptionsDisabled() {
   let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
     info("Testing disabled pause-on-exceptions.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_pause-exceptions-02.js
@@ -36,17 +36,17 @@ function test() {
       .then(() => reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN))
       .then(() => {
         generateMouseClickInTab(gTab, "content.document.querySelector('button')");
       })
       .then(testPauseOnExceptionsAfterReload)
       .then(disablePauseOnExceptions)
       .then(enableIgnoreCaughtExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testPauseOnExceptionsAfterReload() {
   let finished = waitForCaretAndScopes(gPanel, 19).then(() => {
     info("Testing enabled pause-on-exceptions.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_paused-keybindings.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_paused-keybindings.js
@@ -39,12 +39,12 @@ function test() {
     executeSoon(function () {
       EventUtils.synthesizeKey("l", { accelKey: true });
       EventUtils.synthesizeKey("1", {});
       EventUtils.synthesizeKey("5", {});
     });
     yield caretMove;
 
     yield resumeDebuggerThenCloseAndFinish(panel);
-  }).then(null, aError => {
+  }).catch(aError => {
     ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
   });
 }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_pretty-print-11.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_pretty-print-11.js
@@ -31,17 +31,17 @@ function test() {
     finished.then(testSourceIsPretty)
       .then(() => {
         const finished = waitForCaretUpdated(gPanel, 7);
         const reloaded = reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
         return Promise.all([finished, reloaded]);
       })
       .then(testSourceIsPretty)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + DevToolsUtils.safeErrorString(aError));
       });
   });
 }
 
 function testSourceIsUgly() {
   ok(!gEditor.getText().includes("\n  "),
      "The source shouldn't be pretty printed yet.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_promises-allocation-stack.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_promises-allocation-stack.js
@@ -30,17 +30,17 @@ function test() {
     let { tabs } = yield listTabs(client);
     let targetTab = findTab(tabs, TAB_URL);
     yield attachTab(client, targetTab);
 
     yield testGetAllocationStack(client, targetTab, tab);
 
     yield close(client);
     yield closeDebuggerAndFinish(panel);
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, "Got an error: " + error.message + "\n" + error.stack);
   });
 }
 
 function* testGetAllocationStack(client, form, tab) {
   let front = PromisesFront(client, form);
 
   yield front.attach();
--- a/devtools/client/debugger/test/mochitest/browser_dbg_promises-chrome-allocation-stack.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_promises-chrome-allocation-stack.js
@@ -33,23 +33,23 @@ function test() {
     let [, tabClient] = yield attachTab(client, chrome.form);
     yield tabClient.attachThread();
 
     yield testGetAllocationStack(client, chrome.form, () => {
       let p = new Promise(() => {});
       p.name = "p";
       let q = p.then();
       q.name = "q";
-      let r = p.then(null, () => {});
+      let r = p.catch(() => {});
       r.name = "r";
     });
 
     yield close(client);
     finish();
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, "Got an error: " + error.message + "\n" + error.stack);
   });
 }
 
 function* testGetAllocationStack(client, form, makePromises) {
   let front = PromisesFront(client, form);
 
   yield front.attach();
--- a/devtools/client/debugger/test/mochitest/browser_dbg_promises-fulfillment-stack.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_promises-fulfillment-stack.js
@@ -48,17 +48,17 @@ function test() {
     let { tabs } = yield listTabs(client);
     let targetTab = findTab(tabs, TAB_URL);
     yield attachTab(client, targetTab);
 
     yield testGetFulfillmentStack(client, targetTab, tab);
 
     yield close(client);
     yield closeDebuggerAndFinish(panel);
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, "Got an error: " + error.message + "\n" + error.stack);
   });
 }
 
 function* testGetFulfillmentStack(client, form, tab) {
   let front = PromisesFront(client, form);
 
   yield front.attach();
--- a/devtools/client/debugger/test/mochitest/browser_dbg_promises-rejection-stack.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_promises-rejection-stack.js
@@ -48,17 +48,17 @@ function test() {
     let { tabs } = yield listTabs(client);
     let targetTab = findTab(tabs, TAB_URL);
     yield attachTab(client, targetTab);
 
     yield testGetRejectionStack(client, targetTab, tab);
 
     yield close(client);
     yield closeDebuggerAndFinish(panel);
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, "Got an error: " + error.message + "\n" + error.stack);
   });
 }
 
 function* testGetRejectionStack(client, form, tab) {
   let front = PromisesFront(client, form);
 
   yield front.attach();
--- a/devtools/client/debugger/test/mochitest/browser_dbg_reload-preferred-script-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_reload-preferred-script-03.js
@@ -27,17 +27,17 @@ function test() {
     gSources = gDebugger.DebuggerView.Sources;
 
     testSource(undefined, FIRST_URL);
     switchToSource(SECOND_URL)
       .then(() => testSource(SECOND_URL))
       .then(() => switchToSource(FIRST_URL))
       .then(() => testSource(FIRST_URL))
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testSource(aPreferredUrl, aSelectedUrl = aPreferredUrl) {
   info("Currently preferred source: " + gSources.preferredValue);
   info("Currently selected source: " + gSources.selectedValue);
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-02.js
@@ -30,17 +30,17 @@ function test() {
       .then(() => verifySourceAndCaret("-01.js", 1, 1, [1, 1]))
       .then(combineWithLineSearch)
       .then(() => verifySourceAndCaret("-01.js", 2, 1, [53, 53]))
       .then(combineWithTokenSearch)
       .then(() => verifySourceAndCaret("-01.js", 2, 48, [96, 100]))
       .then(combineWithTokenColonSearch)
       .then(() => verifySourceAndCaret("-01.js", 2, 11, [56, 63]))
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function performSimpleSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-basic-03.js
@@ -32,17 +32,17 @@ function test() {
       .then(performFunctionSearch)
       .then(escapeAndHide)
       .then(escapeAndClear)
       .then(() => verifySourceAndCaret("-01.js", 4, 10))
       .then(performGlobalSearch)
       .then(escapeAndClear)
       .then(() => verifySourceAndCaret("-01.js", 4, 10))
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function performFileSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-global-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-global-01.js
@@ -27,17 +27,17 @@ function test() {
     gSearchView = gDebugger.DebuggerView.GlobalSearch;
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(firstSearch)
       .then(secondSearch)
       .then(clearSearch)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function firstSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-global-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-global-03.js
@@ -26,17 +26,17 @@ function test() {
     gSources = gDebugger.DebuggerView.Sources;
     gSearchView = gDebugger.DebuggerView.GlobalSearch;
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(firstSearch)
       .then(performTest)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function firstSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-global-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-global-04.js
@@ -26,17 +26,17 @@ function test() {
     gSources = gDebugger.DebuggerView.Sources;
     gSearchView = gDebugger.DebuggerView.GlobalSearch;
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(firstSearch)
       .then(secondSearch)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function firstSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-global-05.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-global-05.js
@@ -29,17 +29,17 @@ function test() {
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(doSearch)
       .then(testExpandCollapse)
       .then(testClickLineToJump)
       .then(testClickMatchToJump)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function doSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-global-06.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-global-06.js
@@ -28,17 +28,17 @@ function test() {
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(doSearch)
       .then(testFocusLost)
       .then(doSearch)
       .then(testEscape)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function doSearch() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-popup-jank.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-popup-jank.js
@@ -70,17 +70,17 @@ function test() {
       .then(superGenericFunctionSearch)
       .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
       .then(() => ensureCaretAt(aPanel, 6))
       .then(() => pressKey("RETURN"))
       .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
       .then(() => ensureCaretAt(aPanel, 4, 10))
 
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function waitForMatchFoundAndResultsShown(aName) {
   return promise.all([
     once(gDebugger, "popupshown"),
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-01.js
@@ -33,17 +33,17 @@ function test() {
       yield secondSearch();
       yield thirdSearch();
       yield fourthSearch();
       yield fifthSearch();
       yield sixthSearch();
       yield seventhSearch();
 
       return closeDebuggerAndFinish(gPanel)
-        .then(null, aError => {
+        .catch(aError => {
           ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
         });
     });
 
     function bogusSearch() {
       let finished = promise.all([
         ensureSourceIs(gPanel, "-01.js"),
         ensureCaretAt(gPanel, 1),
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-02.js
@@ -37,17 +37,17 @@ function test() {
       .then(goDown)
       .then(goDownAndWrap)
       .then(goUpAndWrap)
       .then(goUp)
       .then(returnAndSwitch)
       .then(firstSearch)
       .then(clickAndSwitch)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function firstSearch() {
   let finished = promise.all([
     ensureSourceIs(gPanel, "-01.js"),
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-sources-03.js
@@ -28,17 +28,17 @@ function test() {
       .then(verifySourcesPane)
       .then(kindaInterpretableSearch)
       .then(verifySourcesPane)
       .then(incrediblySpecificSearch)
       .then(verifySourcesPane)
       .then(returnAndHide)
       .then(verifySourcesPane)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function waitForMatchFoundAndResultsShown() {
   return promise.all([
     once(gDebugger, "popupshown"),
--- a/devtools/client/debugger/test/mochitest/browser_dbg_search-symbols.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_search-symbols.js
@@ -35,17 +35,17 @@ function test() {
       .then(() => showSource("code_function-search-03.js"))
       .then(thirdJsSearch)
       .then(saveSearch)
       .then(filterSearch)
       .then(bogusSearch)
       .then(incrementalSearch)
       .then(emptySearch)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function htmlSearch() {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-01.js
@@ -24,17 +24,17 @@ function test() {
     gDebugger = gPanel.panelWin;
     gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
     gSearchBoxPanel = gDebugger.DebuggerView.Filtering._searchboxHelpPanel;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(showPopup)
       .then(hidePopup)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function showPopup() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_searchbox-help-popup-02.js
@@ -30,17 +30,17 @@ function test() {
       ok(false, "Damn it, this shouldn't have happened.");
     });
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
       .then(tryShowPopup)
       .then(focusEditor)
       .then(testFocusLost)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     callInTab(gTab, "firstCall");
   });
 }
 
 function tryShowPopup() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-01.js
@@ -29,17 +29,17 @@ function test() {
     checkSourceMapsEnabled();
 
     checkInitialSource();
     testSetBreakpoint()
       .then(testSetBreakpointBlankLine)
       .then(testHitBreakpoint)
       .then(testStepping)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function checkSourceMapsEnabled() {
   is(Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled"), true,
     "The source maps functionality should be enabled by default.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-02.js
@@ -28,17 +28,17 @@ function test() {
     gPrefs = gDebugger.Prefs;
     gOptions = gDebugger.DebuggerView.Options;
 
     testToggleGeneratedSource()
       .then(testSetBreakpoint)
       .then(testToggleOnPause)
       .then(testResume)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testToggleGeneratedSource() {
   let finished = waitForSourceShown(gPanel, ".js").then(() => {
     is(gPrefs.sourceMapsEnabled, false,
--- a/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-03.js
@@ -24,17 +24,17 @@ function test() {
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
 
     checkInitialSource()
     testSetBreakpoint()
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function checkInitialSource() {
   isnot(gSources.selectedItem.attachment.source.url.indexOf(".js"), -1,
     "The debugger should not show the minified js file.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_source-maps-04.js
@@ -38,17 +38,17 @@ function test() {
     enablePauseOnExceptions()
       .then(disableIgnoreCaughtExceptions)
       .then(testSetBreakpoint)
       .then(reloadPage)
       .then(testHitBreakpoint)
       .then(enableIgnoreCaughtExceptions)
       .then(disablePauseOnExceptions)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function checkInitialSource() {
   isnot(gSources.selectedItem.attachment.source.url.indexOf("code_math_bogus_map.js"), -1,
     "The debugger should show the minified js file.");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-01.js
@@ -21,17 +21,17 @@ function test() {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSources = gDebugger.DebuggerView.Sources;
 
     openContextMenu()
       .then(testCopyMenuItem)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function clickCopyURL() {
     return new Promise((resolve, reject) => {
       let copyURLMenuItem = gDebugger.document.getElementById("debugger-sources-context-copyurl");
       if (!copyURLMenuItem) {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_sources-contextmenu-02.js
@@ -23,17 +23,17 @@ function test() {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSources = gDebugger.DebuggerView.Sources;
 
     openContextMenu()
       .then(testNewTabMenuItem)
       .then(testNewTabURI)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function testNewTabURI(tabUri) {
     is(tabUri, SCRIPT_URI, "The tab contains the right script.");
     gBrowser.removeCurrentTab();
   }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_sources-keybindings.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_sources-keybindings.js
@@ -20,17 +20,17 @@ function test() {
   initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gSources = gDebugger.DebuggerView.Sources;
 
     testCopyURLShortcut()
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function testCopyURLShortcut() {
     return waitForClipboardPromise(sendCopyShortcut, SCRIPT_URI);
   }
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_stack-contextmenu-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_stack-contextmenu-02.js
@@ -21,17 +21,17 @@ function test() {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
 
     waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_REFILLED)
      .then(openContextMenu)
      .then(testCopyStackMenuItem)
      .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-     .then(null, aError => {
+     .catch(aError => {
        ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
      });
     callInTab(gTab, "simpleCall");
   });
 
   function clickCopyStack() {
     return new Promise((resolve, reject) => {
       let copyStackMenuItem = gDebugger.document.getElementById("copyStackMenuItem");
--- a/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-01.js
@@ -27,17 +27,17 @@ function test() {
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachTabActorForUrl(gClient, TAB_URL))
       .then(testTabActor)
       .then(closeTab)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_tabactor-02.js
@@ -27,17 +27,17 @@ function test() {
       "Root actor should identify itself as a browser.");
 
     addTab(TAB_URL)
       .then(() => attachTabActorForUrl(gClient, TAB_URL))
       .then(testTabActor)
       .then(closeTab)
       .then(() => gClient.close())
       .then(finish)
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function testTabActor([aGrip, aResponse]) {
   let deferred = promise.defer();
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-accessibility.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-accessibility.js
@@ -12,17 +12,17 @@ var gVariablesView;
 
 function test() {
   initDebugger().then(([aTab,, aPanel]) => {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gVariablesView = gDebugger.DebuggerView.Variables;
 
-    performTest().then(null, aError => {
+    performTest().catch(aError => {
       ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
     });
   });
 }
 
 function performTest() {
   let arr = [
     42,
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-01.js
@@ -111,17 +111,17 @@ function test() {
       }))
       .then(() => deleteWatchExpression("myVar.prop + 42"))
       .then(() => testEdit("self", "0910", {
         "myVar.prop": 910
       }))
       .then(() => deleteLastWatchExpression("myVar.prop"))
       .then(() => testWatchExpressionsRemoved())
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function addWatchExpressions() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-getset-02.js
@@ -32,17 +32,17 @@ function test() {
 
     gVars.switch = function () {};
     gVars.delete = function () {};
 
     waitForCaretAndScopes(gPanel, 24)
       .then(() => addWatchExpression())
       .then(() => testEdit("\"xlerb\"", "xlerb"))
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function addWatchExpression() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-01.js
@@ -34,17 +34,17 @@ function test() {
       .then(() => testModification("Infinity", "Infinity"))
       .then(() => testModification("NaN", "NaN"))
       .then(() => testModification("new Function", "anonymous()"))
       .then(() => testModification("+0", "0"))
       .then(() => testModification("-0", "-0"))
       .then(() => testModification("Object.keys({})", "Array[0]"))
       .then(() => testModification("document.title", '"Debugger test page"'))
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function initialChecks() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-value-02.js
@@ -29,17 +29,17 @@ function test() {
       let expanded = once(gVars, "fetched");
       obj.expand();
       return expanded;
     }).then(() => initialCheck("\u2028", "\\u2028", "8"))
       .then(() => initialCheck("\u2029", "\\u2029", "9"))
       .then(() => testModification("\u2028", "\\u2028", "123", "123"))
       .then(() => testModification("\u2029", "\\u2029", "456", "456"))
       .then(() => resumeDebuggerThenCloseAndFinish(panel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 }
 
 function getObjectScope() {
   return gVars.getScopeAtIndex(0).get("obj");
 }
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-watch.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-edit-watch.js
@@ -41,17 +41,17 @@ function test() {
       .then(() => testIntegrity4())
       .then(() => testModification("document.title", "\ \t\r\n", "\"43\"", "44"))
       .then(() => testIntegrity5())
       .then(() => testExprDeletion("this", "44"))
       .then(() => testIntegrity6())
       .then(() => testExprFinalDeletion("ermahgerd", "44"))
       .then(() => testIntegrity7())
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     addExpressions();
     callInTab(gTab, "ermahgerd");
   });
 }
 
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-01.js
@@ -32,17 +32,17 @@ function test() {
     // The first 'with' scope should be expanded by default, but the
     // variables haven't been fetched yet. This is how 'with' scopes work.
     promise.all([
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(prepareVariablesAndProperties)
       .then(testVariablesAndPropertiesFiltering)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testVariablesAndPropertiesFiltering() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-02.js
@@ -32,17 +32,17 @@ function test() {
     // The first 'with' scope should be expanded by default, but the
     // variables haven't been fetched yet. This is how 'with' scopes work.
     promise.all([
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(prepareVariablesAndProperties)
       .then(testVariablesAndPropertiesFiltering)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testVariablesAndPropertiesFiltering() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-03.js
@@ -31,17 +31,17 @@ function test() {
     // The first 'with' scope should be expanded by default, but the
     // variables haven't been fetched yet. This is how 'with' scopes work.
     promise.all([
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(prepareVariablesAndProperties)
       .then(testVariablesAndPropertiesFiltering)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testVariablesAndPropertiesFiltering() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-04.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-04.js
@@ -32,17 +32,17 @@ function test() {
     // The first 'with' scope should be expanded by default, but the
     // variables haven't been fetched yet. This is how 'with' scopes work.
     promise.all([
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(prepareVariablesAndProperties)
       .then(testVariablesAndPropertiesFiltering)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testVariablesAndPropertiesFiltering() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-05.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-filter-05.js
@@ -31,17 +31,17 @@ function test() {
     // The first 'with' scope should be expanded by default, but the
     // variables haven't been fetched yet. This is how 'with' scopes work.
     promise.all([
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(prepareVariablesAndProperties)
       .then(testVariablesAndPropertiesFiltering)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testVariablesAndPropertiesFiltering() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-01.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-01.js
@@ -26,17 +26,17 @@ function test() {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gVariables = gDebugger.DebuggerView.Variables;
 
     waitForCaretAndScopes(gPanel, 24)
       .then(initialChecks)
       .then(testExpandVariables)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function initialChecks() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-02.js
@@ -31,17 +31,17 @@ function test() {
       .then(testScopeVariables)
       .then(testArgumentsProperties)
       .then(testSimpleObject)
       .then(testComplexObject)
       .then(testArgumentObject)
       .then(testInnerArgumentObject)
       .then(testGetterSetterObject)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testScopeVariables() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-03.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-parameters-03.js
@@ -28,17 +28,17 @@ function test() {
     gVariables = gDebugger.DebuggerView.Variables;
 
     waitForCaretAndScopes(gPanel, 24)
       .then(expandGlobalScope)
       .then(testGlobalScope)
       .then(expandWindowVariable)
       .then(testWindowVariable)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function expandGlobalScope() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-with.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-frame-with.js
@@ -29,17 +29,17 @@ function test() {
       waitForCaretAndScopes(gPanel, 22),
       waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_VARIABLES)
     ]).then(testFirstWithScope)
       .then(expandSecondWithScope)
       .then(testSecondWithScope)
       .then(expandFunctionScope)
       .then(testFunctionScope)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function testFirstWithScope() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-large-array-buffer.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-large-array-buffer.js
@@ -28,17 +28,17 @@ function test() {
     gTab = aTab;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gVariables = gDebugger.DebuggerView.Variables;
 
     waitForCaretAndScopes(gPanel, 28, 1)
       .then(() => performTests())
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, error => {
+      .catch(error => {
         ok(false, "Got an error: " + error.message + "\n" + error.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 const VARS_TO_TEST = [
--- a/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-webidl.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_variables-view-webidl.js
@@ -26,17 +26,17 @@ function test() {
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gVariables = gDebugger.DebuggerView.Variables;
 
     waitForCaretAndScopes(gPanel, 24)
       .then(expandGlobalScope)
       .then(performTest)
       .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
     generateMouseClickInTab(gTab, "content.document.querySelector('button')");
   });
 }
 
 function expandGlobalScope() {
--- a/devtools/client/debugger/test/mochitest/browser_dbg_watch-expressions-02.js
+++ b/devtools/client/debugger/test/mochitest/browser_dbg_watch-expressions-02.js
@@ -28,17 +28,17 @@ function test() {
     gVariables = gDebugger.DebuggerView.Variables;
 
     gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
 
     addExpressions();
     performTest()
       .then(finishTest)
       .then(() => closeDebuggerAndFinish(gPanel))
-      .then(null, aError => {
+      .catch(aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
   });
 
   function addExpressions() {
     // https://bugzilla.mozilla.org/show_bug.cgi?id=1205353
     // BZ#1205353 - wrong result for string replace with backslash-dollar.
     gWatch.addExpression("'$$$'.replace(/\\$/, 'foo')");
--- a/devtools/client/debugger/test/mochitest/doc_promise-get-allocation-stack.html
+++ b/devtools/client/debugger/test/mochitest/doc_promise-get-allocation-stack.html
@@ -10,15 +10,15 @@
 
   <body>
     <script type="text/javascript">
       function makePromises() {
         var p = new Promise(() => {});
         p.name = "p";
         var q = p.then();
         q.name = "q";
-        var r = p.then(null, () => {});
+        var r = p.catch(() => {});
         r.name = "r";
       }
     </script>
   </body>
 
 </html>
--- a/devtools/client/debugger/test/mochitest/doc_promise.html
+++ b/devtools/client/debugger/test/mochitest/doc_promise.html
@@ -18,13 +18,13 @@
       var p = window.pending;
       var f = window.fulfilled;
       var r = window.rejected;
       debugger;
     };
 
     // Attach an error handler so that the logs don't have a warning about an
     // unhandled, rejected promise.
-    window.rejected.then(null, function () {});
+    window.rejected.catch(function () {});
     </script>
   </body>
 
 </html>
--- a/devtools/client/debugger/views/variable-bubble-view.js
+++ b/devtools/client/debugger/views/variable-bubble-view.js
@@ -151,17 +151,17 @@ VariableBubbleView.prototype = {
             objectActor: frameFinished.return
           });
         } else {
           let msg = "Evaluation has thrown for: " + identifierInfo.evalString;
           console.warn(msg);
           dumpn(msg);
         }
       })
-      .then(null, err => {
+      .catch(err => {
         let msg = "Couldn't evaluate: " + err.message;
         console.error(msg);
         dumpn(msg);
       });
   },
 
   /**
    * Shows an inspection popup for a specified object actor grip.
--- a/devtools/client/devtools-startup.js
+++ b/devtools/client/devtools-startup.js
@@ -71,17 +71,17 @@ DevToolsStartup.prototype = {
   handleConsoleFlag: function (cmdLine) {
     let window = Services.wm.getMostRecentWindow("devtools:webconsole");
     if (!window) {
       this.initDevTools();
 
       let { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
       let hudservice = require("devtools/client/webconsole/hudservice");
       let { console } = Cu.import("resource://gre/modules/Console.jsm", {});
-      hudservice.toggleBrowserConsole().then(null, console.error);
+      hudservice.toggleBrowserConsole().catch(console.error);
     } else {
       // the Browser Console was already open
       window.focus();
     }
 
     if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO) {
       cmdLine.preventDefault = true;
     }
--- a/devtools/client/framework/test/browser_toolbox_custom_host.js
+++ b/devtools/client/framework/test/browser_toolbox_custom_host.js
@@ -15,17 +15,17 @@ function test() {
   iframe = document.createElement("iframe");
   document.documentElement.appendChild(iframe);
 
   addTab(TEST_URL).then(function (tab) {
     target = TargetFactory.forTab(tab);
     let options = {customIframe: iframe};
     gDevTools.showToolbox(target, null, Toolbox.HostType.CUSTOM, options)
              .then(testCustomHost, console.error)
-             .then(null, console.error);
+             .catch(console.error);
   });
 
   function onMessage(event) {
     if (typeof(event.data) !== "string") {
       return;
     }
     info("onMessage: " + event.data);
     let json = JSON.parse(event.data);
--- a/devtools/client/framework/test/browser_toolbox_raise.js
+++ b/devtools/client/framework/test/browser_toolbox_raise.js
@@ -10,32 +10,32 @@ var {Toolbox} = require("devtools/client
 var toolbox, tab1, tab2;
 
 function test() {
   addTab(TEST_URL).then(tab => {
     tab2 = BrowserTestUtils.addTab(gBrowser);
     let target = TargetFactory.forTab(tab);
     gDevTools.showToolbox(target)
              .then(testBottomHost, console.error)
-             .then(null, console.error);
+             .catch(console.error);
   });
 }
 
 function testBottomHost(aToolbox) {
   toolbox = aToolbox;
 
   // switch to another tab and test toolbox.raise()
   gBrowser.selectedTab = tab2;
   executeSoon(function () {
     is(gBrowser.selectedTab, tab2, "Correct tab is selected before calling raise");
     toolbox.raise();
     executeSoon(function () {
       is(gBrowser.selectedTab, tab1, "Correct tab was selected after calling raise");
 
-      toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost).then(null, console.error);
+      toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost).catch(console.error);
     });
   });
 }
 
 function testWindowHost() {
   // Make sure toolbox is not focused.
   window.addEventListener("focus", onFocus, true);
 
--- a/devtools/client/framework/test/browser_toolbox_sidebar.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar.js
@@ -84,17 +84,17 @@ function test() {
         allTabsReady(panel);
       });
 
       panel.sidebar.addTab("tab1", tab1URL, {selected: true});
       panel.sidebar.addTab("tab2", tab2URL);
       panel.sidebar.addTab("tab3", tab3URL);
 
       panel.sidebar.show();
-    }).then(null, console.error);
+    }).catch(console.error);
   });
 
   function allTabsReady(panel) {
     if (!tab1Selected || !readyTabs.tab1 || !readyTabs.tab2 || !readyTabs.tab3) {
       return;
     }
 
     ok(registeredTabs.tab1, "tab1 registered");
--- a/devtools/client/framework/test/browser_toolbox_sidebar_events.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar_events.js
@@ -64,17 +64,17 @@ function test() {
 
       panel.sidebar.once("hide", function (event, id) {
         collectedEvents.push(event);
       });
 
       panel.sidebar.once("tab1-selected", () => finishUp(panel));
       panel.sidebar.addTab("tab1", tab1URL, {selected: true});
       panel.sidebar.show();
-    }).then(null, console.error);
+    }).catch(console.error);
   });
 
   function finishUp(panel) {
     panel.sidebar.hide();
     panel.sidebar.destroy();
 
     let events = collectedEvents.join(":");
     is(events, "sidebar-created:show:hide:sidebar-destroyed",
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -505,17 +505,17 @@ Toolbox.prototype = {
       // so we don't have to explicitly wait for this in tests; ideally, all tests
       // will handle this on their own, but each have their own tear down function.
       if (flags.testing) {
         yield performanceFrontConnection;
       }
 
       this.emit("ready");
       this._isOpenDeferred.resolve();
-    }.bind(this)).then(null, console.error.bind(console));
+    }.bind(this)).catch(console.error.bind(console));
   },
 
   /**
    * loading React modules when needed (to avoid performance penalties
    * during Firefox start up time).
    */
   get React() {
     return this.browserRequire("devtools/client/shared/vendor/react");
@@ -2474,17 +2474,17 @@ Toolbox.prototype = {
 
           // Force GC to prevent long GC pauses when running tests and to free up
           // memory in general when the toolbox is closed.
           if (flags.testing) {
             win.QueryInterface(Ci.nsIInterfaceRequestor)
               .getInterface(Ci.nsIDOMWindowUtils)
               .garbageCollect();
           }
-        }).then(null, console.error));
+        }).catch(console.error));
 
     let leakCheckObserver = ({wrappedJSObject: barrier}) => {
       // Make the leak detector wait until this toolbox is properly destroyed.
       barrier.client.addBlocker("DevTools: Wait until toolbox is destroyed",
                                 this._destroyer);
     };
 
     let topic = "shutdown-leaks-before-check";
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -507,17 +507,17 @@ CssComputedView.prototype = {
 
             this.inspector.emit("computed-view-refreshed");
             deferred.resolve(undefined);
           }
         }
       );
       this._refreshProcess.schedule();
       return deferred.promise;
-    }).then(null, (err) => console.error(err));
+    }).catch((err) => console.error(err));
   },
 
   /**
    * Handle the shortcut events in the computed view.
    */
   _onShortcut: function (name, event) {
     if (!event.target.closest("#sidebar-panel-computedview")) {
       return;
@@ -671,17 +671,17 @@ CssComputedView.prototype = {
         CssComputedView.propertyNames.push(prop);
       }
     }
 
     CssComputedView.propertyNames.sort();
     CssComputedView.propertyNames.push.apply(CssComputedView.propertyNames,
       mozProps.sort());
 
-    this._createPropertyViews().then(null, e => {
+    this._createPropertyViews().catch(e => {
       if (!this._isDestroyed) {
         console.warn("The creation of property views was cancelled because " +
           "the computed-view was destroyed before it was done creating views");
       } else {
         console.error(e);
       }
     });
   },
@@ -1103,17 +1103,17 @@ PropertyView.prototype = {
           }
 
           this._matchedSelectorResponse = matched;
 
           return this._buildMatchedSelectors().then(() => {
             this.matchedExpander.setAttribute("open", "");
             this.tree.inspector.emit("computed-view-property-expanded");
           });
-        }).then(null, console.error);
+        }).catch(console.error);
     }
 
     this.matchedSelectorsContainer.innerHTML = "";
     this.matchedExpander.removeAttribute("open");
     this.tree.inspector.emit("computed-view-property-collapsed");
     return promise.resolve(undefined);
   },
 
--- a/devtools/client/inspector/fonts/fonts.js
+++ b/devtools/client/inspector/fonts/fonts.js
@@ -165,20 +165,20 @@ FontInspector.prototype = {
       includePreviews: true,
       previewText: this.getPreviewText(),
       previewFillStyle: getColor("body-color")
     };
 
     let fonts = [];
     if (showAllFonts) {
       fonts = yield this.pageStyle.getAllUsedFontFaces(options)
-                      .then(null, console.error);
+                      .catch(console.error);
     } else {
       fonts = yield this.pageStyle.getUsedFontFaces(node, options)
-                      .then(null, console.error);
+                      .catch(console.error);
     }
 
     if (!fonts || !fonts.length) {
       // No fonts to display. Clear the previously shown fonts.
       this.clear();
       return;
     }
 
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -2149,15 +2149,15 @@ if (window.location.protocol === "chrome
     let target = yield targetFromURL(url);
     let fakeToolbox = yield buildFakeToolbox(
       target,
       (toolbox) => attachThread(toolbox),
       { React, ReactDOM, browserRequire }
     );
     let inspectorUI = new Inspector(fakeToolbox);
     inspectorUI.init();
-  }).then(null, e => {
+  }).catch(e => {
     window.alert("Unable to start the inspector:" + e.message + "\n" + e.stack);
   });
 }
 
 exports.Inspector = Inspector;
 exports.buildFakeToolbox = buildFakeToolbox;
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -899,17 +899,17 @@ MarkupView.prototype = {
             this.navigate(this.getContainer(focusNode));
           }
         });
       }, () => {
         let isValidSibling = nextSibling && !nextSibling.isPseudoElement;
         nextSibling = isValidSibling ? nextSibling : null;
         this.walker.insertBefore(node, parent, nextSibling);
       });
-    }).then(null, console.error);
+    }).catch(console.error);
   },
 
   /**
    * If an editable item is focused, select its container.
    */
   _onFocus: function (event) {
     let parent = event.target;
     while (!parent.container) {
@@ -1167,17 +1167,17 @@ MarkupView.prototype = {
     return this._expandContainer(container).then(() => {
       let child = container.children.firstChild;
       let promises = [];
       while (child) {
         promises.push(this._expandAll(child.container));
         child = child.nextSibling;
       }
       return promise.all(promises);
-    }).then(null, console.error);
+    }).catch(console.error);
   },
 
   /**
    * Expand the entire tree beneath a node.
    *
    * @param  {DOMNode} node
    *         The node to expand, or null to start from the top.
    */
@@ -1210,17 +1210,17 @@ MarkupView.prototype = {
     if (isOuter) {
       walkerPromise = this.walker.outerHTML(node);
     } else {
       walkerPromise = this.walker.innerHTML(node);
     }
 
     return walkerPromise.then(longstr => {
       return longstr.string().then(html => {
-        longstr.release().then(null, console.error);
+        longstr.release().catch(console.error);
         return html;
       });
     });
   },
 
   /**
    * Retrieve the outerHTML for a remote node.
    *
@@ -1327,17 +1327,17 @@ MarkupView.prototype = {
     let container = this.getContainer(node);
     if (!container) {
       return promise.reject();
     }
 
     // Changing the outerHTML removes the node which outerHTML was changed.
     // Listen to this removal to reselect the right node afterwards.
     this.reselectOnRemoved(node, "outerhtml");
-    return this.walker.setOuterHTML(node, newValue).then(null, () => {
+    return this.walker.setOuterHTML(node, newValue).catch(() => {
       this.cancelReselectOnRemoved();
     });
   },
 
   /**
    * Replace the innerHTML of any node displayed in the inspector with
    * some other HTML code
    * @param  {Node} node
--- a/devtools/client/inspector/markup/views/element-editor.js
+++ b/devtools/client/inspector/markup/views/element-editor.js
@@ -606,17 +606,17 @@ ElementEditor.prototype = {
         newTagName.toLowerCase() === this.node.tagName.toLowerCase() ||
         !("editTagName" in this.markup.walker)) {
       return;
     }
 
     // Changing the tagName removes the node. Make sure the replacing node gets
     // selected afterwards.
     this.markup.reselectOnRemoved(this.node, "edittagname");
-    this.markup.walker.editTagName(this.node, newTagName).then(null, () => {
+    this.markup.walker.editTagName(this.node, newTagName).catch(() => {
       // Failed to edit the tag name, cancel the reselection.
       this.markup.cancelReselectOnRemoved();
     });
   },
 
   destroy: function () {
     for (let key in this.animationTimers) {
       clearTimeout(this.animationTimers[key]);
--- a/devtools/client/inspector/markup/views/text-editor.js
+++ b/devtools/client/inspector/markup/views/text-editor.js
@@ -39,17 +39,17 @@ function TextEditor(container, node, typ
     maxWidth: () => getAutocompleteMaxWidth(this.value, this.container.elt),
     trimOutput: false,
     done: (val, commit) => {
       if (!commit) {
         return;
       }
       this.node.getNodeValue().then(longstr => {
         longstr.string().then(oldValue => {
-          longstr.release().then(null, console.error);
+          longstr.release().catch(console.error);
 
           this.container.undo.do(() => {
             this.node.setNodeValue(val);
           }, () => {
             this.node.setNodeValue(oldValue);
           });
         });
       });
@@ -101,29 +101,29 @@ TextEditor.prototype = {
   },
 
   update: function () {
     let longstr = null;
     this.node.getNodeValue().then(ret => {
       longstr = ret;
       return longstr.string();
     }).then(str => {
-      longstr.release().then(null, console.error);
+      longstr.release().catch(console.error);
       this.value.textContent = str;
 
       let isWhitespace = !/[^\s]/.exec(str);
       this.value.classList.toggle("whitespace", isWhitespace);
 
       let chars = str.replace(/\n/g, "⏎")
                      .replace(/\t/g, "⇥")
                      .replace(/ /g, "◦");
       this.value.setAttribute("title", isWhitespace
         ? INSPECTOR_L10N.getFormatStr("markupView.whitespaceOnly", chars)
         : "");
-    }).then(null, console.error);
+    }).catch(console.error);
   },
 
   destroy: function () {},
 
   /**
    * Stub method for consistency with ElementEditor.
    */
   getInfoAtNode: function () {
--- a/devtools/client/inspector/rules/models/element-style.js
+++ b/devtools/client/inspector/rules/models/element-style.js
@@ -119,17 +119,17 @@ ElementStyle.prototype = {
       // We're done with the previous list of rules.
       for (let r of existingRules) {
         if (r && r.editor) {
           r.editor.destroy();
         }
       }
 
       return undefined;
-    }).then(null, e => {
+    }).catch(e => {
       // populate is often called after a setTimeout,
       // the connection may already be closed.
       if (this.destroyed) {
         return promise.resolve(undefined);
       }
       return promiseWarn(e);
     });
     this.populated = populated;
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -773,17 +773,17 @@ CssRuleView.prototype = {
     // engine, we will set properties on a dummy element and observe
     // how their .style attribute reflects them as computed values.
     let dummyElementPromise = promise.resolve(this.styleDocument).then(document => {
       // ::before and ::after do not have a namespaceURI
       let namespaceURI = this.element.namespaceURI ||
           document.documentElement.namespaceURI;
       this._dummyElement = document.createElementNS(namespaceURI,
                                                    this.element.tagName);
-    }).then(null, promiseWarn);
+    }).catch(promiseWarn);
 
     let elementStyle = new ElementStyle(element, this, this.store,
       this.pageStyle, this.showUserAgentStyles);
     this._elementStyle = elementStyle;
 
     this._startSelectingElement();
 
     return dummyElementPromise.then(() => {
@@ -796,17 +796,17 @@ CssRuleView.prototype = {
         if (!refresh) {
           this.element.scrollTop = 0;
         }
         this._stopSelectingElement();
         this._elementStyle.onChanged = () => {
           this._changed();
         };
       }
-    }).then(null, e => {
+    }).catch(e => {
       if (this._elementStyle === elementStyle) {
         this._stopSelectingElement();
         this._clearRules();
       }
       console.error(e);
     });
   },
 
@@ -881,17 +881,17 @@ CssRuleView.prototype = {
       this._clearRules();
       let onEditorsReady = this._createEditors();
       this.refreshPseudoClassPanel();
 
       // Notify anyone that cares that we refreshed.
       return onEditorsReady.then(() => {
         this.emit("ruleview-refreshed");
       }, e => console.error(e));
-    }).then(null, promiseWarn);
+    }).catch(promiseWarn);
   },
 
   /**
    * Show the user that the rule view has no node selected.
    */
   _showEmpty: function () {
     if (this.styleDocument.getElementById("ruleview-no-results")) {
       return;
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -326,17 +326,17 @@ HighlightersOverlay.prototype = {
     }
 
     // For some reason, the call to highlighter.hide doesn't always return a
     // promise. This causes some tests to fail when trying to install a
     // rejection handler on the result of the call. To avoid this, check
     // whether the result is truthy before installing the handler.
     let onHidden = this.highlighters[this.hoveredHighlighterShown].hide();
     if (onHidden) {
-      onHidden.then(null, e => console.error(e));
+      onHidden.catch(e => console.error(e));
     }
 
     this.hoveredHighlighterShown = null;
     this.emit("highlighter-hidden");
   },
 
   /**
    * Is the current hovered node a css transform property value in the
--- a/devtools/client/netmonitor/src/har/har-exporter.js
+++ b/devtools/client/netmonitor/src/har/har-exporter.js
@@ -153,17 +153,17 @@ const HarExporter = {
       if (options.jsonp) {
         // This callback name is also used in HAR Viewer by default.
         // http://www.softwareishard.com/har/viewer/
         let callbackName = options.jsonpCallback || "onInputData";
         jsonString = callbackName + "(" + jsonString + ");";
       }
 
       return jsonString;
-    }).then(null, function onError(err) {
+    }).catch(function onError(err) {
       console.error(err);
     });
   },
 
   /**
    * Build HAR data object. This object contains all HTTP data
    * collected by the Network panel. The process is asynchronous
    * since it can involve additional RDP communication (e.g. resolving
--- a/devtools/client/scratchpad/scratchpad.js
+++ b/devtools/client/scratchpad/scratchpad.js
@@ -690,17 +690,17 @@ var Scratchpad = {
     const tabsize = Services.prefs.getIntPref(TAB_SIZE);
 
     return this.prettyPrintWorker.performTask("pretty-print", {
       url: "(scratchpad)",
       indent: tabsize,
       source: uglyText
     }).then(data => {
       this.editor.setText(data.code);
-    }).then(null, error => {
+    }).catch(error => {
       this.writeAsErrorComment({ exception: error });
       throw error;
     });
   },
 
   /**
    * Parse the text and return an AST. If we can't parse it, write an error
    * comment and return false.
@@ -1730,17 +1730,17 @@ var Scratchpad = {
       if (state)
         this.dirty = !state.saved;
 
       this.initialized = true;
       this._triggerObservers("Ready");
       this.populateRecentFilesMenu();
       PreferenceObserver.init();
       CloseObserver.init();
-    }).then(null, (err) => console.error(err));
+    }).catch((err) => console.error(err));
     this._setupCommandListeners();
     this._updateViewMenuItems();
     this._setupPopupShowingListeners();
 
     // Change the accesskey for the help menu as it can be specific on Windows
     // some localizations of Windows (ex:french, german) use "?"
     //  for the help button in the menubar but Gnome does not.
     if (Services.appinfo.OS == "WINNT") {
--- a/devtools/client/scratchpad/test/browser_scratchpad_pprint-02.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_pprint-02.js
@@ -23,17 +23,17 @@ function runTests(sw)
   const space = " ".repeat(6);
 
   const sp = sw.Scratchpad;
   sp.setText("function main() { console.log(5); }");
   sp.prettyPrint().then(() => {
     const prettyText = sp.getText();
     ok(prettyText.includes(space));
     finish();
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, error);
   });
 }
 
 registerCleanupFunction(function () {
   Services.prefs.setIntPref("devtools.editor.tabsize", gTabsize);
   gTabsize = null;
 });
--- a/devtools/client/scratchpad/test/browser_scratchpad_pprint.js
+++ b/devtools/client/scratchpad/test/browser_scratchpad_pprint.js
@@ -17,12 +17,12 @@ function test()
 function runTests(sw)
 {
   const sp = sw.Scratchpad;
   sp.setText("function main() { console.log(5); }");
   sp.prettyPrint().then(() => {
     const prettyText = sp.getText();
     ok(prettyText.includes("\n"));
     finish();
-  }).then(null, error => {
+  }).catch(error => {
     ok(false, error);
   });
 }
--- a/devtools/client/shadereditor/panel.js
+++ b/devtools/client/shadereditor/panel.js
@@ -45,17 +45,17 @@ ShaderEditorPanel.prototype = {
         this.panelWin.gFront = new WebGLFront(this.target.client, this.target.form);
         return this.panelWin.startupShaderEditor();
       })
       .then(() => {
         this.isReady = true;
         this.emit("ready");
         return this;
       })
-      .then(null, function onError(aReason) {
+      .catch(function onError(aReason) {
         DevToolsUtils.reportException("ShaderEditorPanel.prototype.open", aReason);
       });
   },
 
   // DevToolPanel API
 
   get target() {
     return this._toolbox.target;
--- a/devtools/client/shadereditor/shadereditor.js
+++ b/devtools/client/shadereditor/shadereditor.js
@@ -308,17 +308,17 @@ var ShadersListView = Heritage.extend(Wi
         vs: vertexShaderText,
         fs: fragmentShaderText
       });
     }
 
     getShaders()
       .then(getSources)
       .then(showSources)
-      .then(null, e => console.error(e));
+      .catch(e => console.error(e));
   },
 
   /**
    * The check listener for the programs container.
    */
   _onProgramCheck: function ({ detail: { checked }, target }) {
     let sourceItem = this.getItemForElement(target);
     let attachment = sourceItem.attachment;
--- a/devtools/client/shadereditor/test/head.js
+++ b/devtools/client/shadereditor/test/head.js
@@ -113,17 +113,17 @@ function ifWebGLSupported() {
 
 function ifWebGLUnsupported() {
   todo(false, "Skipping test because WebGL isn't supported.");
   finish();
 }
 
 function test() {
   let generator = isWebGLSupported(document) ? ifWebGLSupported : ifWebGLUnsupported;
-  Task.spawn(generator).then(null, handleError);
+  Task.spawn(generator).catch(handleError);
 }
 
 function createCanvas() {
   return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 }
 
 function once(aTarget, aEventName, aUseCapture = false) {
   info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
--- a/devtools/client/shared/developer-toolbar.js
+++ b/devtools/client/shared/developer-toolbar.js
@@ -1001,17 +1001,17 @@ OutputPanel.prototype._outputChanged = f
   this.remove();
 
   this.displayedOutput = ev.output;
 
   if (this.displayedOutput.completed) {
     this._update();
   } else {
     this.displayedOutput.promise.then(this._update, this._update)
-                                .then(null, console.error);
+                                .catch(console.error);
   }
 };
 
 /**
  * Called when displayed Output says it's changed or from outputChanged, which
  * happens when there is a new displayed Output.
  */
 OutputPanel.prototype._update = function () {
--- a/devtools/client/shared/redux/middleware/task.js
+++ b/devtools/client/shared/redux/middleware/task.js
@@ -14,17 +14,17 @@ const ERROR_TYPE = exports.ERROR_TYPE = 
  * asynchronously) and yield on each. If called with a promise, calls `dispatch`
  * on the results.
  */
 
 function task({ dispatch, getState }) {
   return next => action => {
     if (isGenerator(action)) {
       return Task.spawn(action.bind(null, dispatch, getState))
-        .then(null, handleError.bind(null, dispatch));
+        .catch(handleError.bind(null, dispatch));
     }
 
     /*
     if (isPromise(action)) {
       return action.then(dispatch, handleError.bind(null, dispatch));
     }
     */
 
--- a/devtools/client/sourceeditor/autocomplete.js
+++ b/devtools/client/sourceeditor/autocomplete.js
@@ -232,17 +232,17 @@ function autoComplete({ ed, cm }) {
     popup.setItems(suggestions);
 
     popup.once("popup-opened", () => {
       // This event is used in tests.
       ed.emit("after-suggest");
     });
     popup.openPopup(cursorElement, -1 * left, 0);
     autocompleteOpts.suggestionInsertedOnce = false;
-  }).then(null, e => console.error(e));
+  }).catch(e => console.error(e));
 }
 
 /**
  * Inserts a popup item into the current cursor location
  * in the editor.
  */
 function insertPopupItem(ed, popupItem) {
   let {preLabel, text} = popupItem;
--- a/devtools/client/styleeditor/StyleEditorUI.jsm
+++ b/devtools/client/styleeditor/StyleEditorUI.jsm
@@ -229,17 +229,17 @@ StyleEditorUI.prototype = {
    * @param {string} event
    *        Event name
    * @param {StyleSheet} styleSheet
    *        StyleSheet object for new sheet
    */
   _onNewDocument: function () {
     this._debuggee.getStyleSheets().then((styleSheets) => {
       return this._resetStyleSheetList(styleSheets);
-    }).then(null, e => console.error(e));
+    }).catch(e => console.error(e));
   },
 
   /**
    * Add editors for all the given stylesheets to the UI.
    *
    * @param  {array} styleSheets
    *         Array of StyleSheetFront
    */
@@ -629,17 +629,17 @@ StyleEditorUI.prototype = {
             let lineCount = editorText.split("\n").length;
             let ruleCount = showEditor.styleSheet.ruleCount;
             if (lineCount >= ruleCount) {
               showEditor.addUnusedRegions(reports);
             } else {
               this.emit("error", { key: "error-compressed", level: "info" });
             }
           }
-        }.bind(this)).then(null, e => console.error(e));
+        }.bind(this)).catch(e => console.error(e));
       }
     });
   },
 
   /**
    * Switch to the editor that has been marked to be selected.
    *
    * @return {Promise}
@@ -919,17 +919,17 @@ StyleEditorUI.prototype = {
         div.appendChild(link);
 
         list.appendChild(div);
       }
 
       sidebar.hidden = !showSidebar || !inSource;
 
       this.emit("media-list-changed", editor);
-    }.bind(this)).then(null, e => console.error(e));
+    }.bind(this)).catch(e => console.error(e));
   },
 
   /**
     * Called when a media condition is clicked
     * If a responsive mode link is clicked, it will launch it.
     *
     * @param {object} e
     *        Event object
--- a/devtools/client/styleeditor/StyleSheetEditor.jsm
+++ b/devtools/client/styleeditor/StyleSheetEditor.jsm
@@ -285,17 +285,17 @@ StyleSheetEditor.prototype = {
    * @return {Promise}
    *         A promise that'll resolve with the source text once the source
    *         has been loaded or reject on unexpected error.
    */
   fetchSource: function () {
     return this._getSourceTextAndPrettify().then((source) => {
       this.sourceLoaded = true;
       return source;
-    }).then(null, e => {
+    }).catch(e => {
       if (this._isDestroyed) {
         console.warn("Could not fetch the source for " +
                      this.styleSheet.href +
                      ", the editor was destroyed");
         console.error(e);
       } else {
         this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href });
         throw e;
@@ -513,17 +513,17 @@ StyleSheetEditor.prototype = {
     }
     this.focus();
   },
 
   /**
    * Toggled the disabled state of the underlying stylesheet.
    */
   toggleDisabled: function () {
-    this.styleSheet.toggleDisabled().then(null, e => console.error(e));
+    this.styleSheet.toggleDisabled().catch(e => console.error(e));
   },
 
   /**
    * Queue a throttled task to update the live style sheet.
    */
   updateStyleSheet: function () {
     if (this._updateTask) {
       // cancel previous queued task not executed within throttle delay
@@ -555,17 +555,17 @@ StyleSheetEditor.prototype = {
     this._updateTask = null;
 
     if (this.sourceEditor) {
       this._state.text = this.sourceEditor.getText();
     }
 
     this._isUpdating = true;
     this.styleSheet.update(this._state.text, this.transitionsEnabled)
-      .then(null, e => console.error(e));
+      .catch(e => console.error(e));
   },
 
   /**
    * Handle mousemove events, calling _highlightSelectorAt after a delay only
    * and reseting the delay everytime.
    */
   _onMouseMove: function (e) {
     this.highlighter.hide();
--- a/devtools/client/webaudioeditor/panel.js
+++ b/devtools/client/webaudioeditor/panel.js
@@ -39,17 +39,17 @@ WebAudioEditorPanel.prototype = {
         this.panelWin.gFront = new WebAudioFront(this.target.client, this.target.form);
         return this.panelWin.startupWebAudioEditor();
       })
       .then(() => {
         this.isReady = true;
         this.emit("ready");
         return this;
       })
-      .then(null, function onError(aReason) {
+      .catch(function onError(aReason) {
         console.error("WebAudioEditorPanel open failed. " +
                       aReason.error + ": " + aReason.message);
       });
   },
 
   // DevToolPanel API
 
   get target() {
--- a/devtools/client/webconsole/console-output.js
+++ b/devtools/client/webconsole/console-output.js
@@ -3069,17 +3069,17 @@ Widgets.ObjectRenderers.add({
     }
 
     this._text(">");
 
     // Register this widget in the owner message so that it gets destroyed when
     // the message is destroyed.
     this.message.widgets.add(this);
 
-    this.linkToInspector().then(null, e => console.error(e));
+    this.linkToInspector().catch(e => console.error(e));
   },
 
   /**
    * If the DOMNode being rendered can be highlit in the page, this function
    * will attach mouseover/out event listeners to do so, and the inspector icon
    * to open the node in the inspector.
    * @return a promise that resolves when the node has been linked to the
    * inspector, or rejects if it wasn't (either if no toolbox could be found to
@@ -3157,17 +3157,17 @@ Widgets.ObjectRenderers.add({
   /**
    * Unhighlight a previously highlit node
    * @see highlightDomNode
    * @return a promise that resolves when the highlighter has been hidden
    */
   unhighlightDomNode: function () {
     return this.linkToInspector().then(() => {
       return this.toolbox.highlighterUtils.unhighlight();
-    }).then(null, e => console.error(e));
+    }).catch(e => console.error(e));
   },
 
   /**
    * Open the DOMNode corresponding to the ObjectActor in the inspector panel
    * @return a promise that resolves when the inspector has been switched to
    * and the node has been selected, or rejects if the node cannot be selected
    * (detached from the DOM). Note that in any case, the inspector panel will
    * be switched to.
--- a/devtools/client/webconsole/test/browser_console_optimized_out_vars.js
+++ b/devtools/client/webconsole/test/browser_console_optimized_out_vars.js
@@ -45,17 +45,17 @@ function test() {
       webconsole: hud,
       messages: [{
         text: "optimized out",
         category: CATEGORY_OUTPUT,
       }]
     });
 
     finishTest();
-  }).then(null, aError => {
+  }).catch(aError => {
     ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
   });
 }
 
 // Debugger helper functions stolen from devtools/client/debugger/test/head.js.
 
 function ensureThreadClientState(aPanel, aState) {
   let thread = aPanel.panelWin.gThreadClient;
--- a/devtools/client/webconsole/test/browser_webconsole_split.js
+++ b/devtools/client/webconsole/test/browser_webconsole_split.js
@@ -194,17 +194,17 @@ function test() {
   });
 
   function openPanel(toolId) {
     let deferred = promise.defer();
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     gDevTools.showToolbox(target, toolId).then(function (box) {
       toolbox = box;
       deferred.resolve();
-    }).then(null, console.error);
+    }).catch(console.error);
     return deferred.promise;
   }
 
   function openAndCheckPanel(toolId) {
     return openPanel(toolId).then(() => {
       info("Checking toolbox for " + toolId);
       return checkToolboxUI(toolbox.getCurrentPanel());
     });
--- a/devtools/client/webide/content/webide.js
+++ b/devtools/client/webide/content/webide.js
@@ -913,17 +913,17 @@ var Cmds = {
     });
     return UI.busyUntil(disconnecting, "disconnecting from runtime");
   },
 
   takeScreenshot: function () {
     let url = AppManager.deviceFront.screenshotToDataURL();
     return UI.busyUntil(url.then(longstr => {
       return longstr.string().then(dataURL => {
-        longstr.release().then(null, console.error);
+        longstr.release().catch(console.error);
         UI.openInBrowser(dataURL);
       });
     }), "taking screenshot");
   },
 
   showRuntimeDetails: function () {
     UI.selectDeckPanel("runtimedetails");
   },
--- a/devtools/client/webide/modules/app-manager.js
+++ b/devtools/client/webide/modules/app-manager.js
@@ -478,17 +478,17 @@ var AppManager = exports.AppManager = {
         this.connection.on(Connection.Events.CONNECTED, onConnectedOrDisconnected);
         this.connection.on(Connection.Events.DISCONNECTED, onConnectedOrDisconnected);
         try {
           // Reset the connection's state to defaults
           this.connection.resetOptions();
           // Only watch for errors here.  Final resolution occurs above, once
           // we've reached the CONNECTED state.
           this.selectedRuntime.connect(this.connection)
-                              .then(null, e => reject(e));
+                              .catch(e => reject(e));
         } catch (e) {
           reject(e);
         }
       }, reject);
     });
 
     // Record connection result in telemetry
     let logResult = result => {
--- a/devtools/client/webide/test/test_device_preferences.html
+++ b/devtools/client/webide/test/test_device_preferences.html
@@ -72,16 +72,16 @@
 
           searchFields(deck, "debugger");
 
           DebuggerServer.destroy();
 
           yield closeWebIDE(win);
 
           SimpleTest.finish();
-        }).then(null, e => {
+        }).catch(e => {
           ok(false, "Exception: " + e);
           SimpleTest.finish();
         });
       }
     </script>
   </body>
 </html>
--- a/devtools/client/webide/test/test_device_runtime.html
+++ b/devtools/client/webide/test/test_device_runtime.html
@@ -66,16 +66,16 @@
 
           ok(!deck.selectedPanel, "No panel selected");
 
           DebuggerServer.destroy();
 
           yield closeWebIDE(win);
 
           SimpleTest.finish();
-        }).then(null, e => {
+        }).catch(e => {
           ok(false, "Exception: " + e);
           SimpleTest.finish();
         });
       }
     </script>
   </body>
 </html>
--- a/devtools/client/webide/test/test_duplicate_import.html
+++ b/devtools/client/webide/test/test_duplicate_import.html
@@ -61,17 +61,17 @@
           is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
           is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
 
           yield closeWebIDE(win);
 
           yield removeAllProjects();
 
           SimpleTest.finish();
-        }).then(null, e => {
+        }).catch(e => {
           ok(false, "Exception: " + e);
           SimpleTest.finish();
         });
       }
     </script>
   </body>
 </html>
 
--- a/devtools/client/webide/test/test_import.html
+++ b/devtools/client/webide/test/test_import.html
@@ -67,16 +67,16 @@
           is(items[3].querySelector("span").textContent, "A name (in app directory)", "Panel text is correct");
           is(items[4].querySelector("span").textContent, "hosted manifest name property", "Panel text is correct");
 
           yield closeWebIDE(win);
 
           yield removeAllProjects();
 
           SimpleTest.finish();
-        }).then(null, e => {
+        }).catch(e => {
           ok(false, "Exception: " + e);
           SimpleTest.finish();
         });
       }
     </script>
   </body>
 </html>
--- a/devtools/server/actors/script.js
+++ b/devtools/server/actors/script.js
@@ -730,17 +730,17 @@ const ThreadActor = ActorClassWithSpec(t
                     }
 
                     packet.frame.where = {
                       source: originalLocation.originalSourceActor.form(),
                       line: originalLocation.originalLine,
                       column: originalLocation.originalColumn
                     };
                     resolve(onPacket(packet))
-          .then(null, error => {
+          .catch(error => {
             reportError(error);
             return {
               error: "unknownError",
               message: error.message + "\n" + error.stack
             };
           })
           .then(pkt => {
             this.conn.send(pkt);
@@ -1063,17 +1063,17 @@ const ThreadActor = ActorClassWithSpec(t
     let needNest = true;
     let eventLoop;
     let returnVal;
 
     p.then((resolvedVal) => {
       needNest = false;
       returnVal = resolvedVal;
     })
-    .then(null, (error) => {
+    .catch((error) => {
       reportError(error, "Error inside unsafeSynchronize:");
     })
     .then(() => {
       if (eventLoop) {
         eventLoop.resolve();
       }
     });
 
--- a/devtools/server/actors/source.js
+++ b/devtools/server/actors/source.js
@@ -154,17 +154,17 @@ let SourceActor = ActorClassWithSpec(sou
     this._encodeAndSetSourceMapURL = this._encodeAndSetSourceMapURL.bind(this);
     this._getSourceText = this._getSourceText.bind(this);
 
     this._mapSourceToAddon();
 
     if (this.threadActor.sources.isPrettyPrinted(this.url)) {
       this._init = this.prettyPrint(
         this.threadActor.sources.prettyPrintIndent(this.url)
-      ).then(null, error => {
+      ).catch(error => {
         DevToolsUtils.reportException("SourceActor", error);
       });
     } else {
       this._init = null;
     }
   },
 
   get isSourceMapped() {
@@ -472,17 +472,17 @@ let SourceActor = ActorClassWithSpec(sou
       .then(this._getSourceText)
       .then(({ content, contentType }) => {
         return {
           source: createValueGrip(content, this.threadActor.threadLifetimePool,
             this.threadActor.objectGrip),
           contentType: contentType
         };
       })
-      .then(null, error => {
+      .catch(error => {
         reportError(error, "Got an exception during SA_onSource: ");
         throw new Error("Could not load the source for " + this.url + ".\n" +
                         DevToolsUtils.safeErrorString(error));
       });
   },
 
   /**
    * Handler for the "prettyPrint" packet.
@@ -495,17 +495,17 @@ let SourceActor = ActorClassWithSpec(sou
       .then(this._encodeAndSetSourceMapURL)
       .then(() => {
         // We need to reset `_init` now because we have already done the work of
         // pretty printing, and don't want onSource to wait forever for
         // initialization to complete.
         this._init = null;
       })
       .then(this.onSource)
-      .then(null, error => {
+      .catch(error => {
         this.disablePrettyPrint();
         throw new Error(DevToolsUtils.safeErrorString(error));
       });
   },
 
   /**
    * Return a function that sends a request to the pretty print worker, waits on
    * the worker's response, and then returns the pretty printed code.
--- a/devtools/server/actors/utils/TabSources.js
+++ b/devtools/server/actors/utils/TabSources.js
@@ -454,17 +454,17 @@ TabSources.prototype = {
     }
 
     let fetching = fetch(absSourceMapURL, { loadFromCache: false })
       .then(({ content }) => {
         let map = new SourceMapConsumer(content);
         this._setSourceMapRoot(map, absSourceMapURL, sourceURL);
         return map;
       })
-      .then(null, error => {
+      .catch(error => {
         if (!DevToolsUtils.reportingDisabled) {
           DevToolsUtils.reportException("TabSources.prototype._fetchSourceMap", error);
         }
         return null;
       });
     this._sourceMapCache[absSourceMapURL] = fetching;
     return fetching;
   },
--- a/devtools/server/main.js
+++ b/devtools/server/main.js
@@ -1671,17 +1671,17 @@ DebuggerServerConnection.prototype = {
     let pendingResponse = this._actorResponses.get(from) || SyncPromise.resolve(null);
     let responsePromise = pendingResponse.then(() => {
       return responseOrPromise;
     }).then(response => {
       if (!response.from) {
         response.from = from;
       }
       this.transport.send(response);
-    }).then(null, (e) => {
+    }).catch((e) => {
       let errorPacket = this._unknownError(
         "error occurred while processing '" + type, e);
       errorPacket.from = from;
       this.transport.send(errorPacket);
     });
 
     this._actorResponses.set(from, responsePromise);
   },
--- a/devtools/server/tests/mochitest/inspector-helpers.js
+++ b/devtools/server/tests/mochitest/inspector-helpers.js
@@ -202,17 +202,17 @@ function checkAvailable(client, actorID)
     is(response.error, "unrecognizedPacketType",
        "node list actor should be contactable.");
     deferred.resolve(undefined);
   });
   return deferred.promise;
 }
 
 function promiseDone(currentPromise) {
-  currentPromise.then(null, err => {
+  currentPromise.catch(err => {
     ok(false, "Promise failed: " + err);
     if (err.stack) {
       dump(err.stack);
     }
     SimpleTest.finish();
   });
 }
 
@@ -294,17 +294,17 @@ function waitForMutation(walker, test, m
 }
 
 var _tests = [];
 function addTest(test) {
   _tests.push(test);
 }
 
 function addAsyncTest(generator) {
-  _tests.push(() => Task.spawn(generator).then(null, ok.bind(null, false)));
+  _tests.push(() => Task.spawn(generator).catch(ok.bind(null, false)));
 }
 
 function runNextTest() {
   if (_tests.length == 0) {
     SimpleTest.finish();
     return;
   }
   let fn = _tests.shift();
--- a/devtools/server/tests/unit/test_actor-registry-actor.js
+++ b/devtools/server/tests/unit/test_actor-registry-actor.js
@@ -37,17 +37,17 @@ function registerNewActor() {
     constructor: "HelloActor",
     type: { global: true }
   };
 
   gRegistryFront
     .registerActor("resource://test/hello-actor.js", options)
     .then(actorFront => (gActorFront = actorFront))
     .then(talkToNewActor)
-    .then(null, e => {
+    .catch(e => {
       DevToolsUtils.reportException("registerNewActor", e);
       do_check_true(false);
     });
 }
 
 function talkToNewActor() {
   gClient.listTabs(({ helloActor }) => {
     do_check_true(!!helloActor);
@@ -60,17 +60,17 @@ function talkToNewActor() {
     });
   });
 }
 
 function unregisterNewActor() {
   gActorFront
     .unregister()
     .then(testActorIsUnregistered)
-    .then(null, e => {
+    .catch(e => {
       DevToolsUtils.reportException("unregisterNewActor", e);
       do_check_true(false);
     });
 }
 
 function testActorIsUnregistered() {
   gClient.listTabs(({ helloActor }) => {
     do_check_true(!helloActor);
--- a/devtools/server/tests/unit/test_blackboxing-06.js
+++ b/devtools/server/tests/unit/test_blackboxing-06.js
@@ -23,17 +23,17 @@ function run_test() {
       gClient, "test-black-box",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
 
         promise.resolve(setup_code())
           .then(black_box_code)
           .then(run_code)
           .then(test_correct_location)
-          .then(null, function (error) {
+          .catch(function (error) {
             do_check_true(false, "Should not get an error, got " + error);
           })
           .then(function () {
             finishClient(gClient);
           });
       });
   });
   do_test_pending();
--- a/devtools/server/tests/unit/test_promise_state-03.js
+++ b/devtools/server/tests/unit/test_promise_state-03.js
@@ -37,17 +37,17 @@ function run_test() {
 }
 
 function evalCode(debuggee) {
   /* eslint-disable */
   Components.utils.evalInSandbox(
     "doTest();\n" +
     function doTest() {
       var resolved = Promise.reject(new Error("uh oh"));
-      resolved.then(null, () => {
+      resolved.catch(() => {
         var p = resolved;
         debugger;
       });
     },
     debuggee
   );
   /* eslint-enable */
 }
--- a/devtools/server/tests/unit/test_promises_client_getdependentpromises.js
+++ b/devtools/server/tests/unit/test_promises_client_getdependentpromises.js
@@ -18,17 +18,17 @@ add_task(function* () {
 
   ok(Promise.toString().includes("native code"), "Expect native DOM Promise.");
 
   yield testGetDependentPromises(client, chromeActors, () => {
     let p = new Promise(() => {});
     p.name = "p";
     let q = p.then();
     q.name = "q";
-    let r = p.then(null, () => {});
+    let r = p.catch(() => {});
     r.name = "r";
 
     return p;
   });
 
   let response = yield listTabs(client);
   let targetTab = findTab(response.tabs, "test-promises-dependentpromises");
   ok(targetTab, "Found our target tab.");
@@ -37,17 +37,17 @@ add_task(function* () {
   yield testGetDependentPromises(client, targetTab, () => {
     const debuggee =
       DebuggerServer.getTestGlobal("test-promises-dependentpromises");
 
     let p = new debuggee.Promise(() => {});
     p.name = "p";
     let q = p.then();
     q.name = "q";
-    let r = p.then(null, () => {});
+    let r = p.catch(() => {});
     r.name = "r";
 
     return p;
   });
 
   yield close(client);
 });
 
--- a/devtools/server/tests/unit/test_protocol_children.js
+++ b/devtools/server/tests/unit/test_protocol_children.js
@@ -592,14 +592,14 @@ function run_test() {
       do_check_eq(ret.length, 2);
       do_check_true(ret[0] === childFront);
       do_check_true(ret[1] !== childFront);
       do_check_true(ret[1] instanceof ChildFront);
     }).then(() => {
       client.close().then(() => {
         do_test_finished();
       });
-    }).then(null, err => {
+    }).catch(err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_longstring.js
+++ b/devtools/server/tests/unit/test_protocol_longstring.js
@@ -230,14 +230,14 @@ function run_test() {
     }).then(() => {
       trace.expectSend({"type": "release", "to": "<actorid>"});
       trace.expectReceive({"from": "<actorid>"});
       expectRootChildren(0);
     }).then(() => {
       client.close().then(() => {
         do_test_finished();
       });
-    }).then(null, err => {
+    }).catch(err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_protocol_simple.js
+++ b/devtools/server/tests/unit/test_protocol_simple.js
@@ -324,14 +324,14 @@ function run_test() {
         deferred.resolve();
       });
       rootClient.emitFalsyOptions();
       return deferred.promise;
     }).then(() => {
       client.close().then(() => {
         do_test_finished();
       });
-    }).then(null, err => {
+    }).catch(err => {
       do_report_unexpected_exception(err, "Failure executing test");
     });
   });
   do_test_pending();
 }
--- a/devtools/server/tests/unit/test_sourcemaps-10.js
+++ b/devtools/server/tests/unit/test_sourcemaps-10.js
@@ -20,17 +20,17 @@ function run_test() {
   gClient.connect().then(function () {
     attachTestTabAndResume(
       gClient, "test-source-map",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
         promise.resolve(define_code())
           .then(run_code)
           .then(test_frame_location)
-          .then(null, error => {
+          .catch(error => {
             dump(error + "\n");
             dump(error.stack);
             do_check_true(false);
           })
           .then(() => {
             finishClient(gClient);
           });
       });
--- a/devtools/server/tests/unit/test_sourcemaps-11.js
+++ b/devtools/server/tests/unit/test_sourcemaps-11.js
@@ -20,17 +20,17 @@ function run_test() {
   gClient.connect().then(function () {
     attachTestTabAndResume(
       gClient, "test-source-map",
       function (response, tabClient, threadClient) {
         gThreadClient = threadClient;
         promise.resolve(define_code())
           .then(run_code)
           .then(test_frames)
-          .then(null, error => {
+          .catch(error => {
             dump(error + "\n");
             dump(error.stack);
             do_check_true(false);
           })
           .then(() => {
             finishClient(gClient);
           });
       });
--- a/devtools/shared/apps/app-actor-front.js
+++ b/devtools/shared/apps/app-actor-front.js
@@ -615,17 +615,17 @@ AppActorFront.prototype = {
     // On demand, retrieve apps icons in order to be able
     // to synchronously retrieve it on `App` objects
     let promises = [];
     for (let [, app] of this._apps) {
       promises.push(app.getIcon());
     }
 
     return DevToolsUtils.settleAll(promises)
-                        .then(null, () => {});
+                        .catch(() => {});
   },
 
   _listenAppEvents: function (listener) {
     this._listeners.push(listener);
 
     if (this._listeners.length > 1) {
       return promise.resolve();
     }
--- a/devtools/shared/fronts/device.js
+++ b/devtools/shared/fronts/device.js
@@ -14,17 +14,17 @@ const DeviceFront = protocol.FrontClassW
     this.actorID = form.deviceActor;
     this.manage(this);
   },
 
   screenshotToBlob: function () {
     return this.screenshotToDataURL().then(longstr => {
       return longstr.string().then(dataURL => {
         let deferred = defer();
-        longstr.release().then(null, Cu.reportError);
+        longstr.release().catch(Cu.reportError);
         let req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
             .createInstance(Ci.nsIXMLHttpRequest);
         req.open("GET", dataURL, true);
         req.responseType = "blob";
         req.onload = () => {
           deferred.resolve(req.response);
         };
         req.onerror = () => {
--- a/devtools/shared/gcli/templater.js
+++ b/devtools/shared/gcli/templater.js
@@ -169,17 +169,17 @@ function processNode(state, node, data) 
             if (value.indexOf("${") === 0 &&
                 value.charAt(value.length - 1) === "}") {
               replacement = envEval(state, value.slice(2, -1), data, value);
               if (replacement && typeof replacement.then === "function") {
                 node.setAttribute(name, "");
                 /* jshint loopfunc:true */
                 replacement.then(function (newValue) {
                   node.setAttribute(name, newValue);
-                }).then(null, console.error);
+                }).catch(console.error);
               } else {
                 if (state.options.blankNullUndefined && replacement == null) {
                   replacement = "";
                 }
                 node.setAttribute(name, replacement);
               }
             } else {
               node.setAttribute(name, processString(state, value, data));
@@ -448,17 +448,17 @@ function handleAsync(thing, siblingNode,
     // Placeholder element to be replaced once we have the real data
     let tempNode = siblingNode.ownerDocument.createElement("span");
     siblingNode.parentNode.insertBefore(tempNode, siblingNode);
     thing.then(function (delayed) {
       inserter(delayed, tempNode);
       if (tempNode.parentNode != null) {
         tempNode.remove();
       }
-    }).then(null, function (error) {
+    }).catch(function (error) {
       console.error(error.stack);
     });
   } else {
     inserter(thing, siblingNode);
   }
 }
 
 /**
--- a/devtools/shared/protocol.js
+++ b/devtools/shared/protocol.js
@@ -1107,17 +1107,17 @@ var generateRequestHandlers = function (
 
           conn.send(response);
         };
 
         this._queueResponse(p => {
           return p
             .then(() => ret)
             .then(sendReturn)
-            .then(null, this.writeError.bind(this));
+            .catch(this.writeError.bind(this));
         });
       } catch (e) {
         this._queueResponse(p => {
           return p.then(() => this.writeError(e));
         });
       }
     };
 
@@ -1246,17 +1246,17 @@ var Front = Class({
    */
   send: function (packet) {
     if (packet.to) {
       this.conn._transport.send(packet);
     } else {
       this.actor().then(actorID => {
         packet.to = actorID;
         this.conn._transport.send(packet);
-      }).then(null, e => console.error(e));
+      }).catch(e => console.error(e));
     }
   },
 
   /**
    * Send a two-way request on the connection.
    */
   request: function (packet) {
     let deferred = defer();
--- a/devtools/shared/tests/mochitest/test_eventemitter_basic.html
+++ b/devtools/shared/tests/mochitest/test_eventemitter_basic.html
@@ -28,17 +28,17 @@
       const { Task } = require("devtools/shared/task");
 
       SimpleTest.waitForExplicitFinish();
 
       testEmitter();
       testEmitter({});
 
       Task.spawn(testPromise)
-          .then(null, ok.bind(null, false))
+          .catch(ok.bind(null, false))
           .then(SimpleTest.finish);
 
       function testEmitter(aObject) {
         let emitter;
 
         if (aObject) {
           emitter = aObject;
           EventEmitter.decorate(emitter);
--- a/devtools/shared/tests/unit/test_async-utils.js
+++ b/devtools/shared/tests/unit/test_async-utils.js
@@ -21,17 +21,17 @@ function run_test() {
   Task.spawn(function* () {
     yield test_async_args(asyncOnce);
     yield test_async_return(asyncOnce);
     yield test_async_throw(asyncOnce);
 
     yield test_async_once();
     yield test_async_invoke();
     do_test_finished();
-  }).then(null, error => {
+  }).catch(error => {
     do_throw(error);
   });
 }
 
 // Test that arguments are correctly passed through to the async function.
 function test_async_args(async) {
   let obj = {
     method: async(function* (a, b) {
@@ -61,17 +61,17 @@ function test_async_return(async) {
 // Test that the throwing from an async function rejects the promise.
 function test_async_throw(async) {
   let obj = {
     method: async(function* () {
       throw new Error("boom");
     })
   };
 
-  return obj.method().then(null, error => {
+  return obj.method().catch(error => {
     do_check_true(error instanceof Error);
     do_check_eq(error.message, "boom");
   });
 }
 
 // Test that asyncOnce only runs the async function once per instance and
 // returns the same promise for that instance.
 function test_async_once() {
@@ -144,14 +144,14 @@ function test_async_invoke() {
     do_check_eq(results[0], "foo");
     do_check_eq(results[1], "bar");
 
     // Test throwing from the function.
     function thrower() {
       throw new Error("boom");
     }
 
-    yield promiseCall(thrower).then(null, error => {
+    yield promiseCall(thrower).catch(error => {
       do_check_true(error instanceof Error);
       do_check_eq(error.message, "boom");
     });
   });
 }
--- a/devtools/shared/transport/tests/unit/test_client_server_bulk.js
+++ b/devtools/shared/transport/tests/unit/test_client_server_bulk.js
@@ -172,17 +172,17 @@ var test_bulk_request_cs = Task.async(fu
     // Send bulk data to server
     request.on("bulk-send-ready", bulkSendReadyCallback);
 
     // Set up reply handling for this type
     replyHandlers[replyType](request).then(() => {
       client.close();
       transport.close();
     });
-  }).then(null, do_throw);
+  }).catch(do_throw);
 
   DebuggerServer.on("connectionchange", (event, type) => {
     if (type === "closed") {
       serverDeferred.resolve();
     }
   });
 
   return promise.all([
@@ -214,17 +214,17 @@ var test_json_request_cs = Task.async(fu
       type: actorType
     });
 
     // Set up reply handling for this type
     replyHandlers[replyType](request).then(() => {
       client.close();
       transport.close();
     });
-  }).then(null, do_throw);
+  }).catch(do_throw);
 
   DebuggerServer.on("connectionchange", (event, type) => {
     if (type === "closed") {
       serverDeferred.resolve();
     }
   });
 
   return promise.all([
--- a/dom/crypto/test/test_WebCrypto.html
+++ b/dom/crypto/test/test_WebCrypto.html
@@ -486,19 +486,17 @@ TestArray.addTest(
     function encrypt(x, iv) {
       return crypto.subtle.encrypt(
         { name: "AES-CBC", iv: iv },
         x, tv.aes_cbc_enc.data);
     }
 
     function doEncrypt(x) {
       return encrypt(x, new Uint8Array(15))
-        .then(
-          null,
-          function () { return encrypt(new Uint8Array(17)); }
+        .catch(function () { return encrypt(new Uint8Array(17)); }
         );
     }
 
     crypto.subtle.importKey("raw", tv.aes_cbc_enc.key, "AES-CBC", false, ['encrypt'])
       .then(doEncrypt)
       .then(
         error(that),
         complete(that)
@@ -536,19 +534,17 @@ TestArray.addTest(
     function decrypt(x, iv) {
       return crypto.subtle.decrypt(
         { name: "AES-CBC", iv: iv },
         x, tv.aes_cbc_dec.data);
     }
 
     function doDecrypt(x) {
       return decrypt(x, new Uint8Array(15))
-        .then(
-          null,
-          function () { return decrypt(x, new Uint8Array(17)); }
+        .catch(function () { return decrypt(x, new Uint8Array(17)); }
         );
     }
 
     crypto.subtle.importKey("raw", tv.aes_cbc_dec.key, "AES-CBC", false, ['decrypt'])
       .then(doDecrypt)
       .then(
         error(that),
         complete(that)
@@ -586,19 +582,17 @@ TestArray.addTest(
     function encrypt(x, iv) {
       return crypto.subtle.encrypt(
         { name: "AES-CTR", counter: iv, length: 32 },
         x, tv.aes_ctr_enc.data);
     }
 
     function doEncrypt(x) {
       return encrypt(x, new Uint8Array(15))
-        .then(
-          null,
-          function () { return encrypt(x, new Uint8Array(17)); }
+        .catch(function () { return encrypt(x, new Uint8Array(17)); }
         );
     }
 
     crypto.subtle.importKey("raw", tv.aes_ctr_enc.key, "AES-CTR", false, ['encrypt'])
       .then(doEncrypt)
       .then(
         error(that),
         complete(that)
@@ -636,19 +630,17 @@ TestArray.addTest(
     function doDecrypt(x, iv) {
       return crypto.subtle.decrypt(
         { name: "AES-CTR", counter: iv, length: 32 },
         x, tv.aes_ctr_dec.data);
     }
 
     function decrypt(x) {
       return decrypt(x, new Uint8Array(15))
-        .then(
-          null,
-          function () { return decrypt(x, new Uint8Array(17)); }
+        .catch(function () { return decrypt(x, new Uint8Array(17)); }
         );
     }
 
     crypto.subtle.importKey("raw", tv.aes_ctr_dec.key, "AES-CTR", false, ['decrypt'])
       .then(doDecrypt)
       .then(
         error(that),
         complete(that)
--- a/dom/promise/tests/test_on_promise_settled.html
+++ b/dom/promise/tests/test_on_promise_settled.html
@@ -38,17 +38,17 @@ Debugger.prototype.onPromiseResolved.
 
   var promise = Promise.resolve();
   promise
     .then(function () {
       ok(wrappedPromise);
       is(wrappedPromise.unsafeDereference(), promise);
       dbg.onPromiseSettled = undefined;
     })
-    .then(null, function (e) {
+    .catch(function (e) {
       ok(false, "Got an unexpected error: " + e);
     })
     .then(SimpleTest.finish);
   </script>
 </pre>
 </body>
 </html>
 
--- a/dom/promise/tests/test_on_promise_settled_duplicates.html
+++ b/dom/promise/tests/test_on_promise_settled_duplicates.html
@@ -43,17 +43,17 @@ Bug 1084065 - Test that Debugger.prototy
     fulfill(2);
     fulfill(3);
   });
 
   promise
     .then(function () {
       dbg.onPromiseSettled = undefined;
     })
-    .then(null, function (e) {
+    .catch(function (e) {
       ok(false, "Got an unexpected error: " + e);
     })
     .then(SimpleTest.finish);
   </script>
 </pre>
 </body>
 </html>
 
--- a/dom/promise/tests/test_promise.html
+++ b/dom/promise/tests/test_promise.html
@@ -290,17 +290,17 @@ function promiseThenUndefinedResolveFunc
 }
 
 function promiseThenNullResolveFunction() {
   var promise = new Promise(function(resolve, reject) {
     reject(42);
   });
 
   try {
-    promise.then(null, function(v) {
+    promise.catch(function(v) {
       is(v, 42, "Promise rejected with 42");
       runTest();
     });
   } catch (e) {
     ok(false, "then should not throw on null resolve function");
   }
 }
 
--- a/dom/promise/tests/unit/test_monitor_uncaught.js
+++ b/dom/promise/tests/unit/test_monitor_uncaught.js
@@ -15,17 +15,17 @@ PromiseTestUtils.disableUncaughtRejectio
 add_task(function* test_globals() {
   Assert.equal(Promise.defer || undefined, undefined, "We are testing DOM Promise.");
   Assert.notEqual(PromiseDebugging, undefined, "PromiseDebugging is available.");
 });
 
 add_task(function* test_promiseID() {
   let p1 = new Promise(resolve => {});
   let p2 = new Promise(resolve => {});
-  let p3 = p2.then(null, null);
+  let p3 = p2.catch(null);
   let promise = [p1, p2, p3];
 
   let identifiers = promise.map(PromiseDebugging.getPromiseID);
   do_print("Identifiers: " + JSON.stringify(identifiers));
   let idSet = new Set(identifiers);
   Assert.equal(idSet.size, identifiers.length,
     "PromiseDebugging.getPromiseID returns a distinct id per promise");
 
@@ -97,37 +97,37 @@ add_task(function* test_observe_uncaught
       promise: Promise.resolve(0),
       name: "Promise.resolve",
     };
     yield {
       promise: Promise.resolve(resolve => resolve(0)),
       name: "Resolution callback",
     };
     yield {
-      promise: Promise.resolve(0).then(null, null),
+      promise: Promise.resolve(0).catch(null),
       name: "`then(null, null)`"
     };
     yield {
-      promise: Promise.reject(0).then(null, () => {}),
+      promise: Promise.reject(0).catch(() => {}),
       name: "Reject and catch immediately",
     };
     yield {
       promise: resolveLater(),
       name: "Resolve later",
     };
     yield {
       promise: Promise.reject("Simple rejection"),
       leftUncaught: true,
       consumed: false,
       name: "Promise.reject",
     };
 
     // Reject a promise now, consume it later.
     let p = Promise.reject("Reject now, consume later");
-    setTimeout(() => p.then(null, () => {
+    setTimeout(() => p.catch(() => {
       do_print("Consumed promise");
     }), 200);
     yield {
       promise: p,
       leftUncaught: true,
       consumed: true,
       name: "Reject now, consume later",
     };
--- a/dom/security/test/csp/file_service_worker.html
+++ b/dom/security/test/csp/file_service_worker.html
@@ -8,12 +8,12 @@
   function finish(status) {
     window.parent.postMessage({result: status}, "*");
   }
 
   navigator.serviceWorker.ready.then(finish.bind(null, 'allowed'),
                                      finish.bind(null, 'blocked'));
   navigator.serviceWorker
            .register("file_service_worker.js", {scope: "."})
-           .then(null, finish.bind(null, 'blocked'));
+           .catch(finish.bind(null, 'blocked'));
   </script>
 </body>
 </html>
--- a/dom/workers/test/promise_worker.js
+++ b/dom/workers/test/promise_worker.js
@@ -394,17 +394,17 @@ function promiseThenUndefinedResolveFunc
 }
 
 function promiseThenNullResolveFunction() {
   var promise = new Promise(function(resolve, reject) {
     reject(42);
   });
 
   try {
-    promise.then(null, function(v) {
+    promise.catch(function(v) {
       is(v, 42, "Promise rejected with 42");
       runTest();
     });
   } catch (e) {
     ok(false, "then should not throw on null resolve function");
   }
 }
 
--- a/mobile/android/chrome/content/aboutDownloads.js
+++ b/mobile/android/chrome/content/aboutDownloads.js
@@ -14,18 +14,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm");
 
 var gStrings = Services.strings.createBundle("chrome://browser/locale/aboutDownloads.properties");
 XPCOMUtils.defineLazyGetter(this, "strings",
                             () => Services.strings.createBundle("chrome://browser/locale/aboutDownloads.properties"));
 
 function deleteDownload(download) {
-  download.finalize(true).then(null, Cu.reportError);
-  OS.File.remove(download.target.path).then(null, ex => {
+  download.finalize(true).catch(Cu.reportError);
+  OS.File.remove(download.target.path).catch(ex => {
     if (!(ex instanceof OS.File.Error && ex.becauseNoSuchFile)) {
       Cu.reportError(ex);
     }
   });
 }
 
 var contextMenu = {
   _items: [],
@@ -34,41 +34,41 @@ var contextMenu = {
   init: function () {
     let element = document.getElementById("downloadmenu");
     element.addEventListener("click",
                              event => event.download = this._targetDownload,
                              true);
     this._items = [
       new ContextMenuItem("open",
                           download => download.succeeded,
-                          download => download.launch().then(null, Cu.reportError)),
+                          download => download.launch().catch(Cu.reportError)),
       new ContextMenuItem("retry",
                           download => download.error ||
                                       (download.canceled && !download.hasPartialData),
-                          download => download.start().then(null, Cu.reportError)),
+                          download => download.start().catch(Cu.reportError)),
       new ContextMenuItem("remove",
                           download => download.stopped,
                           download => {
                             Downloads.getList(Downloads.ALL)
                                      .then(list => list.remove(download))
-                                     .then(null, Cu.reportError);
+                                     .catch(Cu.reportError);
                             deleteDownload(download);
                           }),
       new ContextMenuItem("pause",
                           download => !download.stopped && download.hasPartialData,
-                          download => download.cancel().then(null, Cu.reportError)),
+                          download => download.cancel().catch(Cu.reportError)),
       new ContextMenuItem("resume",
                           download => download.canceled && download.hasPartialData,
-                          download => download.start().then(null, Cu.reportError)),
+                          download => download.start().catch(Cu.reportError)),
       new ContextMenuItem("cancel",
                           download => !download.stopped ||
                                       (download.canceled && download.hasPartialData),
                           download => {
-                            download.cancel().then(null, Cu.reportError);
-                            download.removePartialData().then(null, Cu.reportError);
+                            download.cancel().catch(Cu.reportError);
+                            download.removePartialData().catch(Cu.reportError);
                           }),
       // following menu item is a global action
       new ContextMenuItem("removeall",
                           () => downloadLists.finished.length > 0,
                           () => downloadLists.removeFinished())
     ];
   },
 
@@ -111,22 +111,22 @@ ContextMenuItem.prototype = {
 function DownloadListView(type, listElementId) {
   this.listElement = document.getElementById(listElementId);
   contextMenu.addContextMenuEventListener(this.listElement);
 
   this.items = new Map();
 
   Downloads.getList(type)
            .then(list => list.addView(this))
-           .then(null, Cu.reportError);
+           .catch(Cu.reportError);
 
   window.addEventListener("unload", event => {
     Downloads.getList(type)
              .then(list => list.removeView(this))
-             .then(null, Cu.reportError);
+             .catch(Cu.reportError);
   });
 }
 
 DownloadListView.prototype = {
   get finished() {
     let finished = [];
     for (let download of this.items.keys()) {
       if (download.stopped && (!download.hasPartialData || download.error)) {
@@ -210,17 +210,17 @@ var downloadLists = {
     let title = strings.GetStringFromName("downloadAction.deleteAll");
     let messageForm = strings.GetStringFromName("downloadMessage.deleteAll");
     let message = PluralForm.get(finished.length, messageForm).replace("#1", finished.length);
 
     if (Services.prompt.confirm(null, title, message)) {
       Downloads.getList(Downloads.ALL)
                .then(list => {
                  for (let download of finished) {
-                   list.remove(download).then(null, Cu.reportError);
+                   list.remove(download).catch(Cu.reportError);
                    deleteDownload(download);
                  }
                }, Cu.reportError);
     }
   }
 };
 
 function DownloadItem(download) {
@@ -301,17 +301,17 @@ DownloadItem.prototype = {
     element.querySelector(".icon").src = this.iconUrl;
     element.querySelector(".size").textContent = this.size;
     element.querySelector(".state").textContent = this.stateDescription;
     element.querySelector(".title").setAttribute("value", this.fileName);
   },
 
   onClick: function (event) {
     if (this.download.succeeded) {
-      this.download.launch().then(null, Cu.reportError);
+      this.download.launch().catch(Cu.reportError);
     }
   },
 
   onDownloadChanged: function () {
     this._updateFromDownload();
     this.updateElement(this.element);
   },
 
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -6831,17 +6831,17 @@ var Distribution = {
       let bytes = yield OS.File.read(aFile.path);
       let raw = new TextDecoder().decode(bytes) || "";
 
       try {
         aCallback(JSON.parse(raw));
       } catch (e) {
         Cu.reportError("Distribution: Could not parse JSON: " + e);
       }
-    }).then(null, function onError(reason) {
+    }).catch(function onError(reason) {
       if (!(reason instanceof OS.File.Error && reason.becauseNoSuchFile)) {
         Cu.reportError("Distribution: Could not read from " + aFile.leafName + " file");
       }
     });
   },
 
   // Track pending installs so we can avoid showing notifications for them.
   pendingAddonInstalls: new Set(),
--- a/mobile/android/components/AddonUpdateService.js
+++ b/mobile/android/components/AddonUpdateService.js
@@ -54,17 +54,17 @@ AddonUpdateService.prototype = {
 
     // If we already auto-upgraded and installed new versions, ignore this check
     if (gNeedsRestart)
       return;
 
     AddonManagerPrivate.backgroundUpdateCheck();
 
     let gmp = new GMPInstallManager();
-    gmp.simpleCheckAndInstall().then(null, () => {});
+    gmp.simpleCheckAndInstall().catch(() => {});
 
     let interval = 1000 * getPref("getIntPref", PREF_ADDON_UPDATE_INTERVAL, 86400);
     EventDispatcher.instance.sendRequest({
       type: "Gecko:ScheduleRun",
       action: "update-addons",
       trigger: interval,
       interval: interval,
     });
--- a/mobile/android/components/Snippets.js
+++ b/mobile/android/components/Snippets.js
@@ -135,17 +135,17 @@ function updateSnippets() {
 /**
  * Caches snippets server response text to `snippets.json` in profile directory.
  *
  * @param response responseText returned from snippets server
  */
 function cacheSnippets(response) {
   let data = gEncoder.encode(response);
   let promise = OS.File.writeAtomic(gSnippetsPath, data, { tmpPath: gSnippetsPath + ".tmp" });
-  promise.then(null, e => Cu.reportError("Error caching snippets: " + e));
+  promise.catch(e => Cu.reportError("Error caching snippets: " + e));
 }
 
 /**
  * Loads snippets from cached `snippets.json`.
  */
 function loadSnippetsFromCache() {
   let promise = OS.File.read(gSnippetsPath);
   promise.then(array => {
@@ -264,17 +264,17 @@ function writeStat(snippetId, timestamp)
         yield file.write(data);
       } finally {
         yield file.close();
       }
     } catch (ex if ex instanceof OS.File.Error && ex.becauseNoSuchFile) {
       // If the file doesn't exist yet, create it.
       yield OS.File.writeAtomic(gStatsPath, data, { tmpPath: gStatsPath + ".tmp" });
     }
-  }).then(null, e => Cu.reportError("Error writing snippets stats: " + e));
+  }).catch(e => Cu.reportError("Error writing snippets stats: " + e));
 }
 
 /**
  * Reads snippets stats data from `snippets-stats.txt` and sends the data to metrics.
  */
 function sendStats() {
   let promise = OS.File.read(gStatsPath);
   promise.then(array => sendStatsRequest(gDecoder.decode(array)), e => {
@@ -310,17 +310,17 @@ function sendStatsRequest(data) {
   _httpGetRequest(url, removeStats);
 }
 
 /**
  * Removes text file where we store snippets stats.
  */
 function removeStats() {
   let promise = OS.File.remove(gStatsPath);
-  promise.then(null, e => Cu.reportError("Error removing snippets stats: " + e));
+  promise.catch(e => Cu.reportError("Error removing snippets stats: " + e));
 }
 
 /**
  * Helper function to make HTTP GET requests.
  *
  * @param url where we send the request
  * @param callback function that is called with the xhr responseText
  */
--- a/netwerk/protocol/http/UserAgentUpdates.jsm
+++ b/netwerk/protocol/http/UserAgentUpdates.jsm
@@ -137,18 +137,18 @@ this.UserAgentUpdates = {
           let update = JSON.parse(gDecoder.decode(bytes));
           if (!update) {
             throw new Error("invalid update");
           }
           return update;
         }
       );
       // try to load next one if the previous load failed
-      return prevLoad ? prevLoad.then(null, tryNext) : tryNext();
-    }, null).then(null, (ex) => {
+      return prevLoad ? prevLoad.catch(tryNext) : tryNext();
+    }, null).catch((ex) => {
       if (AppConstants.platform !== "android") {
         // All previous (non-Android) load attempts have failed, so we bail.
         throw new Error("UserAgentUpdates: Failed to load " + FILE_UPDATES +
                          ex + "\n" + ex.stack);
       }
       // Make one last attempt to read from the Fennec APK root.
       return readChannel("resource://android/" + FILE_UPDATES);
     }).then((update) => {
--- a/netwerk/test/mochitests/test_user_agent_updates.html
+++ b/netwerk/test/mochitests/test_user_agent_updates.html
@@ -272,17 +272,17 @@ const chromeScript = SpecialPowers.loadC
               OVERRIDES.forEach(function (val) {
                 val.expected && is(overrides[val.domain], val.expected,
                   'Incorrect saved override: ' + val.override);
               });
               sendAsyncMessage("testProfileSaveDone");
             }
           );
         }
-      ).then(null,
+      ).catch(
         (reason) => {
           throw reason
         }
       );
     })();
   }
 
   function testProfileLoad(hostname) {
--- a/security/manager/ssl/tests/mochitest/mixedcontent/test_bug383369.html
+++ b/security/manager/ssl/tests/mochitest/mixedcontent/test_bug383369.html
@@ -53,17 +53,17 @@
             list.removeView(this);
             aDownload.whenSucceeded().then(() => {
               list.removeFinished();
               sendAsyncMessage("navigate", "bug383369step2.html");
             });
           },
         });
         sendAsyncMessage("navigate", "download.auto");
-      }).then(null, Cu.reportError);
+      }).catch(Cu.reportError);
     });
     script.addMessageListener("navigate", function(url) {
       window.location = url;
     });
   }
 
   function afterNavigationTest() {}
 
--- a/services/fxaccounts/FxAccounts.jsm
+++ b/services/fxaccounts/FxAccounts.jsm
@@ -1175,17 +1175,17 @@ FxAccountsInternal.prototype = {
       // were already polling for receipt of an earlier email.
       this.pollStartDate = Date.now();
       if (!currentState.whenVerifiedDeferred) {
         currentState.whenVerifiedDeferred = PromiseUtils.defer();
         // This deferred might not end up with any handlers (eg, if sync
         // is yet to start up.)  This might cause "A promise chain failed to
         // handle a rejection" messages, so add an error handler directly
         // on the promise to log the error.
-        currentState.whenVerifiedDeferred.promise.then(null, err => {
+        currentState.whenVerifiedDeferred.promise.catch(err => {
           log.info("the wait for user verification was stopped: " + err);
         });
       }
     }
 
     // We return a promise for testing only. Other callers can ignore this,
     // since verification polling continues in the background.
     return this.checkEmailStatus(sessionToken, { reason: why })
--- a/services/fxaccounts/tests/xpcshell/test_accounts.js
+++ b/services/fxaccounts/tests/xpcshell/test_accounts.js
@@ -647,18 +647,17 @@ add_test(function test_fetchAndUnwrapKey
       run_next_test();
     });
   });
 
   fxa.setSignedInUser(user).then(
     user2 => {
       return fxa.internal.fetchAndUnwrapKeys();
     }
-  ).then(
-    null,
+  ).catch(
     error => {
       log.info("setSignedInUser correctly rejected");
     }
   )
 });
 
 // Alice (User A) signs up but never verifies her email.  Then Bob (User B)
 // signs in with a verified email.  Ensure that no sign-in events are triggered
@@ -1221,67 +1220,67 @@ add_task(function* test_getOAuthTokenCac
   do_check_eq(result, "token");
 });
 
 Services.prefs.setCharPref("identity.fxaccounts.remote.oauth.uri", "https://example.com/v1");
 add_test(function test_getOAuthToken_invalid_param() {
   let fxa = new MockFxAccounts();
 
   fxa.getOAuthToken()
-    .then(null, err => {
+    .catch(err => {
        do_check_eq(err.message, "INVALID_PARAMETER");
        fxa.signOut().then(run_next_test);
     });
 });
 
 add_test(function test_getOAuthToken_invalid_scope_array() {
   let fxa = new MockFxAccounts();
 
   fxa.getOAuthToken({scope: []})
-    .then(null, err => {
+    .catch(err => {
        do_check_eq(err.message, "INVALID_PARAMETER");
        fxa.signOut().then(run_next_test);
     });
 });
 
 add_test(function test_getOAuthToken_misconfigure_oauth_uri() {
   let fxa = new MockFxAccounts();
 
   Services.prefs.deleteBranch("identity.fxaccounts.remote.oauth.uri");
 
   fxa.getOAuthToken()
-    .then(null, err => {
+    .catch(err => {
        do_check_eq(err.message, "INVALID_PARAMETER");
        // revert the pref
        Services.prefs.setCharPref("identity.fxaccounts.remote.oauth.uri", "https://example.com/v1");
        fxa.signOut().then(run_next_test);
     });
 });
 
 add_test(function test_getOAuthToken_no_account() {
   let fxa = new MockFxAccounts();
 
   fxa.internal.currentAccountState.getUserAccountData = function() {
     return Promise.resolve(null);
   };
 
   fxa.getOAuthToken({ scope: "profile" })
-    .then(null, err => {
+    .catch(err => {
        do_check_eq(err.message, "NO_ACCOUNT");
        fxa.signOut().then(run_next_test);
     });
 });
 
 add_test(function test_getOAuthToken_unverified() {
   let fxa = new MockFxAccounts();
   let alice = getTestUser("alice");
 
   fxa.setSignedInUser(alice).then(() => {
     fxa.getOAuthToken({ scope: "profile" })
-      .then(null, err => {
+      .catch(err => {
          do_check_eq(err.message, "UNVERIFIED_ACCOUNT");
          fxa.signOut().then(run_next_test);
       });
   });
 });
 
 add_test(function test_getOAuthToken_network_error() {
   let fxa = new MockFxAccounts();
@@ -1299,17 +1298,17 @@ add_test(function test_getOAuthToken_net
     return Promise.reject(new FxAccountsOAuthGrantClientError({
       error: ERROR_NETWORK,
       errno: ERRNO_NETWORK
     }));
   };
 
   fxa.setSignedInUser(alice).then(() => {
     fxa.getOAuthToken({ scope: "profile", client })
-      .then(null, err => {
+      .catch(err => {
          do_check_eq(err.message, "NETWORK_ERROR");
          do_check_eq(err.details.errno, ERRNO_NETWORK);
          run_next_test();
       });
   });
 });
 
 add_test(function test_getOAuthToken_auth_error() {
@@ -1328,17 +1327,17 @@ add_test(function test_getOAuthToken_aut
     return Promise.reject(new FxAccountsOAuthGrantClientError({
       error: ERROR_INVALID_FXA_ASSERTION,
       errno: ERRNO_INVALID_FXA_ASSERTION
     }));
   };
 
   fxa.setSignedInUser(alice).then(() => {
     fxa.getOAuthToken({ scope: "profile", client })
-      .then(null, err => {
+      .catch(err => {
          do_check_eq(err.message, "AUTH_ERROR");
          do_check_eq(err.details.errno, ERRNO_INVALID_FXA_ASSERTION);
          run_next_test();
       });
   });
 });
 
 add_test(function test_getOAuthToken_unknown_error() {
@@ -1354,17 +1353,17 @@ add_test(function test_getOAuthToken_unk
     client_id: "abc123"
   });
   client.getTokenFromAssertion = function() {
     return Promise.reject("boom");
   };
 
   fxa.setSignedInUser(alice).then(() => {
     fxa.getOAuthToken({ scope: "profile", client })
-      .then(null, err => {
+      .catch(err => {
          do_check_eq(err.message, "UNKNOWN_ERROR");
          run_next_test();
       });
   });
 });
 
 add_test(function test_getSignedInUserProfile() {
   let alice = getTestUser("alice");
--- a/services/fxaccounts/tests/xpcshell/test_oauth_grant_client.js
+++ b/services/fxaccounts/tests/xpcshell/test_oauth_grant_client.js
@@ -100,19 +100,17 @@ add_test(function parseErrorResponse() {
   let response = {
     success: true,
     status: STATUS_SUCCESS,
     body: "unexpected",
   };
 
   client._Request = new mockResponse(response);
   client.getTokenFromAssertion("assertion", "scope")
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
         do_check_eq(e.code, STATUS_SUCCESS);
         do_check_eq(e.errno, ERRNO_PARSE);
         do_check_eq(e.error, ERROR_PARSE);
         do_check_eq(e.message, "unexpected");
         run_next_test();
       }
     );
@@ -122,19 +120,17 @@ add_test(function serverErrorResponse() 
   let client = new FxAccountsOAuthGrantClient(CLIENT_OPTIONS);
   let response = {
     status: 400,
     body: "{ \"code\": 400, \"errno\": 104, \"error\": \"Bad Request\", \"message\": \"Unauthorized\", \"reason\": \"Invalid fxa assertion\" }",
   };
 
   client._Request = new mockResponse(response);
   client.getTokenFromAssertion("blah", "scope")
-    .then(
-    null,
-    function(e) {
+    .catch(function(e) {
       do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
       do_check_eq(e.code, 400);
       do_check_eq(e.errno, ERRNO_INVALID_FXA_ASSERTION);
       do_check_eq(e.error, "Bad Request");
       do_check_eq(e.message, "Unauthorized");
       run_next_test();
     }
   );
@@ -142,53 +138,47 @@ add_test(function serverErrorResponse() 
 
 add_test(function networkErrorResponse() {
   let client = new FxAccountsOAuthGrantClient({
     serverURL: "http://domain.dummy",
     client_id: "abc123"
   });
   Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true);
   client.getTokenFromAssertion("assertion", "scope")
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
         do_check_eq(e.code, null);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         run_next_test();
       }
     ).catch(() => {}).then(() =>
       Services.prefs.clearUserPref("identity.fxaccounts.skipDeviceRegistration"));
 });
 
 add_test(function unsupportedMethod() {
   let client = new FxAccountsOAuthGrantClient(CLIENT_OPTIONS);
 
   return client._createRequest("/", "PUT")
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
         do_check_eq(e.code, ERROR_CODE_METHOD_NOT_ALLOWED);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         do_check_eq(e.message, ERROR_MSG_METHOD_NOT_ALLOWED);
         run_next_test();
       }
     );
 });
 
 add_test(function onCompleteRequestError() {
   let client = new FxAccountsOAuthGrantClient(CLIENT_OPTIONS);
   client._Request = new mockResponseError(new Error("onComplete error"));
   client.getTokenFromAssertion("assertion", "scope")
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
         do_check_eq(e.code, null);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         do_check_eq(e.message, "Error: onComplete error");
         run_next_test();
       }
   );
@@ -198,19 +188,17 @@ add_test(function incorrectErrno() {
   let client = new FxAccountsOAuthGrantClient(CLIENT_OPTIONS);
   let response = {
     status: 400,
     body: "{ \"code\": 400, \"errno\": \"bad errno\", \"error\": \"Bad Request\", \"message\": \"Unauthorized\", \"reason\": \"Invalid fxa assertion\" }",
   };
 
   client._Request = new mockResponse(response);
   client.getTokenFromAssertion("blah", "scope")
-    .then(
-    null,
-    function(e) {
+    .catch(function(e) {
       do_check_eq(e.name, "FxAccountsOAuthGrantClientError");
       do_check_eq(e.code, 400);
       do_check_eq(e.errno, ERRNO_UNKNOWN_ERROR);
       do_check_eq(e.error, "Bad Request");
       do_check_eq(e.message, "Unauthorized");
       run_next_test();
     }
   );
--- a/services/fxaccounts/tests/xpcshell/test_profile_client.js
+++ b/services/fxaccounts/tests/xpcshell/test_profile_client.js
@@ -135,19 +135,17 @@ add_test(function parseErrorResponse() {
   let response = {
     success: true,
     status: STATUS_SUCCESS,
     body: "unexpected",
   };
 
   client._Request = new mockResponse(response);
   client.fetchProfile()
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsProfileClientError");
         do_check_eq(e.code, STATUS_SUCCESS);
         do_check_eq(e.errno, ERRNO_PARSE);
         do_check_eq(e.error, ERROR_PARSE);
         do_check_eq(e.message, "unexpected");
         run_next_test();
       }
     );
@@ -157,19 +155,17 @@ add_test(function serverErrorResponse() 
   let client = new FxAccountsProfileClient(PROFILE_OPTIONS);
   let response = {
     status: 500,
     body: "{ \"code\": 500, \"errno\": 100, \"error\": \"Bad Request\", \"message\": \"Something went wrong\", \"reason\": \"Because the internet\" }",
   };
 
   client._Request = new mockResponse(response);
   client.fetchProfile()
-    .then(
-    null,
-    function(e) {
+    .catch(function(e) {
       do_check_eq(e.name, "FxAccountsProfileClientError");
       do_check_eq(e.code, 500);
       do_check_eq(e.errno, 100);
       do_check_eq(e.error, "Bad Request");
       do_check_eq(e.message, "Something went wrong");
       run_next_test();
     }
   );
@@ -293,19 +289,17 @@ add_test(function server401ResponsePersi
       get() {
         this.response = response;
         ++numRequests;
         this.onComplete();
       }
     };
   }
 
-  client.fetchProfile().then(
-    null,
-    function(e) {
+  client.fetchProfile().catch(function(e) {
       do_check_eq(e.name, "FxAccountsProfileClientError");
       do_check_eq(e.code, 401);
       do_check_eq(e.errno, 100);
       do_check_eq(e.error, "It's not your token, it's you!");
       // should have been exactly 2 requests and exactly 2 auth headers.
       do_check_eq(numRequests, 2);
       do_check_eq(numAuthHeaders, 2);
       // and we should have seen both tokens revoked.
@@ -316,52 +310,46 @@ add_test(function server401ResponsePersi
 });
 
 add_test(function networkErrorResponse() {
   let client = new FxAccountsProfileClient({
     serverURL: "http://domain.dummy",
     fxa: mockFxa,
   });
   client.fetchProfile()
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsProfileClientError");
         do_check_eq(e.code, null);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         run_next_test();
       }
     );
 });
 
 add_test(function unsupportedMethod() {
   let client = new FxAccountsProfileClient(PROFILE_OPTIONS);
 
   return client._createRequest("/profile", "PUT")
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsProfileClientError");
         do_check_eq(e.code, ERROR_CODE_METHOD_NOT_ALLOWED);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         do_check_eq(e.message, ERROR_MSG_METHOD_NOT_ALLOWED);
         run_next_test();
       }
     );
 });
 
 add_test(function onCompleteRequestError() {
   let client = new FxAccountsProfileClient(PROFILE_OPTIONS);
   client._Request = new mockResponseError(new Error("onComplete error"));
   client.fetchProfile()
-    .then(
-      null,
-      function(e) {
+    .catch(function(e) {
         do_check_eq(e.name, "FxAccountsProfileClientError");
         do_check_eq(e.code, null);
         do_check_eq(e.errno, ERRNO_NETWORK);
         do_check_eq(e.error, ERROR_NETWORK);
         do_check_eq(e.message, "Error: onComplete error");
         run_next_test();
       }
   );
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -835,18 +835,17 @@ BrowserIDClusterManager.prototype = {
         }
       ).then(endPointFromIdentityToken
       );
     };
 
     let cb = Async.makeSpinningCallback();
     promiseClusterURL().then(function(clusterURL) {
       cb(null, clusterURL);
-    }).then(
-      null, err => {
+    }).catch(err => {
       log.info("Failed to fetch the cluster URL", err);
       // service.js's verifyLogin() method will attempt to fetch a cluster
       // URL when it sees a 401.  If it gets null, it treats it as a "real"
       // auth error and sets Status.login to LOGIN_FAILED_LOGIN_REJECTED, which
       // in turn causes a notification bar to appear informing the user they
       // need to re-authenticate.
       // On the other hand, if fetching the cluster URL fails with an exception,
       // verifyLogin() assumes it is a transient error, and thus doesn't show
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -263,17 +263,17 @@ HistoryStore.prototype = {
     let i, k;
     for (i = 0, k = 0; i < records.length; i++) {
       let record = records[k] = records[i];
       let shouldApply;
 
       try {
         if (record.deleted) {
           let promise = this.remove(record);
-          promise = promise.then(null, ex => failed.push(record.id));
+          promise = promise.catch(ex => failed.push(record.id));
           blockers.push(promise);
 
           // No further processing needed. Remove it from the list.
           shouldApply = false;
         } else {
           shouldApply = this._recordToPlaceInfo(record);
         }
       } catch (ex) {
--- a/services/sync/tps/extensions/tps/resource/modules/bookmarks.jsm
+++ b/services/sync/tps/extensions/tps/resource/modules/bookmarks.jsm
@@ -20,17 +20,17 @@ Cu.import("resource://services-common/as
 Cu.import("resource://tps/logger.jsm");
 
 var DumpBookmarks = function TPS_Bookmarks__DumpBookmarks() {
   let cb = Async.makeSpinningCallback();
   PlacesBackups.getBookmarksTree().then(result => {
     let [bookmarks, ] = result;
     Logger.logInfo("Dumping Bookmarks...\n" + JSON.stringify(bookmarks) + "\n\n");
     cb(null);
-  }).then(null, error => {
+  }).catch(error => {
     cb(error);
   });
   cb.wait();
 };
 
 /**
  * extend, causes a child object to inherit from a parent
  */
--- a/testing/modules/Assert.jsm
+++ b/testing/modules/Assert.jsm
@@ -387,17 +387,17 @@ proto.rejects = function(promise, expect
       err => {
         if (expected && !expectedException(err, expected)) {
           reject(err);
           return;
         }
         this.report(false, err, expected, message);
         resolve();
       }
-    ).then(null, reject);
+    ).catch(reject);
   });
 };
 
 function compareNumbers(expression, lhs, rhs, message, operator) {
   let lhsIsNumber = typeof lhs == "number";
   let rhsIsNumber = typeof rhs == "number";
 
   if (lhsIsNumber && rhsIsNumber) {
--- a/toolkit/components/asyncshutdown/AsyncShutdown.jsm
+++ b/toolkit/components/asyncshutdown/AsyncShutdown.jsm
@@ -706,17 +706,17 @@ function Barrier(name) {
       } else {
         // If `condition` is not a function, `trigger` is not particularly
         // interesting, and `condition` needs to be normalized to a promise.
         trigger = () => {};
         promise = Promise.resolve(condition);
       }
 
       // Make sure that `promise` never rejects.
-      promise = promise.then(null, error => {
+      promise = promise.catch(error => {
         let msg = `A blocker encountered an error while we were waiting.
           Blocker:  ${ name }
           Phase: ${ this._name }
           State: ${ safeGetState(fetchState) }`;
         warn(msg, error);
 
         // The error should remain uncaught, to ensure that it
         // still causes tests to fail.
@@ -847,17 +847,17 @@ Barrier.prototype = Object.freeze({
       blocker.trigger(); // We have guarantees that this method will never throw
     }
 
     this._isStarted = true;
 
     // Now, wait
     let promise = this._waitForMe.wait();
 
-    promise = promise.then(null, function onError(error) {
+    promise = promise.catch(function onError(error) {
       // I don't think that this can happen.
       // However, let's be overcautious with async/shutdown error reporting.
       let msg = "An uncaught error appeared while completing the phase." +
         " Phase: " + topic;
       warn(msg, error);
     });
 
     promise = promise.then(() => {
--- a/toolkit/components/jsdownloads/src/DownloadCore.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm
@@ -569,17 +569,17 @@ this.Download.prototype = {
    * @rejects  JavaScript exception if any of the operations failed.
    */
   async _succeed() {
     await DownloadIntegration.downloadDone(this);
 
     this._deferSucceeded.resolve();
 
     if (this.launchWhenSucceeded) {
-      this.launch().then(null, Cu.reportError);
+      this.launch().catch(Cu.reportError);
 
       // Always schedule files to be deleted at the end of the private browsing
       // mode, regardless of the value of the pref.
       if (this.source.isPrivate) {
         gExternalAppLauncher.deleteTemporaryPrivateFileWhenPossible(
                              new FileUtils.File(this.target.path));
       } else if (Services.prefs.getBoolPref(
                   "browser.helperApps.deleteTempFileOnExit")) {
@@ -954,17 +954,17 @@ this.Download.prototype = {
           }
 
           this.hasBlockedData = false;
           this.hasPartialData = false;
         }
 
         this._notifyChange();
       }
-    })().then(null, Cu.reportError);
+    })().catch(Cu.reportError);
   },
 
   /**
    * True if the "finalize" method has been called.  This prevents the download
    * from starting again after having been stopped.
    */
   _finalized: false,
 
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -909,17 +909,17 @@ this.DownloadObserver = {
       onDownloadRemoved: aDownload => {
         downloadsSet.delete(aDownload);
         // The download must also be removed from the canceled when offline set.
         this._canceledOfflineDownloads.delete(aDownload);
       }
     };
 
     // We register the view asynchronously.
-    aList.addView(downloadsView).then(null, Cu.reportError);
+    aList.addView(downloadsView).catch(Cu.reportError);
   },
 
   /**
    * Wrapper that handles the test mode before calling the prompt that display
    * a warning message box that informs that there are active downloads,
    * and asks whether the user wants to cancel them or not.
    *
    * @param aCancel
@@ -982,18 +982,18 @@ this.DownloadObserver = {
         break;
       case "last-pb-context-exited":
         let promise = (async function() {
           let list = await Downloads.getList(Downloads.PRIVATE);
           let downloads = await list.getAll();
 
           // We can remove the downloads and finalize them in parallel.
           for (let download of downloads) {
-            list.remove(download).then(null, Cu.reportError);
-            download.finalize(true).then(null, Cu.reportError);
+            list.remove(download).catch(Cu.reportError);
+            download.finalize(true).catch(Cu.reportError);
           }
         })();
         // Handle test mode
         if (gCombinedDownloadIntegration._testResolveClearPrivateList) {
           gCombinedDownloadIntegration._testResolveClearPrivateList(promise);
         } else {
           promise.catch(ex => Cu.reportError(ex));
         }
--- a/toolkit/components/jsdownloads/src/DownloadLegacy.js
+++ b/toolkit/components/jsdownloads/src/DownloadLegacy.js
@@ -127,31 +127,31 @@ DownloadLegacyTransfer.prototype = {
             this._cancelable.cancel(Cr.NS_ERROR_ABORT);
             if (this._cancelable instanceof Ci.nsIWebBrowserPersist) {
               // This component will not send the STATE_STOP notification.
               download.saver.onTransferFinished(Cr.NS_ERROR_ABORT);
               this._cancelable = null;
             }
           }
         });
-      }).then(null, Cu.reportError);
+      }).catch(Cu.reportError);
     } else if ((aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) &&
         (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)) {
       // The last file has been received, or the download failed.  Wait for the
       // associated Download object to be available before notifying.
       this._deferDownload.promise.then(download => {
         // At this point, the hash has been set and we need to copy it to the
         // DownloadSaver.
         if (Components.isSuccessCode(aStatus)) {
           download.saver.setSha256Hash(this._sha256Hash);
           download.saver.setSignatureInfo(this._signatureInfo);
           download.saver.setRedirects(this._redirects);
         }
         download.saver.onTransferFinished(aStatus);
-      }).then(null, Cu.reportError);
+      }).catch(Cu.reportError);
 
       // Release the reference to the component executing the download.
       this._cancelable = null;
     }
   },
 
   onProgressChange: function DLT_onProgressChange(aWebProgress, aRequest,
                                                   aCurSelfProgress,
@@ -171,33 +171,33 @@ DownloadLegacyTransfer.prototype = {
     // change, but if no network request actually started, it is possible that
     // we only receive a status change with an error status code.
     if (!Components.isSuccessCode(aStatus)) {
       this._componentFailed = true;
 
       // Wait for the associated Download object to be available.
       this._deferDownload.promise.then(function DLT_OSC_onDownload(aDownload) {
         aDownload.saver.onTransferFinished(aStatus);
-      }).then(null, Cu.reportError);
+      }).catch(Cu.reportError);
     }
   },
 
   onSecurityChange() { },
 
   // nsIWebProgressListener2
 
   onProgressChange64: function DLT_onProgressChange64(aWebProgress, aRequest,
                                                       aCurSelfProgress,
                                                       aMaxSelfProgress,
                                                       aCurTotalProgress,
                                                       aMaxTotalProgress) {
     // Wait for the associated Download object to be available.
     this._deferDownload.promise.then(function DLT_OPC64_onDownload(aDownload) {
       aDownload.saver.onProgressBytes(aCurTotalProgress, aMaxTotalProgress);
-    }).then(null, Cu.reportError);
+    }).catch(Cu.reportError);
   },
 
   onRefreshAttempted: function DLT_onRefreshAttempted(aWebProgress, aRefreshURI,
                                                       aMillis, aSameURI) {
     // Indicate that refreshes and redirects are allowed by default.  However,
     // note that download components don't usually call this method at all.
     return true;
   },
@@ -242,17 +242,17 @@ DownloadLegacyTransfer.prototype = {
       // Start the download before allowing it to be controlled.  Ignore errors.
       aDownload.start().catch(() => {});
 
       // Start processing all the other events received through nsITransfer.
       this._deferDownload.resolve(aDownload);
 
       // Add the download to the list, allowing it to be seen and canceled.
       return Downloads.getList(Downloads.ALL).then(list => list.add(aDownload));
-    }).then(null, Cu.reportError);
+    }).catch(Cu.reportError);
   },
 
   setSha256Hash(hash) {
     this._sha256Hash = hash;
   },
 
   setSignatureInfo(signatureInfo) {
     this._signatureInfo = signatureInfo;
--- a/toolkit/components/jsdownloads/src/DownloadList.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadList.jsm
@@ -236,20 +236,20 @@ this.DownloadList.prototype = {
             (!aFilterFn || aFilterFn(download))) {
           // Remove the download first, so that the views don't get the change
           // notifications that may occur during finalization.
           await this.remove(download);
           // Ensure that the download is stopped and no partial data is kept.
           // This works even if the download state has changed meanwhile.  We
           // don't need to wait for the procedure to be complete before
           // processing the other downloads in the list.
-          download.finalize(true).then(null, Cu.reportError);
+          download.finalize(true).catch(Cu.reportError);
         }
       }
-    })().then(null, Cu.reportError);
+    })().catch(Cu.reportError);
   },
 };
 
 // DownloadCombinedList
 
 /**
  * Provides a unified, unordered list combining public and private downloads.
  *
@@ -261,18 +261,18 @@ this.DownloadList.prototype = {
  *        Underlying DownloadList containing public downloads.
  * @param aPrivateList
  *        Underlying DownloadList containing private downloads.
  */
 this.DownloadCombinedList = function(aPublicList, aPrivateList) {
   DownloadList.call(this);
   this._publicList = aPublicList;
   this._privateList = aPrivateList;
-  aPublicList.addView(this).then(null, Cu.reportError);
-  aPrivateList.addView(this).then(null, Cu.reportError);
+  aPublicList.addView(this).catch(Cu.reportError);
+  aPrivateList.addView(this).catch(Cu.reportError);
 }
 
 this.DownloadCombinedList.prototype = {
   __proto__: DownloadList.prototype,
 
   /**
    * Underlying DownloadList containing public downloads.
    */
--- a/toolkit/components/jsdownloads/test/unit/head.js
+++ b/toolkit/components/jsdownloads/test/unit/head.js
@@ -331,40 +331,40 @@ function promiseStartLegacyDownload(aSou
 
   return new Promise(resolve => {
 
     Downloads.getList(Downloads.ALL).then(function(aList) {
       // Temporarily register a view that will get notified when the download we
       // are controlling becomes visible in the list of downloads.
       aList.addView({
         onDownloadAdded(aDownload) {
-          aList.removeView(this).then(null, do_report_unexpected_exception);
+          aList.removeView(this).catch(do_report_unexpected_exception);
 
           // Remove the download to keep the list empty for the next test.  This
           // also allows the caller to register the "onchange" event directly.
           let promise = aList.remove(aDownload);
 
           // When the download object is ready, make it available to the caller.
           promise.then(() => resolve(aDownload),
                        do_report_unexpected_exception);
         },
-      }).then(null, do_report_unexpected_exception);
+      }).catch(do_report_unexpected_exception);
 
       let isPrivate = aOptions && aOptions.isPrivate;
 
       // Initialize the components so they reference each other.  This will cause
       // the Download object to be created and added to the public downloads.
       transfer.init(sourceURI, NetUtil.newURI(targetFile), null, mimeInfo, null,
                     null, persist, isPrivate);
       persist.progressListener = transfer;
 
       // Start the actual download process.
       persist.savePrivacyAwareURI(sourceURI, null, null, 0, null, null, targetFile,
                                   isPrivate);
-    }).then(null, do_report_unexpected_exception);
+    }).catch(do_report_unexpected_exception);
 
   });
 }
 
 /**
  * Starts a new download using the nsIHelperAppService interface, and controls
  * it using the legacy nsITransfer interface.  The source of the download will
  * be "interruptible_resumable.txt" and partially downloaded data will be kept.
@@ -384,27 +384,27 @@ function promiseStartExternalHelperAppSe
 
   return new Promise(resolve => {
 
     Downloads.getList(Downloads.PUBLIC).then(function(aList) {
       // Temporarily register a view that will get notified when the download we
       // are controlling becomes visible in the list of downloads.
       aList.addView({
         onDownloadAdded(aDownload) {
-          aList.removeView(this).then(null, do_report_unexpected_exception);
+          aList.removeView(this).catch(do_report_unexpected_exception);
 
           // Remove the download to keep the list empty for the next test.  This
           // also allows the caller to register the "onchange" event directly.
           let promise = aList.remove(aDownload);
 
           // When the download object is ready, make it available to the caller.
           promise.then(() => resolve(aDownload),
                        do_report_unexpected_exception);
         },
-      }).then(null, do_report_unexpected_exception);
+      }).catch(do_report_unexpected_exception);
 
       let channel = NetUtil.newChannel({
         uri: sourceURI,
         loadUsingSystemPrincipal: true
       });
 
       // Start the actual download process.
       channel.asyncOpen2({
@@ -422,17 +422,17 @@ function promiseStartExternalHelperAppSe
         },
 
         onDataAvailable(aRequest, aContext, aInputStream, aOffset,
                                   aCount) {
           this.contentListener.onDataAvailable(aRequest, aContext, aInputStream,
                                                aOffset, aCount);
         },
       });
-    }).then(null, do_report_unexpected_exception);
+    }).catch(do_report_unexpected_exception);
 
   });
 }
 
 /**
  * Waits for a download to reach half of its progress, in case it has not
  * reached the expected progress already.
  *
@@ -634,17 +634,17 @@ function registerInterruptibleHandler(aP
     aResponse.processAsync();
     aFirstPartFn(aRequest, aResponse);
 
     // Wait on the current deferred object, then finish the request.
     _gDeferResponses.promise.then(function RIH_onSuccess() {
       aSecondPartFn(aRequest, aResponse);
       aResponse.finish();
       do_print("Interruptible request finished.");
-    }).then(null, Cu.reportError);
+    }).catch(Cu.reportError);
   });
 }
 
 /**
  * Ensure the given date object is valid.
  *
  * @param aDate
  *        The date object to be checked. This value can be null.
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -369,19 +369,19 @@ var Scheduler = this.Scheduler = {
    * This function will be executed once all the previously
    * pushed tasks have completed.
    * @return {Promise} A promise with the same behavior as
    * the promise returned by |code|.
    */
   push: function(code) {
     let promise = this.queue.then(code);
     // By definition, |this.queue| can never reject.
-    this.queue = promise.then(null, () => undefined);
+    this.queue = promise.catch(() => undefined);
     // Fork |promise| to ensure that uncaught errors are reported
-    return promise.then(null, null);
+    return promise.catch(null);
   },
 
   /**
    * Post a message to the worker thread.
    *
    * @param {string} method The name of the method to call.
    * @param {...} args The arguments to pass to the method. These arguments
    * must be clonable.
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm
+++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm
@@ -441,17 +441,17 @@ var LoginManagerContent = {
     messageManager.sendAsyncMessage("LoginStats:LoginEncountered");
 
     if (!gEnabled) {
       return;
     }
 
     this._getLoginDataFromParent(form, { showMasterPassword: true })
         .then(this.loginsFound.bind(this))
-        .then(null, Cu.reportError);
+        .catch(Cu.reportError);
   },
 
   onPageShow(event, window) {
     this._detectInsecureFormLikes(window);
   },
 
   /**
    * Maps all DOM content documents in this content process, including those in
@@ -645,17 +645,17 @@ var LoginManagerContent = {
       this._getLoginDataFromParent(acForm, { showMasterPassword: false })
           .then(({ form, loginsFound, recipes }) => {
             this._fillForm(form, loginsFound, recipes, {
               autofillForm: true,
               clobberPassword: true,
               userTriggered: true,
             });
           })
-          .then(null, Cu.reportError);
+          .catch(Cu.reportError);
     } else {
       // Ignore the event, it's for some input we don't care about.
     }
   },
 
   /**
    * @param {FormLike} form - the FormLike to look for password fields in.
    * @param {Object} options
--- a/toolkit/components/passwordmgr/nsLoginManager.js
+++ b/toolkit/components/passwordmgr/nsLoginManager.js
@@ -522,17 +522,17 @@ LoginManager.prototype = {
       previousResult = null;
     }
 
     let rect = BrowserUtils.getElementBoundingScreenRect(aElement);
     let acLookupPromise = this._autoCompleteLookupPromise =
       LoginManagerContent._autoCompleteSearchAsync(aSearchString, previousResult,
                                                    aElement, rect);
     acLookupPromise.then(completeSearch.bind(this, acLookupPromise))
-                             .then(null, Cu.reportError);
+                             .catch(Cu.reportError);
   },
 
   stopSearch() {
     this._autoCompleteLookupPromise = null;
   },
 }; // end of LoginManager implementation
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([LoginManager]);
--- a/toolkit/components/places/Bookmarks.jsm
+++ b/toolkit/components/places/Bookmarks.jsm
@@ -715,17 +715,17 @@ var Bookmarks = Object.freeze({
                                         syncChangeCounter = syncChangeCounter + :syncChangeDelta
                WHERE id IN (SELECT id FROM moz_bookmarks WHERE guid = :folderGuid )
               `, { folderGuid, time, syncChangeDelta });
           }
         });
 
         // We don't wait for the frecency calculation.
         if (urls && urls.length) {
-          updateFrecency(db, urls, true).then(null, Cu.reportError);
+          updateFrecency(db, urls, true).catch(Cu.reportError);
         }
       }
     );
   },
 
   /**
    * Returns a list of recently bookmarked items.
    * Only includes actual bookmarks. Excludes folders, separators and queries.
--- a/toolkit/components/places/PlacesUtils.jsm
+++ b/toolkit/components/places/PlacesUtils.jsm
@@ -3064,17 +3064,17 @@ PlacesCreateLivemarkTransaction.prototyp
         }
       }, Cu.reportError);
   },
 
   undoTransaction: function CLTXN_undoTransaction() {
     // The getLivemark callback may fail, but it is used just to serialize,
     // so it doesn't matter.
     this._promise = PlacesUtils.livemarks.getLivemark({ id: this.item.id })
-      .then(null, null).then( () => {
+      .catch(null).then( () => {
         PlacesUtils.bookmarks.removeItem(this.item.id);
       });
   }
 };
 
 
 /**
  * Transaction for removing a livemark item.
@@ -3116,17 +3116,17 @@ PlacesRemoveLivemarkTransaction.prototyp
   },
 
   undoTransaction: function RLTXN_undoTransaction() {
     // Undo work must be serialized, otherwise won't be able to know the
     // feedURI and siteURI of the livemark.
     // The getLivemark callback is expected to receive a failure status but it
     // is used just to serialize, so doesn't matter.
     PlacesUtils.livemarks.getLivemark({ id: this.item.id })
-      .then(null, () => {
+      .catch(() => {
         PlacesUtils.livemarks.addLivemark({ parentId: this.item.parentId
                                           , title: this.item.title
                                           , siteURI: this.item.siteURI
                                           , feedURI: this.item.feedURI
                                           , index: this.item.index
                                           , lastModified: this.item.lastModified
                                           }).then(
           aLivemark => {
--- a/toolkit/components/places/UnifiedComplete.js
+++ b/toolkit/components/places/UnifiedComplete.js
@@ -2199,17 +2199,17 @@ UnifiedComplete.prototype = {
         // indices.  A larger cache helps reducing IO and improving performance.
         // The value used here is larger than the default Storage value defined
         // as MAX_CACHE_SIZE_BYTES in storage/mozStorageConnection.cpp.
         await conn.execute("PRAGMA cache_size = -6144"); // 6MiB
 
         await SwitchToTabStorage.initDatabase(conn);
 
         return conn;
-      })().then(null, ex => {
+      })().catch(ex => {
         dump("Couldn't get database handle: " + ex + "\n");
         Cu.reportError(ex);
       });
     }
     return this._promiseDatabase;
   },
 
   // mozIPlacesAutoComplete
@@ -2251,17 +2251,17 @@ UnifiedComplete.prototype = {
     // result regardless, so we still create the Search object.
     if (!Prefs.enabled) {
       this.finishSearch(true);
       return;
     }
 
     let search = this._currentSearch;
     this.getDatabaseHandle().then(conn => search.execute(conn))
-                            .then(null, ex => {
+                            .catch(ex => {
                               dump(`Query failed: ${ex}\n`);
                               Cu.reportError(ex);
                             })
                             .then(() => {
                               if (search == this._currentSearch) {
                                 this.finishSearch(true);
                               }
                             });
--- a/toolkit/components/places/tests/unit/test_bookmarks_restore_notification.js
+++ b/toolkit/components/places/tests/unit/test_bookmarks_restore_notification.js
@@ -209,17 +209,17 @@ add_task(async function test_html_restor
 
   do_print("HTML restore: normal restore should succeed");
   let file = await promiseFile("bookmarks-test_restoreNotification.html");
   await addBookmarks();
   await BookmarkHTMLUtils.exportToFile(file);
   await PlacesUtils.bookmarks.eraseEverything();
   try {
     BookmarkHTMLUtils.importFromFile(file, false)
-                     .then(null, do_report_unexpected_exception);
+                     .catch(do_report_unexpected_exception);
   } catch (e) {
     do_throw("  Restore should not have failed");
   }
 
   await checkObservers(expectPromises, expectedData);
   await teardown(file);
 });
 
@@ -229,17 +229,17 @@ add_task(async function test_html_restor
     folderId:   null
   }
   let expectPromises = registerObservers(true);
 
   do_print("HTML restore: empty file should succeed");
   let file = await promiseFile("bookmarks-test_restoreNotification.init.html");
   try {
     BookmarkHTMLUtils.importFromFile(file, false)
-                     .then(null, do_report_unexpected_exception);
+                     .catch(do_report_unexpected_exception);
   } catch (e) {
     do_throw("  Restore should not have failed");
   }
 
   await checkObservers(expectPromises, expectedData);
   await teardown(file);
 });
 
@@ -271,17 +271,17 @@ add_task(async function test_html_init_r
 
   do_print("HTML initial restore: normal restore should succeed");
   let file = await promiseFile("bookmarks-test_restoreNotification.init.html");
   await addBookmarks();
   await BookmarkHTMLUtils.exportToFile(file);
   await PlacesUtils.bookmarks.eraseEverything();
   try {
     BookmarkHTMLUtils.importFromFile(file, true)
-                     .then(null, do_report_unexpected_exception);
+                     .catch(do_report_unexpected_exception);
   } catch (e) {
     do_throw("  Restore should not have failed");
   }
 
   await checkObservers(expectPromises, expectedData);
   await teardown(file);
 });
 
@@ -291,17 +291,17 @@ add_task(async function test_html_init_r
     folderId:   null
   }
   let expectPromises = registerObservers(true);
 
   do_print("HTML initial restore: empty file should succeed");
   let file = await promiseFile("bookmarks-test_restoreNotification.init.html");
   try {
     BookmarkHTMLUtils.importFromFile(file, true)
-                     .then(null, do_report_unexpected_exception);
+                     .catch(do_report_unexpected_exception);
   } catch (e) {
     do_throw("  Restore should not have failed");
   }
 
   await checkObservers(expectPromises, expectedData);
   await teardown(file);
 });
 
--- a/toolkit/components/thumbnails/PageThumbs.jsm
+++ b/toolkit/components/thumbnails/PageThumbs.jsm
@@ -529,19 +529,17 @@ this.PageThumbsStorage = {
 
   ensurePath: function Storage_ensurePath() {
     // Create the directory (ignore any error if the directory
     // already exists). As all writes are done from the PageThumbsWorker
     // thread, which serializes its operations, this ensures that
     // future operations can proceed without having to check whether
     // the directory exists.
     return PageThumbsWorker.post("makeDir",
-      [this.path, {ignoreExisting: true}]).then(
-        null,
-        function onError(aReason) {
+      [this.path, {ignoreExisting: true}]).catch(function onError(aReason) {
           Components.utils.reportError("Could not create thumbnails directory" + aReason);
         });
   },
 
   getLeafNameForURL: function Storage_getLeafNameForURL(aURL) {
     if (typeof aURL != "string") {
       throw new TypeError("Expecting a string");
     }
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -427,17 +427,17 @@ function internalSave(aURL, aDocument, a
     promiseTargetFile(fpParams, aSkipPrompt, relatedURI).then(aDialogAccepted => {
       if (!aDialogAccepted)
         return;
 
       saveAsType = fpParams.saveAsType;
       file = fpParams.file;
 
       continueSave();
-    }).then(null, Components.utils.reportError);
+    }).catch(Components.utils.reportError);
   }
 
   function continueSave() {
     // XXX We depend on the following holding true in appendFiltersForContentType():
     // If we should save as a complete page, the saveAsType is kSaveAsType_Complete.
     // If we should save as text, the saveAsType is kSaveAsType_Text.
     var useSaveDocument = aDocument &&
                           (((saveMode & SAVEMODE_COMPLETE_DOM) && (saveAsType == kSaveAsType_Complete)) ||
@@ -820,17 +820,17 @@ function DownloadURL(aURL, aFileName, aI
     download.tryToKeepPartialData = true;
 
     // Ignore errors because failures are reported through the download list.
     download.start().catch(() => {});
 
     // Add the download to the list, allowing it to be managed.
     let list = await Downloads.getList(Downloads.ALL);
     list.add(download);
-  })().then(null, Components.utils.reportError);
+  })().catch(Components.utils.reportError);
 }
 
 // We have no DOM, and can only save the URL as is.
 const SAVEMODE_FILEONLY      = 0x00;
 XPCOMUtils.defineConstant(this, "SAVEMODE_FILEONLY", SAVEMODE_FILEONLY);
 // We have a DOM and can save as complete.
 const SAVEMODE_COMPLETE_DOM  = 0x01;
 XPCOMUtils.defineConstant(this, "SAVEMODE_COMPLETE_DOM", SAVEMODE_COMPLETE_DOM);
--- a/toolkit/modules/DeferredTask.jsm
+++ b/toolkit/modules/DeferredTask.jsm
@@ -288,17 +288,17 @@ this.DeferredTask.prototype = {
           this._armed = false;
           await this._runTask();
         }
       }
 
       // Indicate that the execution of the task has finished.  This happens
       // synchronously with the previous state changes in the function.
       this._runningPromise = null;
-    })().then(null, Cu.reportError));
+    })().catch(Cu.reportError));
   },
 
   /**
    * Executes the associated task and catches exceptions.
    */
   async _runTask() {
     try {
       let result = this._taskFn();
--- a/toolkit/modules/ZipUtils.jsm
+++ b/toolkit/modules/ZipUtils.jsm
@@ -142,17 +142,17 @@ this.ZipUtils = {
           } catch (e) {
             dump("extractFilesAsync: failed to extract file " + path + "\n");
             throw e;
           }
         }
       }
 
       zipReader.close();
-    })().then(null, (e) => {
+    })().catch((e) => {
       zipReader.close();
       throw e;
     });
   },
 
   /**
    * Extracts files from a ZIP file into a directory.
    *
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js
+++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js
@@ -357,17 +357,17 @@ nsUnknownContentTypeDialog.prototype = {
                 return;
               }
 
             }
           }
           aLauncher.saveDestinationAvailable(result);
         });
       });
-    })().then(null, Components.utils.reportError);
+    })().catch(Components.utils.reportError);
   },
 
   getFinalLeafName: function (aLeafName, aFileExt)
   {
     // Remove any leading periods, since we don't want to save hidden files
     // automatically.
     aLeafName = aLeafName.replace(/^\.+/, "");
 
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -1515,17 +1515,17 @@ var AddonManagerInternal = {
         }
       }
 
       logger.debug("Background update check complete");
       Services.obs.notifyObservers(null,
                                    "addons-background-update-complete");
     })();
     // Fork the promise chain so we can log the error and let our caller see it too.
-    buPromise.then(null, e => logger.warn("Error in background update", e));
+    buPromise.catch(e => logger.warn("Error in background update", e));
     return buPromise;
   },
 
   /**
    * Adds a add-on to the list of detected changes for this startup. If
    * addStartupChange is called multiple times for the same add-on in the same
    * startup then only the most recent change will be remembered.
    *
--- a/toolkit/mozapps/extensions/DeferredSave.jsm
+++ b/toolkit/mozapps/extensions/DeferredSave.jsm
@@ -197,24 +197,24 @@ this.DeferredSave.prototype = {
 
     // In either the success or the exception handling case, we don't need to handle
     // the error from _writing here; it's already being handled in another then()
     let toSave = null;
     try {
       toSave = this._dataProvider();
     } catch (e) {
         this.logger.error("Deferred save dataProvider failed", e);
-      writing.then(null, error => {})
+      writing.catch(error => {})
         .then(count => {
           pending.reject(e);
         });
       return;
     }
 
-    writing.then(null, error => { return 0; })
+    writing.catch(error => { return 0; })
     .then(count => {
         this.logger.debug("Starting write");
       this.totalSaves++;
       this.writeInProgress = true;
 
       OS.File.writeAtomic(this._path, toSave, {tmpPath: this._path + ".tmp"})
       .then(
         result => {
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -1652,21 +1652,21 @@ var AddonDatabase = {
    * @param  aCallback
    *         An optional callback to call once complete
    * @return Promise{null} resolves when the database has been deleted
    */
   delete(aCallback) {
     this.DB = BLANK_DB();
 
     this._deleting = this.Writer.flush()
-      .then(null, () => {})
+      .catch(() => {})
       // shutdown(true) never rejects
       .then(() => this.shutdown(true))
       .then(() => OS.File.remove(this.jsonFile, {}))
-      .then(null, error => logger.error("Unable to delete Addon Repository file " +
+      .catch(error => logger.error("Unable to delete Addon Repository file " +
                                  this.jsonFile, error))
       .then(() => this._deleting = null)
       .then(aCallback);
     return this._deleting;
   },
 
   toJSON() {
     let json = {
@@ -1894,18 +1894,17 @@ var AddonDatabase = {
   /**
    * Write the in-memory DB to disk, after waiting for
    * the DB_BATCH_TIMEOUT_MS timeout.
    *
    * @return Promise A promise that resolves after the
    *                 write to disk has completed.
    */
   _saveDBToDisk() {
-    return this.Writer.saveChanges().then(
-      null,
+    return this.Writer.saveChanges().catch(
       e => logger.error("SaveDBToDisk failed", e));
   },
 
   /**
    * Make a developer object from a vanilla
    * JS object from the JSON database
    *
    * @param  aObj
--- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm
@@ -380,17 +380,17 @@ GMPWrapper.prototype = {
     GMPPrefs.reset(GMPPrefs.KEY_UPDATE_LAST_CHECK, null);
     // Delay this in case the user changes his mind and doesn't want to
     // enable EME after all.
     setTimeout(() => {
       if (!this.appDisabled) {
         let gmpInstallManager = new GMPInstallManager();
         // We don't really care about the results, if someone is interested
         // they can check the log.
-        gmpInstallManager.simpleCheckAndInstall().then(null, () => {});
+        gmpInstallManager.simpleCheckAndInstall().catch(() => {});
       }
       this._isUpdateCheckPending = false;
     }, delay);
   },
 
   receiveMessage({target: browser, data: data}) {
     this._log.trace("receiveMessage() data=" + data);
     let parsedData;
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -1941,17 +1941,17 @@ class AddonInstall {
         }
         XPIProvider.setTelemetry(this.addon.id, "unpacked", installedUnpacked);
         recordAddonTelemetry(this.addon);
 
         // Notify providers that a new theme has been enabled.
         if (isTheme(this.addon.type) && this.addon.active)
           AddonManagerPrivate.notifyAddonChanged(this.addon.id, this.addon.type, requiresRestart);
       }
-    })().then(null, (e) => {
+    })().catch((e) => {
       logger.warn(`Failed to install ${this.file.path} from ${this.sourceURI.spec} to ${stagedAddon.path}`, e);
 
       if (stagedAddon.exists())
         recursiveRemove(stagedAddon);
       this.state = AddonManager.STATE_INSTALL_FAILED;
       this.error = AddonManager.ERROR_FILE_ACCESS;
       XPIProvider.removeActiveInstall(this);
       AddonManagerPrivate.callAddonListeners("onOperationCancelled",
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -6045,17 +6045,17 @@ class MutableDirectoryInstallLocation ex
   requestStagingDir() {
     this._stagingDirLock++;
 
     if (this._stagingDirPromise)
       return this._stagingDirPromise;
 
     OS.File.makeDir(this._directory.path);
     let stagepath = OS.Path.join(this._directory.path, DIR_STAGE);
-    return this._stagingDirPromise = OS.File.makeDir(stagepath).then(null, (e) => {
+    return this._stagingDirPromise = OS.File.makeDir(stagepath).catch((e) => {
       if (e instanceof OS.File.Error && e.becauseExists)
         return;
       logger.error("Failed to create staging directory", e);
       throw e;
     });
   }
 
   releaseStagingDir() {
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -676,17 +676,17 @@ this.XPIDatabase = {
             "XPIDB_saves_overlapped", this._deferredSave.overlappedSaves);
         AddonManagerPrivate.recordSimpleMeasure(
             "XPIDB_saves_late", this._deferredSave.dirty ? 1 : 0);
       }
 
       // Return a promise that any pending writes of the DB are complete and we
       // are finished cleaning up
       let flushPromise = this.flush();
-      flushPromise.then(null, error => {
+      flushPromise.catch(error => {
           logger.error("Flush of XPI database failed", error);
           AddonManagerPrivate.recordSimpleMeasure("XPIDB_shutdownFlush_failed", 1);
           // If our last attempt to read or write the DB failed, force a new
           // extensions.ini to be written to disk on the next startup
           Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
         })
         .then(count => {
           // Clear out the cached addons data loaded from JSON
@@ -739,17 +739,17 @@ this.XPIDatabase = {
    * @param  aCallback
    *         Called back with the addon, or null if no matching addon is found
    */
   getAddon(aFilter, aCallback) {
     return this.asyncLoadDB().then(
       addonDB => {
         getRepositoryAddon(_findAddon(addonDB, aFilter), makeSafe(aCallback));
       })
-    .then(null,
+    .catch(
         error => {
           logger.error("getAddon failed", error);
           makeSafe(aCallback)(null);
         });
   },
 
   /**
    * Asynchronously gets an add-on with a particular ID in a particular
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -179,17 +179,17 @@ function log_exceptions(aCallback, ...aA
   } catch (e) {
     info("Exception thrown: " + e);
     throw e;
   }
 }
 
 function log_callback(aPromise, aCallback) {
   aPromise.then(aCallback)
-    .then(null, e => info("Exception thrown: " + e));
+    .catch(e => info("Exception thrown: " + e));
   return aPromise;
 }
 
 function add_test(test) {
   gPendingTests.push(test);
 }
 
 function run_next_test() {