2021-02-12 09:05:32 -08:00
|
|
|
/**
|
|
|
|
* Copyright (c) Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import { Connection } from './client/connection';
|
2022-02-02 21:26:45 -08:00
|
|
|
import { IpcTransport } from './protocol/transport';
|
2022-04-06 13:57:14 -08:00
|
|
|
import type { Playwright } from './client/playwright';
|
2021-02-12 09:05:32 -08:00
|
|
|
import * as childProcess from 'child_process';
|
|
|
|
import * as path from 'path';
|
2022-04-07 12:26:50 -08:00
|
|
|
import { ManualPromise } from './utils';
|
2021-02-12 09:05:32 -08:00
|
|
|
|
2021-10-27 07:28:53 -08:00
|
|
|
export async function start(env: any = {}): Promise<{ playwright: Playwright, stop: () => Promise<void> }> {
|
2021-09-29 14:54:24 -07:00
|
|
|
const client = new PlaywrightClient(env);
|
2021-02-12 09:05:32 -08:00
|
|
|
const playwright = await client._playwright;
|
|
|
|
(playwright as any).driverProcess = client._driverProcess;
|
2021-10-27 07:28:53 -08:00
|
|
|
return { playwright, stop: () => client.stop() };
|
2021-02-12 09:05:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
class PlaywrightClient {
|
|
|
|
_playwright: Promise<Playwright>;
|
|
|
|
_driverProcess: childProcess.ChildProcess;
|
2022-02-02 21:26:45 -08:00
|
|
|
private _closePromise = new ManualPromise<void>();
|
|
|
|
private _transport: IpcTransport;
|
|
|
|
private _stopped = false;
|
2021-02-12 09:05:32 -08:00
|
|
|
|
2021-09-29 14:54:24 -07:00
|
|
|
constructor(env: any) {
|
2021-02-12 09:05:32 -08:00
|
|
|
this._driverProcess = childProcess.fork(path.join(__dirname, 'cli', 'cli.js'), ['run-driver'], {
|
2022-02-02 21:26:45 -08:00
|
|
|
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
2021-02-12 09:05:32 -08:00
|
|
|
detached: true,
|
2021-09-29 14:54:24 -07:00
|
|
|
env: {
|
|
|
|
...process.env,
|
|
|
|
...env
|
|
|
|
},
|
2021-02-12 09:05:32 -08:00
|
|
|
});
|
|
|
|
this._driverProcess.unref();
|
2022-02-02 21:26:45 -08:00
|
|
|
this._driverProcess.on('exit', this._onExit.bind(this));
|
2021-02-12 09:05:32 -08:00
|
|
|
|
|
|
|
const connection = new Connection();
|
2022-02-02 21:26:45 -08:00
|
|
|
this._transport = new IpcTransport(this._driverProcess);
|
|
|
|
connection.onmessage = message => this._transport.send(JSON.stringify(message));
|
|
|
|
this._transport.onmessage = message => connection.dispatch(JSON.parse(message));
|
|
|
|
this._transport.onclose = () => this._closePromise.resolve();
|
2021-02-12 09:05:32 -08:00
|
|
|
|
2021-08-19 17:31:14 +02:00
|
|
|
this._playwright = connection.initializePlaywright();
|
2021-02-12 09:05:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
async stop() {
|
2022-02-02 21:26:45 -08:00
|
|
|
this._stopped = true;
|
|
|
|
this._transport.close();
|
2021-02-12 09:05:32 -08:00
|
|
|
await this._closePromise;
|
|
|
|
}
|
2022-02-02 21:26:45 -08:00
|
|
|
|
|
|
|
private _onExit(exitCode: number | null, signal: string | null) {
|
|
|
|
if (this._stopped)
|
|
|
|
this._closePromise.resolve();
|
|
|
|
else
|
|
|
|
throw new Error(`Server closed with exitCode=${exitCode} signal=${signal}`);
|
|
|
|
}
|
|
|
|
|
2021-02-12 09:05:32 -08:00
|
|
|
}
|