Bug 1958325 - Move TimedPromise to remote/shared/Sync.sys.mjs r=webdriver-reviewers,jdescottes

We will use it in the BiDi module in the next commit.

Drop the unused TimedPromise import from telemetry test altogether.

Differential Revision: https://phabricator.services.mozilla.com/D247041
This commit is contained in:
Martin Pitt
2025-05-05 17:29:01 +00:00
committed by jdescottes@mozilla.com
parent 3939728961
commit 82e49344b2
9 changed files with 153 additions and 153 deletions

View File

@@ -18,10 +18,6 @@ const gTestRoot = getRootDirectory(gTestPath).replace(
"http://mochi.test:8888"
);
const { TimedPromise } = ChromeUtils.importESModule(
"chrome://remote/content/marionette/sync.sys.mjs"
);
async function run_test(count) {
const histogram = TelemetryTestUtils.getAndClearHistogram(
"FX_NUMBER_OF_UNIQUE_SITE_ORIGINS_ALL_TABS"

View File

@@ -46,7 +46,7 @@ what you need:
```javascript
const { TimedPromise } = ChromeUtils.importESModule(
"chrome://remote/content/marionette/sync.sys.mjs"
"chrome://remote/content/shared/Sync.sys.mjs"
);
```

View File

@@ -15,7 +15,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
event: "chrome://remote/content/shared/webdriver/Event.sys.mjs",
Log: "chrome://remote/content/shared/Log.sys.mjs",
pprint: "chrome://remote/content/shared/Format.sys.mjs",
TimedPromise: "chrome://remote/content/marionette/sync.sys.mjs",
TimedPromise: "chrome://remote/content/shared/Sync.sys.mjs",
});
ChromeUtils.defineLazyGetter(lazy, "logger", () =>

View File

@@ -12,7 +12,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
PageLoadStrategy:
"chrome://remote/content/shared/webdriver/Capabilities.sys.mjs",
ProgressListener: "chrome://remote/content/shared/Navigate.sys.mjs",
TimedPromise: "chrome://remote/content/marionette/sync.sys.mjs",
TimedPromise: "chrome://remote/content/shared/Sync.sys.mjs",
truncate: "chrome://remote/content/shared/Format.sys.mjs",
});

View File

