53 lines
1.3 KiB
TypeScript
53 lines
1.3 KiB
TypeScript
|
import * as cp from "child_process";
|
||
|
import { Emitter } from "vs/base/common/event";
|
||
|
|
||
|
enum ControlMessage {
|
||
|
okToChild = "ok>",
|
||
|
okFromChild = "ok<",
|
||
|
}
|
||
|
|
||
|
export type Message = "relaunch";
|
||
|
|
||
|
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(): void {
|
||
|
if (!process.send) {
|
||
|
throw new Error("Not a child process with IPC enabled");
|
||
|
}
|
||
|
process.send("relaunch");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export const ipcMain = new IpcMain();
|