From ddfdaf97c5b3375dde5fab4f4ac01f10eaa5583f Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Thu, 14 Jun 2018 11:39:51 -0700 Subject: [PATCH] fix(page): fix race condition in WaitTask (#2739) This patch eliminates a common race condition with WaitTask, that happens when predicate function gets resolved right before the execution context gets destroyed. This situation results in a "Cannot find context with specified id undefined" exception. Credits go to @jakub300 for his wonderful [investigation](https://github.com/GoogleChrome/puppeteer/issues/1325#issuecomment-395472092). Fixes #1325. --- lib/FrameManager.js | 4 +++- test/frame.spec.js | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/FrameManager.js b/lib/FrameManager.js index d24b0958c2e..cc1d50c1d46 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -869,7 +869,9 @@ class WaitTask { } // Ignore timeouts in pageScript - we track timeouts ourselves. - if (!error && await this._frame.evaluate(s => !s, success)) { + // If the frame's execution context has already changed, `frame.evaluate` will + // throw an error - ignore this predicate run altogether. + if (!error && await this._frame.evaluate(s => !s, success).catch(e => true)) { await success.dispose(); return; } diff --git a/test/frame.spec.js b/test/frame.spec.js index dacb82cf158..ae2a325dd4f 100644 --- a/test/frame.spec.js +++ b/test/frame.spec.js @@ -84,6 +84,14 @@ module.exports.addTests = function({testRunner, expect}) { await page.evaluate(() => window.__FOO = 1); await watchdog; }); + it('should work when resolved right before execution context disposal', async({page, server}) => { + await page.evaluateOnNewDocument(() => window.__RELOADED = true); + await page.waitForFunction(() => { + if (!window.__RELOADED) + window.location.reload(); + return true; + }); + }); it('should poll on interval', async({page, server}) => { let success = false; const startTime = Date.now();