Bug 1416446 - Part 1: Wait for the next tick in BrowserTestUtils.waitForEvent. r=Paolo

This commit is contained in:
Tooru Fujisawa 2017-12-09 06:08:43 +09:00
Родитель ef93d75551
Коммит 4e2bef04c1
2 изменённых файлов: 51 добавлений и 4 удалений

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

@ -741,8 +741,28 @@ this.BrowserTestUtils = {
* let promiseEvent = BrowserTestUtils.waitForEvent(element, "eventName");
* // Do some processing here that will cause the event to be fired
* // ...
* // Now yield until the Promise is fulfilled
* let receivedEvent = yield promiseEvent;
* // Now wait until the Promise is fulfilled
* let receivedEvent = await promiseEvent;
*
* The promise resolution/rejection handler for the returned promise is
* guaranteed not to be called until the next event tick after the event
* listener gets called, so that all other event listeners for the element
* are executed before the handler is executed.
*
* let promiseEvent = BrowserTestUtils.waitForEvent(element, "eventName");
* // Same event tick here.
* await promiseEvent;
* // Next event tick here.
*
* If some code, such like adding yet another event listener, needs to be
* executed in the same event tick, use raw addEventListener instead and
* place the code inside the event listener.
*
* element.addEventListener("load", () => {
* // Add yet another event listener in the same event tick as the load
* // event listener.
* p = BrowserTestUtils.waitForEvent(element, "ready");
* }, { once: true });
*
* @param {Element} subject
* The element that should receive the event.
@ -773,14 +793,14 @@ this.BrowserTestUtils = {
return;
}
subject.removeEventListener(eventName, listener, capture);
resolve(event);
TestUtils.executeSoon(() => resolve(event));
} catch (ex) {
try {
subject.removeEventListener(eventName, listener, capture);
} catch (ex2) {
// Maybe the provided object does not support removeEventListener.
}
reject(ex);
TestUtils.executeSoon(() => reject(ex));
}
}, capture, wantsUntrusted);
});

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

@ -68,3 +68,30 @@ add_task(async function() {
ok(true, "Should have returned a rejected promise trying to unregister an unknown about page");
});
});
add_task(async function testWaitForEvent() {
// A promise returned by BrowserTestUtils.waitForEvent should not be resolved
// in the same event tick as the event listener is called.
let eventListenerCalled = false;
let waitForEventResolved = false;
// Use capturing phase to make sure the event listener added by
// BrowserTestUtils.waitForEvent is called before the normal event listener
// below.
let eventPromise = BrowserTestUtils.waitForEvent(gBrowser, "dummyevent", true);
eventPromise.then(() => {
waitForEventResolved = true;
});
// Add normal event listener that is called after the event listener added by
// BrowserTestUtils.waitForEvent.
gBrowser.addEventListener("dummyevent", () => {
eventListenerCalled = true;
is(waitForEventResolved, false, "BrowserTestUtils.waitForEvent promise resolution handler shouldn't be called at this point.");
}, { once: true });
var event = new CustomEvent("dummyevent");
gBrowser.dispatchEvent(event);
await eventPromise;
is(eventListenerCalled, true, "dummyevent listener should be called");
});