blob: 09834470af023490710b909a921f7a1c1e5ac79d [file] [edit]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {type ChildProcess, spawn} from 'node:child_process';
import * as path from 'node:path';
const HOSTED_MODE_SERVER_PATH = path.join(__dirname, '..', '..', 'scripts', 'hosted_mode', 'server.js');
const cwd = path.join(__dirname, '..', '..');
let runningServer: ChildProcess|undefined;
/**
* Starts a hosted mode server on any available port and returns the port number
* once the server is ready to receive requests.
**/
export function startServer(commandLineArgs: string[]): Promise<number> {
if (runningServer) {
throw new Error('Server was already started.');
}
function handleServerError(error: Error) {
console.error(`Server error: ${error}`);
}
// Copy the current env and append the port.
const env = Object.create(process.env);
env.PORT = 0; // 0 means request a free port from the OS.
return new Promise((resolve, reject) => {
// We open the server with an IPC channel so that it can report the port it
// used back to us. For parallel test mode, we need to avoid specifying a
// port directly and instead request any free port, which is what port 0
// signifies to the OS.
const processArguments = [HOSTED_MODE_SERVER_PATH, ...commandLineArgs];
runningServer = spawn(process.execPath, processArguments, {
cwd,
env,
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
});
runningServer.on('message', message => {
if (message === 'ERROR') {
reject('Could not start server');
} else {
resolve(Number(message));
}
});
runningServer.on('error', handleServerError);
runningServer.stderr?.on('data', handleServerError);
});
}
process.on('exit', stopServer);
export function stopServer() {
runningServer?.kill();
}