Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 8 additions & 25 deletions packages/playwright-core/src/tools/cli-client/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,41 +235,24 @@ export async function program(options?: { embedderVersion?: string}) {
await new Promise<void>(resolve => child.on('exit', () => resolve()));
return;
}
const timer = setTimeout(() => child.stdin!.destroy(), 60_000);
child.unref();
try {
await new Promise<void>((resolve, reject) => {
let outLog = '';
const settle = (err?: Error) => {
clearTimeout(timer);
child.stdout!.removeAllListeners();
child.removeAllListeners('exit');
if (err)
reject(err);
else
resolve();
};
const timer = setTimeout(() => settle(new Error('Dashboard daemon did not spin up within 60s')), 60_000);
child.stdout!.on('data', data => {
outLog += data.toString();
if (!outLog.includes('<EOF>'))
return;
if (outLog.match(/### Success\n[\s\S]*<EOF>/))
settle();
else
settle(new Error(outLog.trim()));
if (outLog.includes('Dashboard is running'))
resolve();
});
child.stdout!.once('error', err => settle(err));
child.once('exit', (code, signal) => settle(new Error(`Dashboard daemon exited (code=${code}, signal=${signal}) before signaling READY${outLog ? '\n' + outLog : ''}`)));
child.once('exit', (code, signal) => reject(new Error(`Dashboard daemon exited (code=${code}, signal=${signal}) before signaling READY${outLog ? '\n' + outLog : ''}`)));
});
} catch (err) {
} finally {
clearTimeout(timer);
child.removeAllListeners('exit');
child.stdin!.destroy();
child.stdout!.destroy();
if (child.exitCode === null && child.signalCode === null)
await new Promise<void>(resolve => child.once('exit', () => resolve()));
throw err;
}
child.stdin!.destroy();
child.stdout!.destroy();
child.unref();
output.show(sessionName, child.pid);
return;
}
Expand Down
8 changes: 1 addition & 7 deletions packages/playwright-core/src/tools/cli-client/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,8 @@ export class Session {
await new Promise<void>((resolve, reject) => {
child.stdout!.on('data', data => {
outLog += data.toString();
if (!outLog.includes('<EOF>'))
return;
if (outLog.match(/### Success\nDaemon listening on (.*)\n<EOF>/)) {
if (outLog.includes('Daemon listening on'))
resolve();
return;
}
const errLogContent = fs.readFileSync(errLog, 'utf-8');
rejectWithPid(reject, outLog.trim() + (errLogContent ? '\n' + errLogContent : ''));
});
child.on('close', code => {
if (!signalled) {
Expand Down
7 changes: 2 additions & 5 deletions packages/playwright-core/src/tools/cli-daemon/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,9 @@ export function decorateProgram(program: Command) {
throw new Error('Error: unable to connect to a browser that does not have any contexts');
const persistent = options.persistent || options.profile || mcpConfig.browser.userDataDir ? true : undefined;
const socketPath = await startCliDaemonServer(sessionName, browserContext, browserInfo, mcpConfig, clientInfo, mcpClientInfo, { persistent, exitOnClose: true, ownership });
console.log(`### Success\nDaemon listening on ${socketPath}`);
console.log('<EOF>');
console.log(`Daemon listening on ${socketPath}\n`);
} catch (error) {
const message = process.env.PWDEBUGIMPL ? (error as Error).stack || (error as Error).message : (error as Error).message;
console.log(`### Error\n${message}`);
console.log('<EOF>');
console.log(error);
gracefullyProcessExitDoNotHang(1);
}
});
Expand Down
21 changes: 8 additions & 13 deletions packages/playwright-core/src/tools/dashboard/dashboardApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ export async function openDashboardApp() {
const { url } = await startDashboardServer(new RegistrySessionProvider(), options);
// eslint-disable-next-line no-console
console.log(`Listening on ${url}`);
// eslint-disable-next-line no-restricted-properties
await new Promise(f => process.stdout.write('', f)); // Make sure stdout is flushed.
selfDestructOnParentGone();
return;
}
Expand All @@ -318,30 +320,23 @@ export async function openDashboardApp() {
try {
server = await acquireSingleton(options);
} catch {
// Another daemon is already running; acquireSingleton forwarded our
// options to it. Signal success so the parent doesn't treat our clean
// exit as a startup failure.
// Another daemon is already running, signal success.
stopSelfDestruct();
// eslint-disable-next-line no-console
console.log('### Success\nDashboard already running');
// eslint-disable-next-line no-console
console.log('<EOF>');
console.log('Dashboard is running');
// eslint-disable-next-line no-restricted-properties
await new Promise(f => process.stdout.write('', f)); // Make sure stdout is flushed.
return;
}
process.on('exit', () => server.close());
try {
await startApp(server, options);
stopSelfDestruct();
// eslint-disable-next-line no-console
console.log('### Success\nDashboard ready');
// eslint-disable-next-line no-console
console.log('<EOF>');
console.log('Dashboard is running');
} catch (error) {
const message = (error as Error).stack || (error as Error).message;
// eslint-disable-next-line no-console
console.log(`### Error\n${message}`);
// eslint-disable-next-line no-console
console.log('<EOF>');
console.log(error);
gracefullyProcessExitDoNotHang(1);
}
}
Expand Down
Loading