Closed Bug 1963526 Opened 2 months ago Closed 2 months ago

For several Playwright tests the targeted test page never finishes loading unless you open the DevTools panel

Categories

(Remote Protocol :: WebDriver BiDi, defect, P2)

defect
Points:
2

Tracking

(firefox-esr128 unaffected, firefox138 unaffected, firefox139 fixed, firefox140 fixed)

RESOLVED FIXED
140 Branch
Tracking Status
firefox-esr128 --- unaffected
firefox138 --- unaffected
firefox139 --- fixed
firefox140 --- fixed

People

(Reporter: whimboo, Assigned: emilio)

References

(Blocks 1 open bug, Regression)

Details

(Keywords: regression, Whiteboard: [webdriver:m16][viewtransitions:m2][wptsync upstream])

Attachments

(6 files)

We're currently experiencing issues where several Playwright tests hang and eventually time out because the test page never completes loading. In the status bar, I can see the message Transferring data from localhost..., indicating that a connection is established, but the page never reaches either the interactive or load document states. It appears that something is preventing the page from fully loading, even though the connection remains open.

Earlier today, I encountered the same behavior in the test page/page-click.spec.ts :: should issue clicks in parallel in page and popup. Notably, this test does not involve any network interception, so it’s unclear why no data is being transferred.

To investigate further, I opened the DevTools network panel during the test using Cmd+Option+I. As soon as I did, the test immediately resumed and completed successfully. This suggests that opening DevTools somehow influences browser behavior in a way that unblocks the page load.

I was able to reduce the issue to the following minimal reproducible test case:

await page.goto(server.PREFIX + '/empty.html');
const [popup] = await Promise.all([
  page.waitForEvent('popup'),
  page.evaluate(() => window.open('/counter.html')),
]);
await popup.locator('button').click();

Interestingly, the issue does not occur if the click() call on the popup button is removed.

Julian, do you have an idea why opening DevTools would affect this behavior? It would also be good to know what might be causing the page to hang in the first place.

Flags: needinfo?(jdescottes)

I was able to capture a Gecko profile for this case with a slightly modified test to make it clear which page load for localhost actually stalls:

https://share.firefox.dev/4cVt6uD

The process of the newly opened tab is foreground but there is no activity for about 9s until I manually opened devtools, which caused the test to proceed.

It's not only related to DevTools. Simply clicking on the background tab will resume the test.

Flags: needinfo?(jdescottes)

Interestingly, the issue does not occur if the click() call on the popup button is removed.

Testing locally, it makes the reduced test case pass, but the page still doesn't load. You can wait for 5 seconds, you'll see the HTML is never loaded.

Regression window: https://hg-edge.mozilla.org/integration/autoland/pushloghtml?fromchange=8b055aa60807b71b880ea47770eb40e519609443&tochange=0b9e529a5541927220ce52a9577c4fb41782e0ae

  • Emilio Cobos Álvarez — Bug 1958942 - Refactor how we schedule and suppress rendering phases. r=smaug
  • Ryan VanderMeulen — Bug 1958041 - Pass the ZSTD_DISABLE_ASM flag more consistently to Windows builds. r=jesup

Hi Emilio it looks like Bug 1958942 regressed some Playwright tests, where tab calling window.open never seems to render the new tab. The network request corresponding to the HTML page is done properly, the response is received, but the tab keeps loading and is blank.

Opening devtools or focusing back and forth the new tab fixes it. Any idea?

Flags: needinfo?(emilio)
Keywords: regression
Regressed by: 1958942

Set release status flags based on info from the regressing bug 1958942

Can you give me a way of reproducing this? That'd probably be the faster way of fixing this.

It seems the pres shell is not initialized, so we don't render the document. DevTools seems to kick it off by flushing layout via Element.hasVisibleScrollbars.

So the question is why StartLayout() wasn't called by nsContentSink before.

Flags: needinfo?(emilio) → needinfo?(jdescottes)

