Bug 1437295 - Promise-ify some of the paint/flushing methods. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Sat, 10 Mar 2018 23:26:27 -0500
changeset 765927 d54313f163a7ef36f922fef0e96c0a94a3d9414d
parent 765246 f1965cf7425fe422c9e9c78018f11b97e0a0f229
child 765928 a5dc6dd28c3d376426152e4b127c08237175d2ce
push id102181
push userkgupta@mozilla.com
push dateSun, 11 Mar 2018 04:27:20 +0000
reviewersbotond
bugs1437295
milestone60.0a1
Bug 1437295 - Promise-ify some of the paint/flushing methods. r?botond This is functionally a no-op but it makes code cleaner, particularly some of the changes in a future patch. MozReview-Commit-ID: 5UoT3aNJaPz
gfx/layers/apz/test/mochitest/apz_test_utils.js
testing/mochitest/tests/SimpleTest/paint_listener.js
--- a/gfx/layers/apz/test/mochitest/apz_test_utils.js
+++ b/gfx/layers/apz/test/mochitest/apz_test_utils.js
@@ -110,54 +110,62 @@ function isLayerized(elementId) {
       if (paint[scrollId]["contentDescription"].includes(elementId)) {
         return true;
       }
     }
   }
   return false;
 }
 
+function promiseApzRepaintsFlushed(aWindow = window) {
+  return new Promise(function (resolve, reject) {
+    var repaintDone = function() {
+      SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed");
+      setTimeout(resolve, 0);
+    };
+    SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
+    if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
+      dump("Flushed APZ repaints, waiting for callback...\n");
+    } else {
+      dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
+      repaintDone();
+    }
+  });
+}
+
 function flushApzRepaints(aCallback, aWindow = window) {
   if (!aCallback) {
     throw "A callback must be provided!";
   }
-  var repaintDone = function() {
-    SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed");
-    setTimeout(aCallback, 0);
-  };
-  SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
-  if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
-    dump("Flushed APZ repaints, waiting for callback...\n");
-  } else {
-    dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
-    repaintDone();
-  }
+  promiseApzRepaintsFlushed(aWindow).then(aCallback);
 }
 
 // Flush repaints, APZ pending repaints, and any repaints resulting from that
 // flush. This is particularly useful if the test needs to reach some sort of
-// "idle" state in terms of repaints. Usually just doing waitForAllPaints
+// "idle" state in terms of repaints. Usually just waiting for all paints
 // followed by flushApzRepaints is sufficient to flush all APZ state back to
 // the main thread, but it can leave a paint scheduled which will get triggered
 // at some later time. For tests that specifically test for painting at
 // specific times, this method is the way to go. Even if in doubt, this is the
 // preferred method as the extra step is "safe" and shouldn't interfere with
 // most tests.
 function waitForApzFlushedRepaints(aCallback) {
   // First flush the main-thread paints and send transactions to the APZ
-  waitForAllPaints(function() {
+  promiseAllPaintsDone()
     // Then flush the APZ to make sure any repaint requests have been sent
-    // back to the main thread
-    flushApzRepaints(function() {
-      // Then flush the main-thread again to process the repaint requests.
-      // Once this is done, we should be in a stable state with nothing
-      // pending, so we can trigger the callback.
-      waitForAllPaints(aCallback);
-    });
-  });
+    // back to the main thread. Note that we need a wrapper function around
+    // promiseApzRepaintsFlushed otherwise the rect produced by
+    // promiseAllPaintsDone gets passed to it as the window parameter.
+    .then(() => promiseApzRepaintsFlushed())
+    // Then flush the main-thread again to process the repaint requests.
+    // Once this is done, we should be in a stable state with nothing
+    // pending, so we can trigger the callback.
+    .then(promiseAllPaintsDone)
+    // Then allow the callback to be triggered.
+    .then(aCallback);
 }
 
 // This function takes a set of subtests to run one at a time in new top-level
 // windows, and returns a Promise that is resolved once all the subtests are
 // done running.
 //
 // The aSubtests array is an array of objects with the following keys:
 //   file: required, the filename of the subtest.
@@ -262,24 +270,20 @@ function runSubtestsSeriallyInFreshWindo
     advanceSubtestExecution();
   });
 }
 
 function pushPrefs(prefs) {
   return SpecialPowers.pushPrefEnv({'set': prefs});
 }
 
-function waitUntilApzStable() {
-  return new Promise(function(resolve, reject) {
-    SimpleTest.waitForFocus(function() {
-      waitForAllPaints(function() {
-        flushApzRepaints(resolve);
-      });
-    }, window);
-  });
+async function waitUntilApzStable() {
+  await SimpleTest.promiseFocus(window);
+  await promiseAllPaintsDone();
+  await promiseApzRepaintsFlushed();
 }
 
 function isApzEnabled() {
   var enabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
   if (!enabled) {
     // All tests are required to have at least one assertion. Since APZ is
     // disabled, and the main test is presumably not going to run, we stick in
     // a dummy assertion here to keep the test passing.
--- a/testing/mochitest/tests/SimpleTest/paint_listener.js
+++ b/testing/mochitest/tests/SimpleTest/paint_listener.js
@@ -79,9 +79,18 @@
 
   window.waitForAllPaintsFlushed = function(callback, subdoc) {
     waitForPaints(callback, subdoc, FlushModes.FLUSH);
   };
 
   window.waitForAllPaints = function(callback) {
     waitForPaints(callback, null, FlushModes.NOFLUSH);
   };
+
+  window.promiseAllPaintsDone = function(subdoc = null, flush = false) {
+    var flushmode = flush ? FlushModes.FLUSH : FlushModes.NOFLUSH;
+    return new Promise(function (resolve, reject) {
+      // The callback is given the components of the rect, but resolve() can
+      // only be given one arg, so we turn it back into an array.
+      waitForPaints((l, r, t, b) => resolve([l, r, t, b]), subdoc, flushmode);
+    });
+  }
 })();