@@ -2,8 +2,6 @@
* 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/. */
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
@@ -17,8 +15,6 @@ ChromeUtils.defineLazyGetter(lazy, "logger", () =>
const { TYPE_ONE_SHOT, TYPE_REPEATING_SLACK } = Ci.nsITimer;
const PROMISE_TIMEOUT = AppConstants.DEBUG ? 4500 : 1500;
/**
* Runs a Promise-like function off the main thread until it is resolved
* through ``resolve`` or ``rejected`` callbacks. The function is
@@ -135,93 +131,6 @@ export function PollPromise(func, { timeout = null, interval = 10 } = {}) {
);
}
/**
* Represents the timed, eventual completion (or failure) of an
* asynchronous operation, and its resulting value.
*
* In contrast to a regular Promise, it times out after ``timeout``.
*
* @param {Function} fn
* Function to run, which will have its ``reject``
* callback invoked after the ``timeout`` duration is reached.
* It is given two callbacks: ``resolve(value)`` and
* ``reject(error)``.
* @param {object=} options
* @param {string} options.errorMessage
* Message to use for the thrown error.
* @param {number=} options.timeout
* ``condition``'s ``reject`` callback will be called
* after this timeout, given in milliseconds.
* By default 1500 ms in an optimised build and 4500 ms in
* debug builds.
* @param {Error=} options.throws
* When the ``timeout`` is hit, this error class will be
* thrown. If it is null, no error is thrown and the promise is
* instead resolved on timeout with a TimeoutError.
*
* @returns {Promise.<*>}
* Timed promise.
*
* @throws {TypeError}
* If `timeout` is not a number.
* @throws {RangeError}
* If `timeout` is not an unsigned integer.
*/
export function TimedPromise(fn, options = {}) {
const {
errorMessage = "TimedPromise timed out",
timeout = PROMISE_TIMEOUT,
throws = lazy.error.TimeoutError,
} = options;
const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
if (typeof fn != "function") {
throw new TypeError();
}
if (typeof timeout != "number") {
throw new TypeError();
}
if (!Number.isInteger(timeout) || timeout < 0) {
throw new RangeError();
}
return new Promise((resolve, reject) => {
let trace;
// Reject only if |throws| is given. Otherwise it is assumed that
// the user is OK with the promise timing out.
let bail = () => {
const message = `${errorMessage} after ${timeout} ms`;
if (throws !== null) {
let err = new throws(message);
reject(err);
} else {
lazy.logger.warn(message, trace);
resolve();
}
};
trace = lazy.error.stack();
timer.initWithCallback({ notify: bail }, timeout, TYPE_ONE_SHOT);
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}).then(
res => {
timer.cancel();
return res;
},
err => {
timer.cancel();
throw err;
}
);
}
/**
* Pauses for the given duration.
*

View File

@@ -6,7 +6,6 @@ const {
DebounceCallback,
PollPromise,
Sleep,
TimedPromise,
waitForMessage,
waitForObserverTopic,
} = ChromeUtils.importESModule(
@@ -169,57 +168,6 @@ add_task(async function test_PollPromise_interval() {
equal(2, nevals);
});
add_task(function test_TimedPromise_funcTypes() {
for (let type of ["foo", 42, null, undefined, true, [], {}]) {
Assert.throws(() => new TimedPromise(type), /TypeError/);
}
new TimedPromise(resolve => resolve());
new TimedPromise(function (resolve) {
resolve();
});
});
add_task(function test_TimedPromise_timeoutTypes() {
for (let timeout of ["foo", null, true, [], {}]) {
Assert.throws(
() => new TimedPromise(resolve => resolve(), { timeout }),
/TypeError/
);
}
for (let timeout of [1.2, -1]) {
Assert.throws(
() => new TimedPromise(resolve => resolve(), { timeout }),
/RangeError/
);
}
new TimedPromise(resolve => resolve(), { timeout: 42 });
});
add_task(async function test_TimedPromise_errorMessage() {
try {
await new TimedPromise(() => {}, { timeout: 0 });
ok(false, "Expected Timeout error not raised");
} catch (e) {
ok(
e.message.includes("TimedPromise timed out after"),
"Expected default error message found"
);
}
try {
await new TimedPromise(() => {}, {
errorMessage: "Not found",
timeout: 0,
});
ok(false, "Expected Timeout error not raised");
} catch (e) {
ok(
e.message.includes("Not found after"),
"Expected custom error message found"
);
}
});
add_task(async function test_Sleep() {
await Sleep(0);
for (let type of ["foo", true, null, undefined]) {

View File

@@ -2,6 +2,8 @@
* 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/. */
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
@@ -11,6 +13,8 @@ ChromeUtils.defineESModuleGetters(lazy, {
const { TYPE_ONE_SHOT, TYPE_REPEATING_SLACK } = Ci.nsITimer;
const PROMISE_TIMEOUT = AppConstants.DEBUG ? 4500 : 1500;
ChromeUtils.defineLazyGetter(lazy, "logger", () =>
lazy.Log.get(lazy.Log.TYPES.REMOTE_AGENT)
);
@@ -334,3 +338,90 @@ export function PollPromise(func, options = {}) {
}
);
}
/**
* Represents the timed, eventual completion (or failure) of an
* asynchronous operation, and its resulting value.
*
* In contrast to a regular Promise, it times out after ``timeout``.
*
* @param {Function} fn
* Function to run, which will have its ``reject``
* callback invoked after the ``timeout`` duration is reached.
* It is given two callbacks: ``resolve(value)`` and
* ``reject(error)``.
* @param {object=} options
* @param {string} options.errorMessage
* Message to use for the thrown error.
* @param {number=} options.timeout
* ``condition``'s ``reject`` callback will be called
* after this timeout, given in milliseconds.
* By default 1500 ms in an optimised build and 4500 ms in
* debug builds.
* @param {Error=} options.throws
* When the ``timeout`` is hit, this error class will be
* thrown. If it is null, no error is thrown and the promise is
* instead resolved on timeout with a TimeoutError.
*
* @returns {Promise.<*>}
* Timed promise.
*
* @throws {TypeError}
* If `timeout` is not a number.
* @throws {RangeError}
* If `timeout` is not an unsigned integer.
*/
export function TimedPromise(fn, options = {}) {
const {
errorMessage = "TimedPromise timed out",
timeout = PROMISE_TIMEOUT,
throws = lazy.error.TimeoutError,
} = options;
const timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
if (typeof fn != "function") {
throw new TypeError();
}
if (typeof timeout != "number") {
throw new TypeError();
}
if (!Number.isInteger(timeout) || timeout < 0) {
throw new RangeError();
}
return new Promise((resolve, reject) => {
let trace;
// Reject only if |throws| is given. Otherwise it is assumed that
// the user is OK with the promise timing out.
let bail = () => {
const message = `${errorMessage} after ${timeout} ms`;
if (throws !== null) {
let err = new throws(message);
reject(err);
} else {
lazy.logger.warn(message, trace);
resolve();
}
};
trace = lazy.error.stack();
timer.initWithCallback({ notify: bail }, timeout, TYPE_ONE_SHOT);
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}).then(
res => {
timer.cancel();
return res;
},
err => {
timer.cancel();
throw err;
}
);
}

View File

@@ -15,7 +15,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
generateUUID: "chrome://remote/content/shared/UUID.sys.mjs",
Log: "chrome://remote/content/shared/Log.sys.mjs",
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
TimedPromise: "chrome://remote/content/marionette/sync.sys.mjs",
TimedPromise: "chrome://remote/content/shared/Sync.sys.mjs",
UserContextManager:
"chrome://remote/content/shared/UserContextManager.sys.mjs",
waitForObserverTopic: "chrome://remote/content/marionette/sync.sys.mjs",

View File

@@ -6,8 +6,13 @@ const { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
const { AnimationFramePromise, Deferred, EventPromise, PollPromise } =
ChromeUtils.importESModule("chrome://remote/content/shared/Sync.sys.mjs");
const {
AnimationFramePromise,
Deferred,
EventPromise,
PollPromise,
TimedPromise,
} = ChromeUtils.importESModule("chrome://remote/content/shared/Sync.sys.mjs");
const { Log } = ChromeUtils.importESModule(
"resource://gre/modules/Log.sys.mjs"
@@ -453,3 +458,54 @@ add_task(async function test_PollPromise_resolve() {
Assert.equal(appender.messages[0].level, Log.Level.Warn);
Assert.equal(appender.messages[0].message, "PollingFailed after 100 ms");
});
add_task(function test_TimedPromise_funcTypes() {
for (let type of ["foo", 42, null, undefined, true, [], {}]) {
Assert.throws(() => new TimedPromise(type), /TypeError/);
}
new TimedPromise(resolve => resolve());
new TimedPromise(function (resolve) {
resolve();
});
});
add_task(function test_TimedPromise_timeoutTypes() {
for (let timeout of ["foo", null, true, [], {}]) {
Assert.throws(
() => new TimedPromise(resolve => resolve(), { timeout }),
/TypeError/
);
}
for (let timeout of [1.2, -1]) {
Assert.throws(
() => new TimedPromise(resolve => resolve(), { timeout }),
/RangeError/
);
}
new TimedPromise(resolve => resolve(), { timeout: 42 });
});
add_task(async function test_TimedPromise_errorMessage() {
try {
await new TimedPromise(() => {}, { timeout: 0 });
ok(false, "Expected Timeout error not raised");
} catch (e) {
ok(
e.message.includes("TimedPromise timed out after"),
"Expected default error message found"
);
}
try {
await new TimedPromise(() => {}, {
errorMessage: "Not found",
timeout: 0,
});
ok(false, "Expected Timeout error not raised");
} catch (e) {
ok(
e.message.includes("Not found after"),
"Expected custom error message found"
);
}
});