(In reply to Emilio Cobos Álvarez (:emilio) from comment #7)

Can you give me a way of reproducing this? That'd probably be the faster way of fixing this.

It seems the pres shell is not initialized, so we don't render the document. DevTools seems to kick it off by flushing layout via Element.hasVisibleScrollbars.

So the question is why StartLayout() wasn't called by nsContentSink before.

(I didn't manage to repro outside of playwright, not sure what I'm missing)

  • git clone https://github.com/microsoft/playwright/
  • cd playwright && npm i
  • in a test file eg tests/page/page-click.spec.ts, add
it.only('should be able to use window open', async ({ page, server }) => {
  await page.goto(server.PREFIX + '/empty.html');
  await page.bringToFront();
  const [popup] = await Promise.all([
    page.waitForEvent('popup'),
    page.evaluate(() => window.open('/counter.html')),
  ]);
  await popup.locator('button').click();
});
  • DEBUG=pw:browser BIDI_FFPATH='PATH_TO_YOUR_LOCAL_BUILD' npm run biditest -- --project='moz-firefox-page' --headed
Flags: needinfo?(jdescottes)

Ok, let me try that.

Assignee: nobody → emilio
Status: NEW → ASSIGNED
Flags: needinfo?(emilio)
Whiteboard: [viewtransitions:triage]
Whiteboard: [viewtransitions:triage] → [viewtransitions:m2]

Do I need a specific version of node or something?

$ DEBUG=pw:browser BIDI_FFPATH='~/src/moz/firefox/obj-debug/dist/bin/firefox' npm run biditest -- --project='moz-firefox-page' --headed

> playwright-internal@1.53.0-next biditest
> playwright test --config=tests/bidi/playwright.config.ts --project=moz-firefox-page --headed

node:internal/modules/cjs/loader:668
      throw e;
      ^

Error: Cannot find module '/home/emilio/src/moz/playwright/node_modules/@playwright/experimental-ct-core/lib/program.js'
    at createEsmNotFoundErr (node:internal/modules/cjs/loader:1441:15)
    at finalizeEsmResolution (node:internal/modules/cjs/loader:1430:15)
    at resolveExports (node:internal/modules/cjs/loader:661:14)
    at Function._findPath (node:internal/modules/cjs/loader:753:31)
    at Function._resolveFilename (node:internal/modules/cjs/loader:1391:27)
    at defaultResolveImpl (node:internal/modules/cjs/loader:1061:19)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1066:22)
    at Function._load (node:internal/modules/cjs/loader:1215:37)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:235:24) {
  code: 'MODULE_NOT_FOUND',
  path: '/home/emilio/src/moz/playwright/node_modules/@playwright/experimental-ct-core'
}

Node.js v23.9.0

I also tried to follow the instructions in https://github.com/microsoft/playwright/blob/main/CONTRIBUTING.md, which seemed to get further along, but then npx install playwright or your command fails with:

npx playwright install
node:internal/modules/cjs/loader:1408
  throw err;
  ^

Error: Cannot find module './utilsBundleImpl'
Require stack:
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/utilsBundle.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/server/utils/debugLogger.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/server/utils/socksProxy.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/remote/playwrightConnection.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/remote/playwrightServer.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/androidServerImpl.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/inProcessFactory.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/inprocess.js
- /home/emilio/src/moz/playwright/packages/playwright-core/index.js
- /home/emilio/src/moz/playwright/packages/playwright-core/lib/cli/program.js
- /home/emilio/src/moz/playwright/packages/playwright/lib/program.js
- /home/emilio/src/moz/playwright/packages/playwright-ct-core/lib/program.js
- /home/emilio/src/moz/playwright/packages/playwright-ct-react/cli.js
    at Function._resolveFilename (node:internal/modules/cjs/loader:1405:15)
    at defaultResolveImpl (node:internal/modules/cjs/loader:1061:19)
    at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1066:22)
    at Function._load (node:internal/modules/cjs/loader:1215:37)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
    at Module.require (node:internal/modules/cjs/loader:1491:12)
    at require (node:internal/modules/helpers:135:16)
    at Object.<anonymous> (/home/emilio/src/moz/playwright/packages/playwright-core/lib/utilsBundle.js:44:16)
    at Module._compile (node:internal/modules/cjs/loader:1734:14) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/utilsBundle.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/server/utils/debugLogger.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/server/utils/socksProxy.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/remote/playwrightConnection.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/remote/playwrightServer.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/androidServerImpl.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/inProcessFactory.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/inprocess.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/index.js',
    '/home/emilio/src/moz/playwright/packages/playwright-core/lib/cli/program.js',
    '/home/emilio/src/moz/playwright/packages/playwright/lib/program.js',
    '/home/emilio/src/moz/playwright/packages/playwright-ct-core/lib/program.js',
    '/home/emilio/src/moz/playwright/packages/playwright-ct-react/cli.js'
  ]
}

Node.js v23.9.0
Flags: needinfo?(emilio) → needinfo?(jdescottes)

Not that I know of, I'm on v22.3.0

With that version, same steps, I hit the error at the bottom :(

OK let me try to move it to a wdspec test

Flags: needinfo?(jdescottes)

On mac it works (after running npm run watch). Let me try to debug it ther first :)

Flags: needinfo?(emilio)

Ok, so I debugged this and this seems all kind of expected given the current code I believe? But I understand the regression. Here's the Pernosco session with notes.

The main issue is that WebDriver is blocking the parser (and thus the load event, but more importantly StartLayout() and everything else) from here.

That in turn waits for the viewport to be set via here and then awaits for the window dimensions to be set here, which in turn waits for an animation frame and resize events here.

So the main issue is that we're waiting for resize events and animation frames that will never arrive, because the parsing is blocked and rendering is suppressed.

This just so happened to work before my patch because this line didn't check for pres shell initialization. But really it was mostly by chance, we would've gotten similarly deadlocked if we didn't happen to create the PresShell early.

