Mess with lusha's waitFor for fun. (#133)

This commit is contained in:
Pavel Feldman 2017-07-25 15:57:31 -07:00 committed by Andrey Lushnikov
parent 4adf11427a
commit 49e363c121

View File

@ -422,7 +422,7 @@ class WaitTask {
constructor(frame, pageScript, timeout) { constructor(frame, pageScript, timeout) {
this._frame = frame; this._frame = frame;
this._pageScript = pageScript; this._pageScript = pageScript;
this._runningTask = null; this._runCount = 0;
frame._waitTasks.add(this); frame._waitTasks.add(this);
this.promise = new Promise((resolve, reject) => { this.promise = new Promise((resolve, reject) => {
this._resolve = resolve; this._resolve = resolve;
@ -438,31 +438,35 @@ class WaitTask {
* @param {!Error} error * @param {!Error} error
*/ */
terminate(error) { terminate(error) {
this._terminated = true;
this._reject(error); this._reject(error);
this._cleanup(); this._cleanup();
} }
rerun() { async rerun() {
let runningTask = this._frame._evaluateExpression(this._pageScript, true).then(finish.bind(this), finish.bind(this, false)); const runCount = ++this._runCount;
this._runningTask = runningTask; let success = false;
let error = null;
try {
success = await this._frame._evaluateExpression(this._pageScript, true);
} catch (e) {
error = e;
}
/** if (this._terminated || runCount !== this._runCount)
* @param {boolean} success
* @param {?Error=} error
*/
function finish(success, error) {
if (runningTask !== this._runningTask)
return; return;
// Ignore timeouts in pageScript - we track timeouts ourselves. // Ignore timeouts in pageScript - we track timeouts ourselves.
if (!success && !error) if (!success && !error)
return; return;
if (error) if (error)
this._reject(error); this._reject(error);
else else
this._resolve(); this._resolve();
this._cleanup(); this._cleanup();
} }
}
_cleanup() { _cleanup() {
clearTimeout(this._timeoutTimer); clearTimeout(this._timeoutTimer);
@ -477,30 +481,28 @@ class WaitTask {
* @param {number} timeout * @param {number} timeout
* @return {!Promise<boolean>} * @return {!Promise<boolean>}
*/ */
function waitForSelectorPageFunction(selector, visible, timeout) { async function waitForSelectorPageFunction(selector, visible, timeout) {
const resultPromise = visible ? waitForVisible(selector) : waitInDOM(selector); let timedOut = false;
const timeoutPromise = new Promise(fulfill => setTimeout(fulfill, timeout)); setTimeout(() => timedOut = true, timeout);
return Promise.race([ await waitForDOM();
resultPromise.then(() => true), await waitForVisible();
timeoutPromise.then(() => false) return !timedOut;
]);
/** /**
* @param {string} selector
* @return {!Promise<!Element>} * @return {!Promise<!Element>}
*/ */
function waitInDOM(selector) { function waitForDOM() {
let node = document.querySelector(selector); let node = document.querySelector(selector);
if (node) if (node)
return Promise.resolve(node); return Promise.resolve();
let fulfill; let fulfill;
const result = new Promise(x => fulfill = x); const result = new Promise(x => fulfill = x);
const observer = new MutationObserver(mutations => { const observer = new MutationObserver(mutations => {
const node = document.querySelector(selector); const node = document.querySelector(selector);
if (node) { if (node || timedOut) {
observer.disconnect(); observer.disconnect();
fulfill(node); fulfill();
} }
}); });
observer.observe(document, { observer.observe(document, {
@ -511,23 +513,26 @@ function waitForSelectorPageFunction(selector, visible, timeout) {
} }
/** /**
* @param {string} selector
* @return {!Promise<!Element>} * @return {!Promise<!Element>}
*/ */
async function waitForVisible(selector) { function waitForVisible() {
let fulfill; let fulfill;
const result = new Promise(x => fulfill = x); const result = new Promise(x => fulfill = x);
onRaf(); onRaf();
return result; return result;
async function onRaf() { function onRaf() {
const node = await waitInDOM(selector); if (timedOut) {
const style = window.getComputedStyle(node); fulfill();
if (style.display === 'none' || style.visibility === 'hidden') { return;
}
const node = document.querySelector(selector);
const style = node ? window.getComputedStyle(node) : null;
if (!style || style.display === 'none' || style.visibility === 'hidden') {
requestAnimationFrame(onRaf); requestAnimationFrame(onRaf);
return; return;
} }
fulfill(node); fulfill();
} }
} }
} }