diff --git a/src/vs/base/parts/ipc/common/ipc.mp.ts b/src/vs/base/parts/ipc/common/ipc.mp.ts index 91931de0a326d..c63ce5f5cd957 100644 --- a/src/vs/base/parts/ipc/common/ipc.mp.ts +++ b/src/vs/base/parts/ipc/common/ipc.mp.ts @@ -44,12 +44,14 @@ export class Protocol implements IMessagePassingProtocol { readonly onMessage; constructor(private port: MessagePort) { - this.onMessage = Event.fromDOMEventEmitter(this.port, 'message', (e: MessageEvent) => { - if (e.data) { - return VSBuffer.wrap(e.data); - } - return VSBuffer.alloc(0); - }); + // A `message` event may carry no (or empty) data (e.g. during + // connection teardown). An empty frame is never a valid protocol + // message (the smallest valid frame still has a serialized header), + // so we must not forward it: doing so makes the channel readers + // deserialize an `undefined` header and crash. Filter these out at + // the transport boundary instead. + const onMessage = Event.fromDOMEventEmitter(this.port, 'message', (e: MessageEvent) => e.data ? VSBuffer.wrap(e.data) : VSBuffer.alloc(0)); + this.onMessage = Event.filter(onMessage, data => data.byteLength > 0); // we must call start() to ensure messages are flowing port.start(); }