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(); public readonly onMessage = this._onMessage.event; public handshake(child?: cp.ChildProcess): Promise { 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();