In terms of how to fix this... I guess one option could be to explicitly initialize rendering, but that's somewhat lame. It's pretty much what was happening tho, I guess, because of the .innerWidth / .innerHeight right below the animation frame callback... So maybe that's a good enough short term workaround?

We could also unblock parsing with a timeout, but that's also not great... We could also not block rendering when Document::BlockParsing() is being used... Which I guess it's fair given there's basically arbitrary script blocking our initialization... Thoughts Olli / Henrik / Julian?

Flags: needinfo?(smaug)
Flags: needinfo?(jdescottes)
Flags: needinfo?(hskupin)
Flags: needinfo?(emilio)

This is a somewhat low-risk-fix-to-previous behavior. But, I'd note, not
great.

Thanks for the detailed explanation!

We could also unblock parsing with a timeout, but that's also not great

We actually have another issue related to an AnimationFramePromise which never resolves. There is a patch to fix this at Bug 1947402 using a timeout and it also happens to "fix" this playwright issue, although as you said not great, and it stills slows down the test by 1500ms ...

The BiDi spec makes it clear that for new contexts we should update the viewport before running preload scripts, which should run before any content script. As a temporary workaround, force rendering if we attempt to update the viewport sounds fine, but if not blocking rendering during that phase is an option, it would probably be better.

Flags: needinfo?(jdescottes)

I'd prefer avoiding web observable behavior changes based on a privileged api, but also I guess in this particular case it'd be very hard to observe.

Severity: -- → S3
Points: --- → 2
Priority: -- → P2
Whiteboard: [viewtransitions:m2] → [webdriver:m16][viewtransitions:m2]
Pushed by jdescottes@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/b66f3182de7f Explicitly initialize layout from document-element-inserted if needed. r=jdescottes,webdriver-reviewers https://hg.mozilla.org/integration/autoland/rev/ef874abc66b9 [wdspec] Fix type hints for various BiDi wdspec helpers r=webdriver-reviewers,whimboo https://hg.mozilla.org/integration/autoland/rev/f097102ffdf0 [wdspec] Add test for setViewport for user context and window.open() r=webdriver-reviewers,whimboo
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/52371 for changes under testing/web-platform/tests
Whiteboard: [webdriver:m16][viewtransitions:m2] → [webdriver:m16][viewtransitions:m2], [wptsync upstream]

Backed out for causing multiple failures

Backout link

Push with failures

Failure log Wd
Failure log lint

Flags: needinfo?(jdescottes)

mistake in the test, will fix

Flags: needinfo?(jdescottes)
Pushed by jdescottes@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/fcdb3ed4a111 Explicitly initialize layout from document-element-inserted if needed. r=jdescottes,webdriver-reviewers https://hg.mozilla.org/integration/autoland/rev/d7071f1be055 [wdspec] Fix type hints for various BiDi wdspec helpers r=webdriver-reviewers,whimboo https://hg.mozilla.org/integration/autoland/rev/c18424fd2f84 [wdspec] Add test for setViewport for user context and window.open() r=webdriver-reviewers,whimboo
Flags: needinfo?(smaug)
Flags: needinfo?(hskupin)
Upstream PR was closed without merging
Upstream PR merged by moz-wptsync-bot
Upstream PR merged by moz-wptsync-bot

The patch landed in nightly and beta is affected.
:emilio, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(emilio)

301 Julian :)

Flags: needinfo?(emilio) → needinfo?(jdescottes)

This is a somewhat low-risk-fix-to-previous behavior. But, I'd note, not
great.

Original Revision: https://phabricator.services.mozilla.com/D247662

Attachment #9486007 - Flags: approval-mozilla-beta?
Attachment #9486008 - Flags: approval-mozilla-beta?
Attachment #9486009 - Flags: approval-mozilla-beta?

firefox-beta Uplift Approval Request

  • User impact if declined: using window.open in automation will hang indefinitely if a viewport configuration is defined
  • Code covered by automated testing: yes
  • Fix verified in Nightly: yes
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing: N/A
  • Risk associated with taking this patch: low
  • Explanation of risk level: Simple JS fix to force rendering, webdriver bidi only
  • String changes made/needed: none
  • Is Android affected?: no
Flags: needinfo?(jdescottes)
Attachment #9486007 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9486008 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Attachment #9486009 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Points: 2 → 5
Points: 5 → 2
Whiteboard: [webdriver:m16][viewtransitions:m2], [wptsync upstream] → [webdriver:m16][webdriver:relnote][viewtransitions:m2][wptsync upstream]
Blocks: 1917540

We fixed the regression in the same version of Firefox. So nothing we actually have to announce to our users.

Whiteboard: [webdriver:m16][webdriver:relnote][viewtransitions:m2][wptsync upstream] → [webdriver:m16][viewtransitions:m2][wptsync upstream]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: