2019-11-01 10:51:23 -05:00

62 lines
1.5 KiB
TypeScript

import * as cp from "child_process";
import { Emitter } from "vs/base/common/event";
enum ControlMessage {
okToChild = "ok>",
okFromChild = "ok<",
}
interface RelaunchMessage {
type: "relaunch";
version: string;
}
export type Message = RelaunchMessage;
class IpcMain {
protected readonly _onMessage = new Emitter<Message>();
public readonly onMessage = this._onMessage.event;
public handshake(child?: cp.ChildProcess): Promise<void> {
return new Promise((resolve, reject) => {
const target = child || process;
if (!target.send) {
throw new Error("Not spawned with IPC enabled");
}
target.on("message", (message) => {
if (message === child ? ControlMessage.okFromChild : ControlMessage.okToChild) {
target.removeAllListeners();
target.on("message", (msg) => this._onMessage.fire(msg));
if (child) {
target.send!(ControlMessage.okToChild);
}
resolve();
}
});
if (child) {
child.once("error", reject);
child.once("exit", (code) => {
const error = new Error(`Unexpected exit with code ${code}`);
(error as any).code = code;
reject(error);
});
} else {
target.send(ControlMessage.okFromChild);
}
});
}
public relaunch(version: string): void {
this.send({ type: "relaunch", version });
}
private send(message: Message): void {
if (!process.send) {
throw new Error("Not a child process with IPC enabled");
}
process.send(message);
}
}
export const ipcMain = new IpcMain();