bug 1490333: marionette: move whenIdle to sync module; r=whimboo

This patch moves the private whenIdle function to sync so it can
be shared across JSMs.

It also changes its semantics somewhat, so that instead of taking
a callback function (suitable for DOM event callbacks) it returns
a promise that is resolved when the main thread becomes idle and
the window has completed an animation frame tick.
This commit is contained in:
Andreas Tolfsen 2018-09-11 16:49:18 +01:00
Родитель 70bcf9dfa6
Коммит 1e9bb7ecbc
3 изменённых файлов: 45 добавлений и 29 удалений

Просмотреть файл

@ -58,6 +58,7 @@ const {MarionettePrefs} = ChromeUtils.import("chrome://marionette/content/prefs.
ChromeUtils.import("chrome://marionette/content/proxy.js"); ChromeUtils.import("chrome://marionette/content/proxy.js");
ChromeUtils.import("chrome://marionette/content/reftest.js"); ChromeUtils.import("chrome://marionette/content/reftest.js");
const { const {
IdlePromise,
PollPromise, PollPromise,
TimedPromise, TimedPromise,
} = ChromeUtils.import("chrome://marionette/content/sync.js", {}); } = ChromeUtils.import("chrome://marionette/content/sync.js", {});
@ -1445,10 +1446,11 @@ GeckoDriver.prototype.setWindowRect = async function(cmd) {
// Synchronous resize to |width| and |height| dimensions. // Synchronous resize to |width| and |height| dimensions.
async function resizeWindow(width, height) { async function resizeWindow(width, height) {
return new Promise(resolve => { await new Promise(resolve => {
win.addEventListener("resize", whenIdle(win, resolve), {once: true}); win.addEventListener("resize", resolve, {once: true});
win.resizeTo(width, height); win.resizeTo(width, height);
}); });
await new IdlePromise(win);
} }
// Wait until window size has changed. We can't wait for the // Wait until window size has changed. We can't wait for the
@ -3142,10 +3144,11 @@ GeckoDriver.prototype.dismissDialog = async function() {
this._checkIfAlertIsPresent(); this._checkIfAlertIsPresent();
await new Promise(resolve => { await new Promise(resolve => {
win.addEventListener("DOMModalDialogClosed", whenIdle(win, () => { win.addEventListener("DOMModalDialogClosed", async () => {
await new IdlePromise(win);
this.dialog = null; this.dialog = null;
resolve(); resolve();
}), {once: true}); }, {once: true});
let {button0, button1} = this.dialog.ui; let {button0, button1} = this.dialog.ui;
(button1 ? button1 : button0).click(); (button1 ? button1 : button0).click();
@ -3161,10 +3164,11 @@ GeckoDriver.prototype.acceptDialog = async function() {
this._checkIfAlertIsPresent(); this._checkIfAlertIsPresent();
await new Promise(resolve => { await new Promise(resolve => {
win.addEventListener("DOMModalDialogClosed", whenIdle(win, () => { win.addEventListener("DOMModalDialogClosed", async () => {
await new IdlePromise(win);
this.dialog = null; this.dialog = null;
resolve(); resolve();
}), {once: true}); }, {once: true});
let {button0} = this.dialog.ui; let {button0} = this.dialog.ui;
button0.click(); button0.click();
@ -3648,16 +3652,17 @@ function getOuterWindowId(win) {
} }
/** /**
* Exit fullscreen and wait for <var>window</var> to resize. * Exit fullscreen and wait for `window` to resize.
* *
* @param {ChromeWindow} window * @param {ChromeWindow} window
* Window to exit fullscreen. * Window to exit fullscreen.
*/ */
async function exitFullscreen(window) { async function exitFullscreen(window) {
return new Promise(resolve => { await new Promise(resolve => {
window.addEventListener("sizemodechange", whenIdle(window, resolve), {once: true}); window.addEventListener("sizemodechange", () => resolve(), {once: true});
window.fullScreen = false; window.fullScreen = false;
}); });
await new IdlePromise(window);
} }
/** /**
@ -3674,23 +3679,3 @@ async function restoreWindow(chromeWindow, contentWindow) {
chromeWindow.restore(); chromeWindow.restore();
}); });
} }
/**
* Throttle <var>callback</var> until the main thread is idle and
* <var>window</var> has performed an animation frame.
*
* @param {ChromeWindow} window
* Window to request the animation frame from.
* @param {function()} callback
* Called when done.
*
* @return {function()}
* Anonymous function that when invoked will wait for the main
* thread to clear up and request an animation frame before calling
* <var>callback</var>.
*/
function whenIdle(window, callback) {
return () => Services.tm.idleDispatchToMainThread(() => {
window.requestAnimationFrame(callback);
});
}

Просмотреть файл

@ -16,6 +16,7 @@ const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
XPCOMUtils.defineLazyGetter(this, "logger", Log.get); XPCOMUtils.defineLazyGetter(this, "logger", Log.get);
this.EXPORTED_SYMBOLS = [ this.EXPORTED_SYMBOLS = [
"IdlePromise",
"MessageManagerDestroyedPromise", "MessageManagerDestroyedPromise",
"PollPromise", "PollPromise",
"Sleep", "Sleep",
@ -265,3 +266,20 @@ function MessageManagerDestroyedPromise(messageManager) {
Services.obs.addObserver(observe, "message-manager-disconnect"); Services.obs.addObserver(observe, "message-manager-disconnect");
}); });
} }
/**
* Throttle until the main thread is idle and `window` has performed
* an animation frame (in that order).
*
* @param {ChromeWindow} window
* Window to request the animation frame from.
*
* @return Promise
*/
function IdlePromise(window) {
return new Promise(resolve => {
Services.tm.idleDispatchToMainThread(() => {
window.requestAnimationFrame(resolve);
});
});
}

Просмотреть файл

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
const { const {
IdlePromise,
PollPromise, PollPromise,
Sleep, Sleep,
TimedPromise, TimedPromise,
@ -141,3 +142,15 @@ add_task(async function test_Sleep() {
Assert.throws(() => new Sleep(1.2), /RangeError/); Assert.throws(() => new Sleep(1.2), /RangeError/);
Assert.throws(() => new Sleep(-1), /RangeError/); Assert.throws(() => new Sleep(-1), /RangeError/);
}); });
add_task(async function test_IdlePromise() {
let called = false;
let window = {
requestAnimationFrame(callback) {
called = true;
callback();
}
};
await IdlePromise(window);
ok(called);
});