Bug 1404946 - Rename wait.until to PollPromise. r?whimboo
In formalising our synchronisation module, this renames wait.until
to PollPromise. It is a specialisation of a promise, just like
TimedPromise, that poll-waits a condition for a given amount of time
before either resolving (passing) or rejecting (failing) the poll-wait.
Also fix and improve documentation.
MozReview-Commit-ID: AcP3C1qCgKA
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -42,17 +42,20 @@ Cu.import("chrome://marionette/content/e
Cu.import("chrome://marionette/content/event.js");
Cu.import("chrome://marionette/content/interaction.js");
Cu.import("chrome://marionette/content/l10n.js");
Cu.import("chrome://marionette/content/legacyaction.js");
Cu.import("chrome://marionette/content/modal.js");
Cu.import("chrome://marionette/content/proxy.js");
Cu.import("chrome://marionette/content/reftest.js");
Cu.import("chrome://marionette/content/session.js");
-const {wait, TimedPromise} = Cu.import("chrome://marionette/content/sync.js", {});
+const {
+ PollPromise,
+ TimedPromise,
+} = Cu.import("chrome://marionette/content/sync.js", {});
Cu.importGlobalProperties(["URL"]);
this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];
const FRAME_SCRIPT = "chrome://marionette/content/listener.js";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -1483,30 +1486,30 @@ GeckoDriver.prototype.setWindowRect = as
win.resizeTo(width, height);
});
}
// Wait until window size has changed. We can't wait for the
// user-requested window size as this may not be achievable on the
// current system.
const windowResizeChange = async () => {
- return wait.until((resolve, reject) => {
+ return new PollPromise((resolve, reject) => {
let curRect = this.curBrowser.rect;
if (curRect.width != origRect.width &&
curRect.height != origRect.height) {
resolve();
} else {
reject();
}
});
};
// Wait for the window position to change.
async function windowPosition(x, y) {
- return wait.until((resolve, reject) => {
+ return new PollPromise((resolve, reject) => {
if ((x == win.screenX && y == win.screenY) ||
(win.screenX != origRect.x || win.screenY != origRect.y)) {
resolve();
} else {
reject();
}
});
}
@@ -3044,17 +3047,17 @@ GeckoDriver.prototype.maximizeWindow = a
const origSize = {
outerWidth: win.outerWidth,
outerHeight: win.outerHeight,
};
// Wait for the window size to change.
async function windowSizeChange() {
- return wait.until((resolve, reject) => {
+ return new PollPromise((resolve, reject) => {
let curSize = {
outerWidth: win.outerWidth,
outerHeight: win.outerHeight,
};
if (curSize.outerWidth != origSize.outerWidth ||
curSize.outerHeight != origSize.outerHeight) {
resolve();
} else {
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -10,17 +10,17 @@ const {classes: Cc, interfaces: Ci, util
Cu.import("chrome://marionette/content/assert.js");
Cu.import("chrome://marionette/content/atom.js");
const {
InvalidSelectorError,
NoSuchElementError,
pprint,
StaleElementReferenceError,
} = Cu.import("chrome://marionette/content/error.js", {});
-const {wait} = Cu.import("chrome://marionette/content/sync.js", {});
+const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
this.EXPORTED_SYMBOLS = ["element"];
const XMLNS = "http://www.w3.org/1999/xhtml";
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const uuidGen = Cc["@mozilla.org/uuid-generator;1"]
.getService(Ci.nsIUUIDGenerator);
@@ -244,17 +244,17 @@ element.find = function(container, strat
let searchFn;
if (opts.all) {
searchFn = findElements.bind(this);
} else {
searchFn = findElement.bind(this);
}
return new Promise((resolve, reject) => {
- let findElements = wait.until((resolve, reject) => {
+ let findElements = new PollPromise((resolve, reject) => {
let res = find_(container, strategy, selector, searchFn, opts);
if (res.length > 0) {
resolve(Array.from(res));
} else {
reject([]);
}
}, opts.timeout);
--- a/testing/marionette/sync.js
+++ b/testing/marionette/sync.js
@@ -6,25 +6,18 @@
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
const {
error,
TimeoutError,
} = Cu.import("chrome://marionette/content/error.js", {});
-/* exported TimedPromise */
-this.EXPORTED_SYMBOLS = ["wait", "TimedPromise"];
-
-/**
- * Poll-waiting utilities.
- *
- * @namespace
- */
-this.wait = {};
+/* exported PollPromise, TimedPromise */
+this.EXPORTED_SYMBOLS = ["PollPromise", "TimedPromise"];
const {TYPE_ONE_SHOT, TYPE_REPEATING_SLACK} = Ci.nsITimer;
/**
* @callback Condition
*
* @param {function(*)} resolve
* To be called when the condition has been met. Will return the
@@ -34,63 +27,67 @@ const {TYPE_ONE_SHOT, TYPE_REPEATING_SLA
* the condition to be revaluated or time out.
*
* @return {*}
* The value from calling <code>resolve</code>.
*/
/**
* Runs a promise-like function off the main thread until it is resolved
- * through |resolve| or |rejected| callbacks. The function is guaranteed
- * to be run at least once, irregardless of the timeout.
+ * through <code>resolve</code> or <code>rejected</code> callbacks.
+ * The function is guaranteed to be run at least once, irregardless of
+ * the timeout.
*
- * The |func| is evaluated every |interval| for as long as its runtime
- * duration does not exceed |interval|. Evaluations occur sequentially,
- * meaning that evaluations of |func| are queued if the runtime evaluation
- * duration of |func| is greater than |interval|.
+ * The <var>func</var> is evaluated every <var>interval</var> for as
+ * long as its runtime duration does not exceed <var>interval</var>.
+ * Evaluations occur sequentially, meaning that evaluations of
+ * <var>func</var> are queued if the runtime evaluation duration of
+ * <var>func</var> is greater than <var>interval</var>.
*
- * |func| is given two arguments, |resolve| and |reject|, of which one
- * must be called for the evaluation to complete. Calling |resolve| with
- * an argument indicates that the expected wait condition was met and
- * will return the passed value to the caller. Conversely, calling
- * |reject| will evaluate |func| again until the |timeout| duration has
- * elapsed or |func| throws. The passed value to |reject| will also be
+ * <var>func</var> is given two arguments, <code>resolve</code> and
+ * <code>reject</code>, of which one must be called for the evaluation
+ * to complete. Calling <code>resolve</code> with an argument
+ * indicates that the expected wait condition was met and will return
+ * the passed value to the caller. Conversely, calling
+ * <code>reject</code> will evaluate <var>func</var> again until
+ * the <var>timeout</var> duration has elapsed or <var>func</var>
+ * throws. The passed value to <code>reject</code> will also be
* returned to the caller once the wait has expired.
*
* Usage:
*
* <pre><code>
- * let els = wait.until((resolve, reject) => {
+ * let els = new PollPromise((resolve, reject) => {
* let res = document.querySelectorAll("p");
* if (res.length > 0) {
* resolve(Array.from(res));
* } else {
* reject([]);
* }
* });
* </pre></code>
*
* @param {Condition} func
* Function to run off the main thread.
- * @param {number=} timeout
- * Desired timeout. If 0 or less than the runtime evaluation time
- * of |func|, |func| is guaranteed to run at least once. The default
- * is 2000 milliseconds.
- * @param {number=} interval
- * Duration between each poll of |func| in milliseconds. Defaults to
- * 10 milliseconds.
+ * @param {number=} [timeout=2000] timeout
+ * Desired timeout. If 0 or less than the runtime evaluation
+ * time of <var>func</var>, <var>func</var> is guaranteed to run
+ * at least once. The default is 2000 milliseconds.
+ * @param {number=} [interval=10] interval
+ * Duration between each poll of <var>func</var> in milliseconds.
+ * Defaults to 10 milliseconds.
*
* @return {Promise.<*>}
- * Yields the value passed to |func|'s |resolve| or |reject|
- * callbacks.
+ * Yields the value passed to <var>func</var>'s
+ * <code>resolve</code> or <code>reject</code> callbacks.
*
* @throws {*}
- * If |func| throws, its error is propagated.
+ * If <var>func</var> throws, its error is propagated.
*/
-wait.until = function(func, timeout = 2000, interval = 10) {
+function PollPromise(func, timeout = 2000, interval = 10) {
const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
return new Promise((resolve, reject) => {
const start = new Date().getTime();
const end = start + timeout;
let evalFn = () => {
new Promise(func).then(resolve, rejected => {
@@ -114,17 +111,17 @@ wait.until = function(func, timeout = 20
}).then(res => {
timer.cancel();
return res;
}, err => {
timer.cancel();
throw err;
});
-};
+}
/**
* The <code>TimedPromise</code> object represents the timed, eventual
* completion (or failure) of an asynchronous operation, and its
* resulting value.
*
* In contrast to a regular {@link Promise}, it times out after
* <var>timeout</var>.
--- a/testing/marionette/test_sync.js
+++ b/testing/marionette/test_sync.js
@@ -1,76 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const {utils: Cu} = Components;
-Cu.import("chrome://marionette/content/sync.js");
+const {PollPromise} = Cu.import("chrome://marionette/content/sync.js", {});
const DEFAULT_TIMEOUT = 2000;
-add_task(async function test_until_types() {
+add_task(async function test_PollPromise_types() {
for (let typ of [true, false, "foo", 42, [], {}]) {
- strictEqual(typ, await wait.until(resolve => resolve(typ)));
+ strictEqual(typ, await new PollPromise(resolve => resolve(typ)));
}
});
-add_task(async function test_until_timeoutElapse() {
+add_task(async function test_PollPromise_timeoutElapse() {
let nevals = 0;
let start = new Date().getTime();
- await wait.until((resolve, reject) => {
+ await new PollPromise((resolve, reject) => {
++nevals;
reject();
});
let end = new Date().getTime();
greaterOrEqual((end - start), DEFAULT_TIMEOUT);
greaterOrEqual(nevals, 15);
});
-add_task(async function test_until_rethrowError() {
+add_task(async function test_PollPromise_rethrowError() {
let nevals = 0;
let err;
try {
- await wait.until(() => {
+ await PollPromise(() => {
++nevals;
throw new Error();
});
} catch (e) {
err = e;
}
equal(1, nevals);
ok(err instanceof Error);
});
-add_task(async function test_until_noTimeout() {
+add_task(async function test_PollPromise_noTimeout() {
// run at least once when timeout is 0
let nevals = 0;
let start = new Date().getTime();
- await wait.until((resolve, reject) => {
+ await new PollPromise((resolve, reject) => {
++nevals;
reject();
}, 0);
let end = new Date().getTime();
equal(1, nevals);
less((end - start), DEFAULT_TIMEOUT);
});
-add_task(async function test_until_timeout() {
+add_task(async function test_PollPromise_timeout() {
let nevals = 0;
let start = new Date().getTime();
- await wait.until((resolve, reject) => {
+ await new PollPromise((resolve, reject) => {
++nevals;
reject();
}, 100);
let end = new Date().getTime();
greater(nevals, 1);
greaterOrEqual((end - start), 100);
});
-add_task(async function test_until_interval() {
+add_task(async function test_PollPromise_interval() {
let nevals = 0;
- await wait.until((resolve, reject) => {
+ await new PollPromise((resolve, reject) => {
++nevals;
reject();
}, 100, 100);
equal(2, nevals);
});