mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-20 15:18:08 +02:00
Fix a race condition involving the waitForEvent
integration test helper function
Debugging #17931 uncovered a race condition in the way we use the `waitForEvent` function. Currently the following happens: 1. We call `waitForEvent`, which starts execution of the function body and immediately returns a promise. 2. We do the action that triggers the event. 3. We await the promise, which resolves if the event is triggered or the timeout is reached. The problem is in step 1: function body execution has started, but not necessarily completed. Given that we don't await the promise, we immediately trigger step 2 and it's not unlikely that the event we trigger arrives before the event listener is actually registered in the function body of `waitForEvent` (which is slower because it needs to be evaluated in the page context and there is some other logic before the actual `addEventListener` call). This commit fixes the issue by passing the action to `waitForEvent` as a callback so `waitForEvent` itself can call it once it's safe to do so. This should make sure that we always register the event listener before triggering the event, and because we shouldn't miss events anymore we can also remove the retry logic for pasting.
This commit is contained in:
parent
55ba4aa66a
commit
7128b95d29
2 changed files with 29 additions and 20 deletions
|
@ -23,9 +23,11 @@ import {
|
|||
} from "./test_utils.mjs";
|
||||
|
||||
const selectAll = async page => {
|
||||
const promise = waitForEvent(page, "selectionchange");
|
||||
await kbSelectAll(page);
|
||||
await promise;
|
||||
await waitForEvent({
|
||||
page,
|
||||
eventName: "selectionchange",
|
||||
action: () => kbSelectAll(page),
|
||||
});
|
||||
|
||||
await page.waitForFunction(() => {
|
||||
const selection = document.getSelection();
|
||||
|
|
|
@ -186,13 +186,14 @@ async function getSpanRectFromText(page, pageNumber, text) {
|
|||
);
|
||||
}
|
||||
|
||||
async function waitForEvent(
|
||||
async function waitForEvent({
|
||||
page,
|
||||
eventName,
|
||||
action,
|
||||
selector = null,
|
||||
validator = null,
|
||||
timeout = 5000
|
||||
) {
|
||||
timeout = 5000,
|
||||
}) {
|
||||
const handle = await page.evaluateHandle(
|
||||
(name, sel, validate, timeOut) => {
|
||||
let callback = null,
|
||||
|
@ -227,13 +228,15 @@ async function waitForEvent(
|
|||
validator ? validator.toString() : null,
|
||||
timeout
|
||||
);
|
||||
|
||||
await action();
|
||||
|
||||
const success = await awaitPromise(handle);
|
||||
if (success === null) {
|
||||
console.log(`waitForEvent: ${eventName} didn't trigger within the timeout`);
|
||||
} else if (!success) {
|
||||
console.log(`waitForEvent: ${eventName} triggered, but validation failed`);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
async function waitForStorageEntries(page, nEntries) {
|
||||
|
@ -293,9 +296,11 @@ async function mockClipboard(pages) {
|
|||
}
|
||||
|
||||
async function copy(page) {
|
||||
const promise = waitForEvent(page, "copy");
|
||||
await kbCopy(page);
|
||||
await promise;
|
||||
await waitForEvent({
|
||||
page,
|
||||
eventName: "copy",
|
||||
action: () => kbCopy(page),
|
||||
});
|
||||
}
|
||||
|
||||
async function copyToClipboard(page, data) {
|
||||
|
@ -314,20 +319,22 @@ async function copyToClipboard(page, data) {
|
|||
}
|
||||
|
||||
async function paste(page) {
|
||||
const promise = waitForEvent(page, "paste");
|
||||
await kbPaste(page);
|
||||
await promise;
|
||||
await waitForEvent({
|
||||
page,
|
||||
eventName: "paste",
|
||||
action: () => kbPaste(page),
|
||||
});
|
||||
}
|
||||
|
||||
async function pasteFromClipboard(page, selector = null) {
|
||||
const validator = e => e.clipboardData.items.length !== 0;
|
||||
let hasPasteEvent = false;
|
||||
while (!hasPasteEvent) {
|
||||
// We retry to paste if nothing has been pasted before the timeout.
|
||||
const promise = waitForEvent(page, "paste", selector, validator);
|
||||
await kbPaste(page);
|
||||
hasPasteEvent = await promise;
|
||||
}
|
||||
await waitForEvent({
|
||||
page,
|
||||
eventName: "paste",
|
||||
action: () => kbPaste(page),
|
||||
selector,
|
||||
validator,
|
||||
});
|
||||
}
|
||||
|
||||
async function getSerialized(page, filter = undefined) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue