Bug 1353542 - Cleanup the script output and fix tests, r=Mossop.
authorFlorian Quèze <florian@queze.net>
Fri, 12 May 2017 14:54:05 +0200
changeset 406190 0929827f535f2c57eef31d3c28fdebb84bc87d95
parent 406189 586c752c204ac58c3155ef438edf559cc3e648c9
child 406191 b2d4e9f99355b57b0433b2f1add8259f00bc7aa5
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1353542
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1353542 - Cleanup the script output and fix tests, r=Mossop.
browser/base/content/content.js
browser/base/content/test/appUpdate/head.js
browser/base/content/test/general/browser_aboutCertError.js
browser/base/content/test/general/browser_audioTabIcon.js
browser/base/content/test/general/browser_getshortcutoruri.js
browser/base/content/test/popupNotifications/head.js
browser/base/content/test/social/head.js
browser/base/content/test/webrtc/head.js
browser/components/places/content/editBookmarkOverlay.js
browser/components/places/tests/unit/test_leftpane_corruption_handling.js
browser/components/search/test/browser_searchbar_openpopup.js
browser/components/uitour/test/head.js
browser/extensions/pdfjs/test/browser_pdfjs_navigation.js
browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm
services/sync/tests/unit/test_extension_storage_engine.js
services/sync/tests/unit/test_extension_storage_tracker.js
testing/mochitest/tests/SimpleTest/SimpleTest.js
toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js
toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
toolkit/components/formautofill/test/chrome/loader.js
toolkit/components/formautofill/test/chrome/loader_parent.js
toolkit/components/formautofill/test/loader_common.js
toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
toolkit/components/osfile/tests/xpcshell/head.js
toolkit/components/passwordmgr/test/pwmgr_common.js
toolkit/components/places/PlacesTransactions.jsm
toolkit/components/places/tests/unit/test_async_transactions.js
toolkit/components/places/tests/unit/test_promiseBookmarksTree.js
toolkit/components/satchel/test/browser/browser_privbrowsing_perwindowpb.js
toolkit/components/thumbnails/BackgroundPageThumbs.jsm
toolkit/modules/DeferredTask.jsm
toolkit/modules/Sqlite.jsm
toolkit/modules/tests/xpcshell/test_Log.js
toolkit/mozapps/extensions/test/browser/browser_experiments.js
toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -1187,17 +1187,17 @@ var PageInfoListener = {
       }
     }
     return feeds;
   },
 
   // Only called once to get the media tab's media elements from the content page.
   getMediaInfo(document, window, strings) {
     let frameList = this.goThroughFrames(document, window);
-    (() => this.processFrames(document, frameList, strings))();
+    this.processFrames(document, frameList, strings);
   },
 
   goThroughFrames(document, window) {
     let frameList = [document];
     if (window && window.frames.length > 0) {
       let num = window.frames.length;
       for (let i = 0; i < num; i++) {
         // Recurse through the frames.
--- a/browser/base/content/test/appUpdate/head.js
+++ b/browser/base/content/test/appUpdate/head.js
@@ -191,17 +191,17 @@ function runUpdateProcessingTest(updates
     }
 
     await finishTestRestoreUpdaterBackup();
   })();
 }
 
 function processStep(step) {
   if (typeof(step) == "function") {
-    return (step)();
+    return step();
   }
 
   const {notificationId, button, beforeClick, cleanup} = step;
   return (async function() {
 
     await BrowserTestUtils.waitForEvent(PanelUI.notificationPanel, "popupshown");
     const shownNotification = PanelUI.activeNotification.id;
 
--- a/browser/base/content/test/general/browser_aboutCertError.js
+++ b/browser/base/content/test/general/browser_aboutCertError.js
@@ -159,17 +159,17 @@ add_task(async function checkWrongSystem
   let serverDate = new Date("2015/10/27");
   let serverDateFmt = formatter.format(serverDate);
   let localDateFmt = formatter.format(new Date());
 
   let skew = Math.floor((Date.now() - serverDate.getTime()) / 1000);
   await SpecialPowers.pushPrefEnv({set: [[PREF_BLOCKLIST_CLOCK_SKEW_SECONDS, skew]]});
 
   info("Loading a bad cert page with a skewed clock");
-  let message = await (setUpPage)();
+  let message = await setUpPage();
 
   isnot(message.divDisplay, "none", "Wrong time message information is visible");
   ok(message.text.includes("clock appears to show the wrong time"),
      "Correct error message found");
   ok(message.text.includes("expired.example.com"), "URL found in error message");
   ok(message.systemDate.includes(localDateFmt), "correct local date displayed");
   ok(message.actualDate.includes(serverDateFmt), "correct server date displayed");
   ok(message.learnMoreLink.includes("time-errors"), "time-errors in the Learn More URL");
@@ -180,44 +180,44 @@ add_task(async function checkWrongSystem
   serverDate = new Date();
   serverDate.setYear(serverDate.getFullYear() + 1);
   serverDateFmt = formatter.format(serverDate);
 
   skew = Math.floor((Date.now() - serverDate.getTime()) / 1000);
   await SpecialPowers.pushPrefEnv({set: [[PREF_BLOCKLIST_CLOCK_SKEW_SECONDS, skew]]});
 
   info("Loading a bad cert page with a skewed clock");
-  message = await (setUpPage)();
+  message = await setUpPage();
 
   isnot(message.divDisplay, "none", "Wrong time message information is visible");
   ok(message.text.includes("clock appears to show the wrong time"),
      "Correct error message found");
   ok(message.text.includes("expired.example.com"), "URL found in error message");
   ok(message.systemDate.includes(localDateFmt), "correct local date displayed");
   ok(message.actualDate.includes(serverDateFmt), "correct server date displayed");
 
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
   // pretend we only have a slightly skewed system time, four hours
   skew = 60 * 60 * 4;
   await SpecialPowers.pushPrefEnv({set: [[PREF_BLOCKLIST_CLOCK_SKEW_SECONDS, skew]]});
 
   info("Loading a bad cert page with an only slightly skewed clock");
-  message = await (setUpPage)();
+  message = await setUpPage();
 
   is(message.divDisplay, "none", "Wrong time message information is not visible");
 
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 
   // now pretend we have no skewed system time
   skew = 0;
   await SpecialPowers.pushPrefEnv({set: [[PREF_BLOCKLIST_CLOCK_SKEW_SECONDS, skew]]});
 
   info("Loading a bad cert page with no skewed clock");
-  message = await (setUpPage)();
+  message = await setUpPage();
 
   is(message.divDisplay, "none", "Wrong time message information is not visible");
 
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function checkAdvancedDetails() {
   info("Loading a bad cert page and verifying the main error and advanced details section");
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -143,17 +143,17 @@ function get_wait_for_mute_promise(tab, 
       }
       return true;
     }
     return false;
   });
 }
 
 async function test_mute_tab(tab, icon, expectMuted) {
-  let mutedPromise = test_mute_keybinding(tab, expectMuted);
+  let mutedPromise = get_wait_for_mute_promise(tab, expectMuted);
 
   let activeTab = gBrowser.selectedTab;
 
   let tooltip = document.getElementById("tabbrowser-tab-tooltip");
 
   await hover_icon(icon, tooltip);
   EventUtils.synthesizeMouseAtCenter(icon, {button: 0});
   leave_icon(icon);
--- a/browser/base/content/test/general/browser_getshortcutoruri.js
+++ b/browser/base/content/test/general/browser_getshortcutoruri.js
@@ -65,21 +65,21 @@ var testData = [
   // parameter is passed (bug 420328).
   [new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"),
    new keywordResult(null, null, true)],
   [new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"),
    new keywordResult(null, null, true)],
 
   // Test escaping (%s = escaped, %S = raw)
   // UTF-8 default
-  [new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "fo�"),
-   new keywordResult("http://bmget/?esc=fo%C3%A9&raw=fo�", null)],
+  [new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "fo\xE9"),
+   new keywordResult("http://bmget/?esc=fo%C3%A9&raw=fo\xE9", null)],
   // Explicitly-defined ISO-8859-1
-  [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "fo�"),
-   new keywordResult("http://bmget/?esc=fo%E9&raw=fo�", null)],
+  [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "fo\xE9"),
+   new keywordResult("http://bmget/?esc=fo%E9&raw=fo\xE9", null)],
 
   // Bug 359809: Test escaping +, /, and @
   // UTF-8 default
   [new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "+/@"),
    new keywordResult("http://bmget/?esc=%2B%2F%40&raw=+/@", null)],
   // Explicitly-defined ISO-8859-1
   [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "+/@"),
    new keywordResult("http://bmget/?esc=%2B%2F%40&raw=+/@", null)],
