Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

waitForSelector fails with timeout error when puppeteer reconnects to a browser. #6527

Closed
dmitrysteblyuk opened this issue Oct 20, 2020 · 1 comment

Comments

@dmitrysteblyuk
Copy link
Contributor

Steps to reproduce

Tell us about your environment:

  • Puppeteer version: 5.3.1
  • Platform / OS version: Mac OS X 10.15.6
  • URLs (if applicable): -
  • Node.js version: 14.7.0

What steps will reproduce the problem?

Please include code that reproduces the issue.

  1. Launch browser (or connect to already running one).
  2. Open a new page, navigate to any url (or use already opened one if exists)
  3. Disconnect browser.
  4. Connect to the same browser and find the same page (from step 2).
  5. Reload/navigate this page.
  6. Await waitForSelector.
  7. Bug. TimeoutError: waiting for selector "div.test-reconnect" failed: timeout 5000ms exceeded

Example below:

const {createServer} = require('http');
const puppeteer = require('puppeteer');

const httpPort = 8909;
const waitOptions = {timeout: 5 * 1000};
const testUrl = `http://localhost:${httpPort}/`;

const testServer = createServer(({}, response) => {
  response.write('<div class="test-reconnect">Test Reconnect</div>');
  response.end();
});

(async () => {
  await new Promise((resolve, reject) => {
    testServer.on('listening', resolve);
    testServer.on('error', reject);
    testServer.listen(httpPort);
  });

  let browserWSEndpoint;

  {
    const browser = await puppeteer.launch({
      headless: false
    });
    browserWSEndpoint = browser.wsEndpoint();

    const page = await browser.newPage();
    await page.goto(testUrl);

    await page.reload();

    const element = await page.waitForSelector('div.test-reconnect', waitOptions);
    await element.dispose();

    // Reloading/navigating page before reconnection fixes the issue becuase the old
    // utility world gets destroyed on page reload.
    // So when puppeteer connects again it creates a new one and `waitForSelector` works fine.

    // await page.evaluate(() => setTimeout(() => location.reload(), 1000)); // <-- uncomment to make it work

    browser.disconnect();

    await new Promise((resolve) => setTimeout(resolve, 2000));
  }

  {
    console.log('reconnect');
    const browser = await puppeteer.connect({
      browserWSEndpoint
    });

    const page = (await browser.pages())
      .find((page) => page.url() === testUrl);

    // If page is not reloaded/navigated the old utility world is not yet destroyed
    // and `waitForSelector` works.
    await page.reload(); // <-- comment to make it work

    console.log('after reload');
    const element = await page.waitForSelector('div.test-reconnect', waitOptions);
    await element.dispose();

    await new Promise((resolve) => setTimeout(resolve, 1000));

    await browser.close();
  }
})()
.catch(console.error)
.finally(() => {
  testServer.close();
  process.exit();
});

What is the expected result?
waitForSelector works for a reconnected browser.

What happens instead?
waitForSelector fails with timeout error.

@dmitrysteblyuk
Copy link
Contributor Author

So what's happening here is that isolated utility world is being destroyed after browser is disconnected, but only when page is reloaded/navigated after that.

A new utility world is not created if there's already existing one:

if (this._isolatedWorlds.has(name)) return;

So the old one is being used.
But after page is reloaded it gets destroyed and a new one is not created either.
As a result the context for the secondary world is never set.

mathiasbynens pushed a commit that referenced this issue Nov 26, 2020
Don’t use the old utility world, as it is being destroyed later when browser reconnects to the page.

Issue: #6527
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant