From d0644f5444a00531517a2cd0ffec0a1364e6bdf6 Mon Sep 17 00:00:00 2001 From: Joel Einbinder Date: Tue, 21 May 2024 15:15:05 -0400 Subject: [PATCH] fix(electron): flaky startup if stderr comes in too fast (#30855) Chromium's `DevTools listening on` message sometimes arrives before Playwright is finished connecting to Node. Without this patch, it would miss the message and fail to connect. --- .../playwright-core/src/server/electron/electron.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/server/electron/electron.ts b/packages/playwright-core/src/server/electron/electron.ts index 9b934ca2f7..b8f361b48a 100644 --- a/packages/playwright-core/src/server/electron/electron.ts +++ b/packages/playwright-core/src/server/electron/electron.ts @@ -229,6 +229,8 @@ export class Electron extends SdkObject { onExit: () => app?.emit(ElectronApplication.Events.Close), }); + // All waitForLines must be started immediately. + // Otherwise the lines might come before we are ready. const waitForXserverError = new Promise(async (resolve, reject) => { waitForLine(progress, launchedProcess, /Unable to open X display/).then(() => reject(new Error([ 'Unable to open X display!', @@ -240,17 +242,20 @@ export class Electron extends SdkObject { progress.metadata.log ].join('\n')))).catch(() => {}); }); + const nodeMatchPromise = waitForLine(progress, launchedProcess, /^Debugger listening on (ws:\/\/.*)$/); + const chromeMatchPromise = waitForLine(progress, launchedProcess, /^DevTools listening on (ws:\/\/.*)$/); + const debuggerDisconnectPromise = waitForLine(progress, launchedProcess, /Waiting for the debugger to disconnect\.\.\./); - const nodeMatch = await waitForLine(progress, launchedProcess, /^Debugger listening on (ws:\/\/.*)$/); + const nodeMatch = await nodeMatchPromise; const nodeTransport = await WebSocketTransport.connect(progress, nodeMatch[1]); const nodeConnection = new CRConnection(nodeTransport, helper.debugProtocolLogger(), browserLogsCollector); // Immediately release exiting process under debug. - waitForLine(progress, launchedProcess, /Waiting for the debugger to disconnect\.\.\./).then(() => { + debuggerDisconnectPromise.then(() => { nodeTransport.close(); }).catch(() => {}); const chromeMatch = await Promise.race([ - waitForLine(progress, launchedProcess, /^DevTools listening on (ws:\/\/.*)$/), + chromeMatchPromise, waitForXserverError, ]) as RegExpMatchArray; const chromeTransport = await WebSocketTransport.connect(progress, chromeMatch[1]);