@@ -132,12 +132,12 @@ async function setupKeywords() {
         let [paramName, paramValue] = data.postData.split("=");
         addedEngine.addParam(paramName, paramValue, null);
       }
       gAddedEngines.push(addedEngine);
     }
   }
 }
 
-function cleanupKeywords() {
-  PlacesUtils.bookmarks.remove(folder);
+async function cleanupKeywords() {
+  await PlacesUtils.bookmarks.remove(folder);
   gAddedEngines.map(Services.search.removeEngine);
 }
--- a/browser/base/content/test/popupNotifications/head.js
+++ b/browser/base/content/test/popupNotifications/head.js
@@ -74,17 +74,17 @@ function setup() {
                   .then(goNext);
   registerCleanupFunction(() => {
     gBrowser.removeTab(gBrowser.selectedTab);
     PopupNotifications.buttonDelay = PREF_SECURITY_DELAY_INITIAL;
   });
 }
 
 function goNext() {
-  executeSoon(() => executeSoon(Task.async(runNextTest)));
+  executeSoon(() => executeSoon(runNextTest));
 }
 
 async function runNextTest() {
   if (tests.length == 0) {
     executeSoon(finish);
     return;
   }
 
@@ -92,22 +92,22 @@ async function runNextTest() {
   if (nextTest.onShown) {
     let shownState = false;
     onPopupEvent("popupshowing", function() {
       info("[" + nextTest.id + "] popup showing");
     });
     onPopupEvent("popupshown", function() {
       shownState = true;
       info("[" + nextTest.id + "] popup shown");
-      (() => nextTest.onShown(this))()
+      (nextTest.onShown(this) || Promise.resolve())
           .then(undefined, ex => Assert.ok(false, "onShown failed: " + ex));
     });
     onPopupEvent("popuphidden", function() {
       info("[" + nextTest.id + "] popup hidden");
-      (() => nextTest.onHidden(this))()
+      (nextTest.onHidden(this) || Promise.resolve())
           .then(() => goNext(), ex => Assert.ok(false, "onHidden failed: " + ex));
     }, () => shownState);
     info("[" + nextTest.id + "] added listeners; panel is open: " + PopupNotifications.isPanelOpen);
   }
 
   info("[" + nextTest.id + "] running test");
   await nextTest.run();
 }
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -75,17 +75,17 @@ function runSocialTestWithProvider(manif
   }
 
   info("runSocialTestWithProvider: " + manifests.toSource());
 
   let finishCount = 0;
   function finishIfDone(callFinish) {
     finishCount++;
     if (finishCount == manifests.length)
-      (finishCleanUp)().then(finishcallback || defaultFinishChecks);
+      finishCleanUp().then(finishcallback || defaultFinishChecks);
   }
   function removeAddedProviders(cleanup) {
     manifests.forEach(function(m) {
       // If we're "cleaning up", don't call finish when done.
       let finishCb = cleanup ? function() {} : finishIfDone;
       // Similarly, if we're cleaning up, catch exceptions from removeProvider
       let removeProvider = SocialService.disableProvider.bind(SocialService);
       if (cleanup) {
--- a/browser/base/content/test/webrtc/head.js
+++ b/browser/base/content/test/webrtc/head.js
@@ -527,15 +527,15 @@ async function runTests(tests, options =
      "should start the test without any prior popup notification");
   ok(gIdentityHandler._identityPopup.hidden,
      "should start the test with the control center hidden");
 
   await SpecialPowers.pushPrefEnv({"set": [[PREF_PERMISSION_FAKE, true]]});
 
   for (let testCase of tests) {
     info(testCase.desc);
-    await (testCase.run(browser))();
+    await testCase.run(browser);
     await cleanup();
   }
 
   // Some tests destroy the original tab and leave a new one in its place.
   await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 }
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -548,17 +548,17 @@ var gEditItemOverlay = {
     };
 
     // Only in the library info-pane it's safe (and necessary) to batch these.
     // TODO bug 1093030: cleanup this mess when the bookmarksProperties dialog
     // and star UI code don't "run a batch in the background".
     if (window.document.documentElement.id == "places")
       PlacesTransactions.batch(setTags).catch(Components.utils.reportError);
     else
-      (setTags)().catch(Components.utils.reportError);
+      setTags().catch(Components.utils.reportError);
     return true;
   },
 
   async _updateTags() {
     let uris = this._paneInfo.bulkTagging ?
                  this._paneInfo.uris : [this._paneInfo.uri];
     let currentTags = this._paneInfo.bulkTagging ?
                         await this._getCommonTags() :
--- a/browser/components/places/tests/unit/test_leftpane_corruption_handling.js
+++ b/browser/components/places/tests/unit/test_leftpane_corruption_handling.js
@@ -47,17 +47,17 @@ add_task(async function() {
 
   // Create the left pane, and store its current status, it will be used
   // as reference value.
   gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
   gReferenceHierarchy = folderIdToHierarchy(gLeftPaneFolderId);
 
   while (gTests.length) {
     // Run current test.
-    await (gTests.shift())();
+    await gTests.shift();
 
     // Regenerate getters.
     Object.defineProperty(PlacesUIUtils, "leftPaneFolderId", gLeftPaneFolderIdGetter);
     gLeftPaneFolderId = PlacesUIUtils.leftPaneFolderId;
     Object.defineProperty(PlacesUIUtils, "allBookmarksFolderId", gAllBookmarksFolderIdGetter);
 
     // Check the new left pane folder.
     let leftPaneHierarchy = folderIdToHierarchy(gLeftPaneFolderId)
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -84,17 +84,17 @@ function add_no_popup_task(task) {
   add_task(async function() {
     let sawPopup = false;
     function listener() {
       sawPopup = true;
     }
 
     info("Entering test " + task.name);
     searchPopup.addEventListener("popupshowing", listener);
-    await (task)();
+    await task();
     searchPopup.removeEventListener("popupshowing", listener);
     ok(!sawPopup, "Shouldn't have seen the suggestions popup");
     info("Leaving test " + task.name);
   });
 }
 
 // Simulates the full set of events for a context click
 function context_click(target) {
--- a/browser/components/uitour/test/head.js
+++ b/browser/components/uitour/test/head.js
@@ -43,17 +43,17 @@ function waitForCondition(condition, nex
 
 /**
  * Wrapper to partially transition tests to Task. Use `add_UITour_task` instead for new tests.
  */
 function taskify(fun) {
   return (doneFn) => {
     // Output the inner function name otherwise no name will be output.
     info("\t" + fun.name);
-    return (fun)().then(doneFn, (reason) => {
+    return fun().then(doneFn, (reason) => {
       ok(false, reason);
       doneFn();
     });
   };
 }
 
 function is_hidden(element) {
   var style = element.ownerGlobal.getComputedStyle(element);
@@ -430,17 +430,17 @@ function nextTest() {
  * All new tests that need the help of `loadUITourTestPage` should use this
  * wrapper around their test's generator function to reduce boilerplate.
  */
 function add_UITour_task(func) {
   let genFun = async function() {
     await new Promise((resolve) => {
       waitForFocus(function() {
         loadUITourTestPage(function() {
-          let funcPromise = (func)()
+          let funcPromise = (func() || Promise.resolve())
                                 .then(() => done(true),
                                       (reason) => {
                                         ok(false, reason);
                                         return done(true);
                                       });
           resolve(funcPromise);
         });
       });
--- a/browser/extensions/pdfjs/test/browser_pdfjs_navigation.js
+++ b/browser/extensions/pdfjs/test/browser_pdfjs_navigation.js
@@ -158,17 +158,17 @@ add_task(async function test() {
       await ContentTask.spawn(newTabBrowser, null, async function() {
         // Check if PDF is opened with internal viewer
         Assert.ok(content.document.querySelector("div#viewer"), "document content has viewer UI");
         Assert.ok("PDFJS" in content.wrappedJSObject, "window content has PDFJS object");
       });
 
       await ContentTask.spawn(newTabBrowser, null, contentSetUp);
 
-      await (runTests(newTabBrowser))();
+      await runTests(newTabBrowser);
 
       await ContentTask.spawn(newTabBrowser, null, async function() {
         let pageNumber = content.document.querySelector("input#pageNumber");
         Assert.equal(pageNumber.value, pageNumber.max, "Document is left on the last page");
       });
     });
 });
 
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/TestRunner.jsm
@@ -216,17 +216,17 @@ this.TestRunner = {
                              String(this.combos.length).length) + this._comboName(combo);
       return Screenshot.captureExternal(filename)
         .then(() => {
           this.completedCombos++;
         });
     };
 
     log.debug("_onConfigurationReady");
-    return (delayedScreenshot)();
+    return delayedScreenshot();
   },
 
   _comboName(combo) {
     return combo.reduce(function(a, b) {
       return a + "_" + b.name;
     }, "");
   },
 };
--- a/services/sync/tests/unit/test_extension_storage_engine.js
+++ b/services/sync/tests/unit/test_extension_storage_engine.js
@@ -45,19 +45,19 @@ add_task(function* test_calling_sync_cal
   equal(syncMock.calls.length, 1);
 });
 
 add_task(function* test_calling_sync_calls_ext_storage_sync() {
   const extension = {id: "my-extension"};
   let oldSync = extensionStorageSync.syncAll;
   let syncMock = extensionStorageSync.syncAll = mock({returns: Promise.resolve()});
   try {
-    yield* withSyncContext(function* (context) {
+    yield withSyncContext(async function(context) {
       // Set something so that everyone knows that we're using storage.sync
-      yield extensionStorageSync.set(extension, {"a": "b"}, context);
+      await extensionStorageSync.set(extension, {"a": "b"}, context);
 
-      yield engine._sync();
+      await engine._sync();
     });
   } finally {
     extensionStorageSync.syncAll = oldSync;
   }
   do_check_true(syncMock.calls.length >= 1);
 });
--- a/services/sync/tests/unit/test_extension_storage_tracker.js
+++ b/services/sync/tests/unit/test_extension_storage_tracker.js
@@ -15,24 +15,24 @@ Service.engineManager.register(Extension
 const engine = Service.engineManager.get("extension-storage");
 do_get_profile();   // so we can use FxAccounts
 loadWebExtensionTestFunctions();
 
 add_task(function* test_changing_extension_storage_changes_score() {
   const tracker = engine._tracker;
   const extension = {id: "my-extension-id"};
   Svc.Obs.notify("weave:engine:start-tracking");
-  yield* withSyncContext(function*(context) {
-    yield extensionStorageSync.set(extension, {"a": "b"}, context);
+  yield withSyncContext(async function(context) {
+    await extensionStorageSync.set(extension, {"a": "b"}, context);
   });
   do_check_eq(tracker.score, SCORE_INCREMENT_MEDIUM);
 
   tracker.resetScore();
-  yield* withSyncContext(function*(context) {
-    yield extensionStorageSync.remove(extension, "a", context);
+  yield withSyncContext(async function(context) {
+    await extensionStorageSync.remove(extension, "a", context);
   });
   do_check_eq(tracker.score, SCORE_INCREMENT_MEDIUM);
 
   Svc.Obs.notify("weave:engine:stop-tracking");
 });
 
 function run_test() {
   run_next_test();
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -700,17 +700,17 @@ SimpleTest.requestFlakyTimeout = functio
 SimpleTest._pendingWaitForFocusCount = 0;
 
 /**
  * Version of waitForFocus that returns a promise. The Promise will
  * not resolve to the focused window, as it might be a CPOW (and Promises
  * cannot be resolved with CPOWs). If you require the focused window,
  * you should use waitForFocus instead.
  */
-SimpleTest.promiseFocus = function *(targetWindow, expectBlankPage)
+SimpleTest.promiseFocus = function (targetWindow, expectBlankPage)
 {
     return new Promise(function (resolve, reject) {
         SimpleTest.waitForFocus(win => {
             // Just resolve, without passing the window (see bug 1233497)
             resolve();
         }, targetWindow, expectBlankPage);
     });
 }
--- a/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js
+++ b/toolkit/components/asyncshutdown/tests/xpcshell/test_AsyncShutdown_leave_uncaught.js
@@ -2,18 +2,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 "use strict";
 
 //
 // This file contains tests that need to leave uncaught asynchronous
 // errors. If your test catches all its asynchronous errors, please
 // put it in another file.
 //
-
-Promise.Debugging.clearUncaughtErrorObservers();
+Cu.import("resource://testing-common/PromiseTestUtils.jsm");
+PromiseTestUtils.thisTestLeaksUncaughtRejectionsAndShouldBeFixed();
 
 function run_test() {
   run_next_test();
 }
 
 add_task(async function test_phase_simple_async() {
   do_print("Testing various combinations of a phase with a single condition");
   for (let kind of ["phase", "barrier", "xpcom-barrier", "xpcom-barrier-unwrapped"]) {
--- a/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
+++ b/toolkit/components/contentprefs/tests/mochitest/test_remoteContentPrefs.html
@@ -207,18 +207,17 @@
           addMessageListener("testRemoteContentPrefs:prefResults",
                              (msg) => { resolve(msg.data.results); });
         });
         tester.is(results.length, 0, "should not have seen the pb pref");
       }
 
       var tests = { test1, test2, test3, test4 };
       function testHandler(mm, testName) {
-        let test = tests[testName];
-        (test(mm))().then(() => {
+        tests[testName](mm).then(() => {
           mm.sendAsyncMessage(`testRemoteContentPrefs:${testName}Finished`, {});
         }).catch((e) => {
           mm.sendAsyncMessage("testRemoteContentPrefs:fail", { reason: e });
         });
       }
 
       for (let test of Object.getOwnPropertyNames(tests)) {
         addMessageListener(`testRemoteContentPrefs:${test}`, function(message) {
--- a/toolkit/components/formautofill/test/chrome/loader.js
+++ b/toolkit/components/formautofill/test/chrome/loader.js
@@ -68,17 +68,17 @@ var add_task_in_child_process = add_task
 
 window.addEventListener("load", function() {
   (async function() {
     try {
       for (let [taskFn, taskType, taskId] of gTestTasks) {
         if (taskType == "content") {
           // This is a normal task executed in the current process.
           info("Running " + taskFn.name);
-          await (taskFn)();
+          await taskFn();
         } else {
           // This is a task executed in the parent process.
           info("Running task in parent process: " + taskFn.name);
           let promiseFinished = new Promise(function(resolve) {
             parentScript.addMessageListener("finish_task_" + taskId, resolve);
           });
           parentScript.sendAsyncMessage("start_task_" + taskId);
           await promiseFinished;
--- a/toolkit/components/formautofill/test/chrome/loader_parent.js
+++ b/toolkit/components/formautofill/test/chrome/loader_parent.js
@@ -42,17 +42,17 @@ var Assert = {
 // Define task registration functions, see description in "loader_common.js".
 function add_task_in_parent_process(taskFn, taskIdOverride) {
   let taskId = taskIdOverride || getTaskId(Components.stack.caller);
   Output.print("Registering in the parent process: " + taskId);
   addMessageListener("start_task_" + taskId, function() {
     (async function() {
       try {
         Output.print("Running in the parent process " + taskId);
-        await (taskFn)();
+        await taskFn();
       } catch (ex) {
         assert.ok(false, ex);
       }
 
       sendAsyncMessage("finish_task_" + taskId, {});
     })();
   });
 }
--- a/toolkit/components/formautofill/test/loader_common.js
+++ b/toolkit/components/formautofill/test/loader_common.js
@@ -80,17 +80,17 @@ var gTerminationTasks = [];
  *
  * Even xpcshell doesn't support calling "add_task" in the "tail.js" file,
  * because it registers the task but does not wait for its termination,
  * potentially leading to intermittent failures in subsequent tests.
  */
 async function terminationTaskFn() {
   for (let taskFn of gTerminationTasks) {
     try {
-      await (taskFn)();
+      await taskFn();
     } catch (ex) {
       Output.print(ex);
       Assert.ok(false);
     }
   }
 }
 
 function add_termination_task(taskFn) {
--- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
+++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ -180,17 +180,17 @@ var test_stat = maketest("stat", functio
     }
   })();
 });
 
 /**
  * Test feature detection using OS.File.Info.prototype on main thread
  */
 var test_info_features_detect = maketest("features_detect", function features_detect(test) {
-  return (function() {
+  return (async function() {
     if (OS.Constants.Win) {
       // see if winBirthDate is defined
       if ("winBirthDate" in OS.File.Info.prototype) {
         test.ok(true, "winBirthDate is defined");
       } else {
         test.fail("winBirthDate not defined though we are under Windows");
       }
     } else if (OS.Constants.libc) {
--- a/toolkit/components/osfile/tests/xpcshell/head.js
+++ b/toolkit/components/osfile/tests/xpcshell/head.js
@@ -26,22 +26,22 @@ Services.prefs.setBoolPref("toolkit.osfi
 /**
  * As add_task, but execute the test both with native operations and
  * without.
  */
 function add_test_pair(generator) {
   add_task(async function() {
     do_print("Executing test " + generator.name + " with native operations");
     Services.prefs.setBoolPref("toolkit.osfile.native", true);
-    return (generator)();
+    return generator();
   });
   add_task(async function() {
     do_print("Executing test " + generator.name + " without native operations");
     Services.prefs.setBoolPref("toolkit.osfile.native", false);
-    return (generator)();
+    return generator();
   });
 }
 
 /**
  * Fetch asynchronously the contents of a file using xpcom.
  *
  * Used for comparing xpcom-based results to os.file-based results.
  *
--- a/toolkit/components/passwordmgr/test/pwmgr_common.js
+++ b/toolkit/components/passwordmgr/test/pwmgr_common.js
@@ -401,26 +401,30 @@ if (this.addMessageListener) {
     if (AppConstants.platform == "android") {
       LoginManagerParent.init();
     }
 
     commonInit(selfFilling);
     sendAsyncMessage("doneSetup");
   });
 
-  addMessageListener("loadRecipes", async function(recipes) {
-    var recipeParent = await LoginManagerParent.recipeParentPromise;
-    await recipeParent.load(recipes);
-    sendAsyncMessage("loadedRecipes", recipes);
+  addMessageListener("loadRecipes", function(recipes) {
+    (async function() {
+      var recipeParent = await LoginManagerParent.recipeParentPromise;
+      await recipeParent.load(recipes);
+      sendAsyncMessage("loadedRecipes", recipes);
+    })();
   });
 
-  addMessageListener("resetRecipes", async function() {
-    let recipeParent = await LoginManagerParent.recipeParentPromise;
-    await recipeParent.reset();
-    sendAsyncMessage("recipesReset");
+  addMessageListener("resetRecipes", function() {
+    (async function() {
+      let recipeParent = await LoginManagerParent.recipeParentPromise;
+      await recipeParent.reset();
+      sendAsyncMessage("recipesReset");
+    })();
   });
 
   addMessageListener("proxyLoginManager", msg => {
     // Recreate nsILoginInfo objects from vanilla JS objects.
     let recreatedArgs = msg.args.map((arg, index) => {
       if (msg.loginInfoIndices.includes(index)) {
         return LoginHelper.vanillaObjectToLogin(arg);
       }
--- a/toolkit/components/places/PlacesTransactions.jsm
+++ b/toolkit/components/places/PlacesTransactions.jsm
@@ -534,17 +534,17 @@ var TransactionsManager = {
 
   batch(aTask) {
     return this._mainEnqueuer.enqueue(async () => {
       this._batching = true;
       this._createdBatchEntry = false;
       let rv;
       try {
         // We should return here, but bug 958949 makes that impossible.
-        rv = (await (aTask)());
+        rv = await aTask();
       } finally {
         this._batching = false;
         this._createdBatchEntry = false;
       }
       return rv;
     });
   },
 
--- a/toolkit/components/places/tests/unit/test_async_transactions.js
+++ b/toolkit/components/places/tests/unit/test_async_transactions.js
@@ -1363,19 +1363,19 @@ add_task(async function test_sort_folder
   let originalOrder = [...preSep, sep, ...postSep];
   let sortedOrder = [...preSep.slice(0).reverse(),
                      sep,
                      ...postSep.slice(0).reverse()];
   await PT.batch(async function() {
     folder_info.guid = await PT.NewFolder(folder_info).transact();
     for (let info of originalOrder) {
       info.parentGuid = folder_info.guid;
-      info.guid = await info == sep ?
+      info.guid = await (info == sep ?
                     PT.NewSeparator(info).transact() :
-                    PT.NewBookmark(info).transact();
+                    PT.NewBookmark(info).transact());
     }
   });
 
   let folderId = await PlacesUtils.promiseItemId(folder_info.guid);
   let folderContainer = PlacesUtils.getFolderContents(folderId).root;
   function ensureOrder(aOrder) {
     for (let i = 0; i < folderContainer.childCount; i++) {
       do_check_eq(folderContainer.getChild(i).bookmarkGuid, aOrder[i].guid);
--- a/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js
+++ b/toolkit/components/places/tests/unit/test_promiseBookmarksTree.js
@@ -129,17 +129,22 @@ async function compareToNode(aItem, aNod
       compare_prop("uri");
       // node.tags's format is "a, b" whilst promiseBoookmarksTree is "a,b"
       if (aNode.tags === null)
         check_unset("tags");
       else
         compare_prop_to_value("tags", aNode.tags.replace(/, /g, ","), false);
 
       if (aNode.icon) {
-        compareFavicons(aNode.icon, aItem.iconuri);
+        try {
+          await compareFavicons(aNode.icon, aItem.iconuri);
+        } catch (ex) {
+          do_print(ex);
+          todo_check_true(false);
+        }
       } else {
         check_unset(aItem.iconuri);
       }
 
       check_unset(...FOLDER_ONLY_PROPS);
 
       let itemURI = uri(aNode.uri);
       compare_prop_to_value("charset",
--- a/toolkit/components/satchel/test/browser/browser_privbrowsing_perwindowpb.js
+++ b/toolkit/components/satchel/test/browser/browser_privbrowsing_perwindowpb.js
@@ -44,20 +44,16 @@ add_task(async function test() {
   }
 
   function testOnWindow(aOptions, aCallback) {
     return BrowserTestUtils.openNewBrowserWindow(aOptions)
                            .then(win => { windowsToClose.push(win); return win; });
   }
 
 
-  await testOnWindow({private: true}).then((aWin) => {
-    return (doTest(false, aWin))();
-  });
+  await testOnWindow({private: true}).then(aWin => doTest(false, aWin));
 
   // Test when not on private mode after visiting a site on private
   // mode. The form history should not exist.
-  await testOnWindow({}).then((aWin) => {
-    return (doTest(true, aWin))();
-  });
+  await testOnWindow({}).then(aWin => doTest(true, aWin));
 
   await Promise.all(windowsToClose.map(win => BrowserTestUtils.closeWindow(win)));
 });
--- a/toolkit/components/thumbnails/BackgroundPageThumbs.jsm
+++ b/toolkit/components/thumbnails/BackgroundPageThumbs.jsm
@@ -100,32 +100,38 @@ const BackgroundPageThumbs = {
     let exists = await PageThumbsStorage.fileExistsForURL(url);
     if (exists) {
       if (options.onDone) {
         options.onDone(url);
       }
       return url;
     }
     let thumbPromise = new Promise((resolve, reject) => {
-      function observe(subject, topic, data) { // jshint ignore:line
-        if (data === url) {
-          switch (topic) {
-            case "page-thumbnail:create":
-              resolve();
-              break;
-            case "page-thumbnail:error":
-              reject(new Error("page-thumbnail:error"));
-              break;
+      let observer = {
+        observe(subject, topic, data) { // jshint ignore:line
+          if (data === url) {
+            switch (topic) {
+              case "page-thumbnail:create":
+                resolve();
+                break;
+              case "page-thumbnail:error":
+                reject(new Error("page-thumbnail:error"));
+                break;
+            }
+            Services.obs.removeObserver(observer, "page-thumbnail:create");
+            Services.obs.removeObserver(observer, "page-thumbnail:error");
           }
-          Services.obs.removeObserver(observe, "page-thumbnail:create");
-          Services.obs.removeObserver(observe, "page-thumbnail:error");
-        }
-      }
-      Services.obs.addObserver(observe, "page-thumbnail:create");
-      Services.obs.addObserver(observe, "page-thumbnail:error");
+        },
+        QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                               Ci.nsISupportsWeakReference])
+      };
+      // Use weak references to avoid leaking in tests where the promise we
+      // return is GC'ed before it has resolved.
+      Services.obs.addObserver(observer, "page-thumbnail:create", true);
+      Services.obs.addObserver(observer, "page-thumbnail:error", true);
     });
     try {
       this.capture(url, options);
       await thumbPromise;
     } catch (err) {
       if (options.onDone) {
         options.onDone(url);
       }
--- a/toolkit/modules/DeferredTask.jsm
+++ b/toolkit/modules/DeferredTask.jsm
@@ -267,29 +267,29 @@ this.DeferredTask.prototype = {
     // means that the assignment of "this._runningPromise" must complete before
     // the task gets a chance to start.
     this._timer = null;
     this._armed = false;
     this._runningPromise = runningDeferred.promise;
 
     runningDeferred.resolve((async () => {
       // Execute the provided function asynchronously.
-      await (this._taskFn)().then(null, Cu.reportError);
+      await (this._taskFn() || Promise.resolve()).then(null, Cu.reportError);
 
       // Now that the task has finished, we check the state of the object to
       // determine if we should restart the task again.
       if (this._armed) {
         if (!this._finalized) {
           this._startTimer();
         } else {
           // Execute the task again immediately, for the last time.  The isArmed
           // property should return false while the task is running, and should
           // remain false after the last execution terminates.
           this._armed = false;
-          await (this._taskFn)().then(null, Cu.reportError);
+          await (this._taskFn() || Promise.resolve()).then(null, Cu.reportError);
         }
       }
 
       // 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));
   },
--- a/toolkit/modules/Sqlite.jsm
+++ b/toolkit/modules/Sqlite.jsm
@@ -21,16 +21,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+                                  "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService",
                                    "@mozilla.org/toolkit/finalizationwitness;1",
                                    "nsIFinalizationWitnessService");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "console",
                                   "resource://gre/modules/Console.jsm");
 
@@ -583,17 +585,19 @@ ConnectionData.prototype = Object.freeze
             } else {
               this._log.warn("A transaction was already in progress, likely a nested transaction", ex);
               throw ex;
             }
           }
 
           let result;
           try {
-            result = await (func)();
+            // Keep Task.spawn here to preserve API compat; unfortunately
+            // func was a generator rather than a task here.
+            result = await Task.spawn(func);
           } catch (ex) {
             // It's possible that the exception has been caused by trying to
             // close the connection in the middle of a transaction.
             if (this._closeRequested) {
               this._log.warn("Connection closed while performing a transaction", ex);
             } else {
               this._log.warn("Error during transaction. Rolling back", ex);
               // If we began a transaction, we must rollback it.
--- a/toolkit/modules/tests/xpcshell/test_Log.js
+++ b/toolkit/modules/tests/xpcshell/test_Log.js
@@ -558,30 +558,31 @@ add_task(async function log_message_with
   for (let msg of appender.messages) {
     do_check_true(msg.params === testParams);
     do_check_true(msg.message.startsWith("Test "));
   }
 });
 
 /*
  * Check that we format JS Errors reasonably.
+ * This needs to stay a generator to exercise Task.jsm's stack rewriting.
  */
-add_task(async function format_errors() {
+add_task(function *format_errors() {
   let pFormat = new Log.ParameterFormatter();
 
   // Test that subclasses of Error are recognized as errors.
   let err = new ReferenceError("Ref Error", "ERROR_FILE", 28);
   let str = pFormat.format(err);
   do_check_true(str.includes("ReferenceError"));
   do_check_true(str.includes("ERROR_FILE:28"));
   do_check_true(str.includes("Ref Error"));
 
   // Test that JS-generated Errors are recognized and formatted.
   try {
-    await Promise.resolve();  // Scrambles the stack
+    yield Promise.resolve();  // Scrambles the stack
     // eslint-disable-next-line no-eval
     eval("javascript syntax error");
   } catch (e) {
     str = pFormat.format(e);
     do_check_true(str.includes("SyntaxError: missing ;"));
     // Make sure we identified it as an Error and formatted the error location as
     // lineNumber:columnNumber.
     do_check_true(str.includes(":1:11)"));
--- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js
@@ -138,44 +138,32 @@ add_task(async function testActiveExperi
   Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
 
   await gCategoryUtilities.openType("experiment");
   let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
   is_element_visible(el, "Experiment info is visible on experiment tab.");
 });
 
 add_task(async function testExperimentLearnMore() {
-  // Actual URL is irrelevant.
-  Services.prefs.setCharPref("toolkit.telemetry.infoURL",
-                             "http://mochi.test:8888/server.js");
-
   await gCategoryUtilities.openType("experiment");
   let btn = gManagerWindow.document.getElementById("experiments-learn-more");
 
   is_element_visible(btn, "Learn more button visible.");
 
-  let deferred = Promise.defer();
-  window.addEventListener("DOMContentLoaded", function onLoad(event) {
-    info("Telemetry privacy policy window opened.");
-    window.removeEventListener("DOMContentLoaded", onLoad);
-
-    let browser = gBrowser.selectedBrowser;
-    let expected = Services.prefs.getCharPref("toolkit.telemetry.infoURL");
-    Assert.equal(browser.currentURI.spec, expected, "New tab should have loaded privacy policy.");
-    browser.contentWindow.close();
-
-    Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
-
-    deferred.resolve();
-  });
+  // Actual URL is irrelevant.
+  let expected = "http://mochi.test:8888/server.js";
+  Services.prefs.setCharPref("toolkit.telemetry.infoURL", expected);
 
   info("Opening telemetry privacy policy.");
+  let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, expected);
   EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
+  await loadPromise;
 
-  await deferred.promise;
+  Services.prefs.clearUserPref("toolkit.telemetry.infoURL");
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
 });
 
 add_task(async function testOpenPreferences() {
   await gCategoryUtilities.openType("experiment");
   let btn = gManagerWindow.document.getElementById("experiments-change-telemetry");
 
   is_element_visible(btn, "Change telemetry button visible in in-content UI.");
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_gmpProvider.js
@@ -62,22 +62,25 @@ function run_test() {
   gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0);
   gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true);
   for (let addon of gMockAddons.values()) {
     gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id),
                        true);
     gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id),
                        true);
   }
-  GMPScope.GMPProvider.shutdown();
-  GMPScope.GMPProvider.startup();
 
   run_next_test();
 }
 
+add_task(async function init() {
+  await GMPScope.GMPProvider.shutdown();
+  GMPScope.GMPProvider.startup();
+});
+
 add_task(async function test_notInstalled() {
   for (let addon of gMockAddons.values()) {
     gPrefs.setCharPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id), "");
     gPrefs.setBoolPref(gGetKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id), false);
   }
 
   let addons = await promiseAddonsByIDs([...gMockAddons.keys()]);
   Assert.equal(addons.length, gMockAddons.size);
@@ -190,27 +193,27 @@ add_task(async function test_enable() {
   }
 });
 
 add_task(async function test_globalEmeDisabled() {
   let addons = await promiseAddonsByIDs([...gMockEmeAddons.keys()]);
   Assert.equal(addons.length, gMockEmeAddons.size);
 
   gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, false);
-  GMPScope.GMPProvider.shutdown();
+  await GMPScope.GMPProvider.shutdown();
   GMPScope.GMPProvider.startup();
   for (let addon of addons) {
     Assert.ok(!addon.isActive);
     Assert.ok(addon.appDisabled);
     Assert.ok(!addon.userDisabled);
 
     Assert.equal(addon.permissions, 0);
   }
   gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true);
-  GMPScope.GMPProvider.shutdown();
+  await GMPScope.GMPProvider.shutdown();
   GMPScope.GMPProvider.startup();
 });
 
 add_task(async function test_autoUpdatePrefPersistance() {
   let addons = await promiseAddonsByIDs([...gMockAddons.keys()]);
   Assert.equal(addons.length, gMockAddons.size);
 
   for (let addon of addons) {