diff --git a/packages/core-internal/src/shared/stdio.ts b/packages/core-internal/src/shared/stdio.ts index 8bd794b87b..e90bd4cab2 100644 --- a/packages/core-internal/src/shared/stdio.ts +++ b/packages/core-internal/src/shared/stdio.ts @@ -31,7 +31,8 @@ export class ReadBuffer { } const line = this._buffer.toString('utf8', 0, index).replace(/\r$/, ''); - this._buffer = this._buffer.subarray(index + 1); + const remainder = this._buffer.subarray(index + 1); + this._buffer = remainder.length === 0 ? undefined : remainder; try { return deserializeMessage(line); diff --git a/packages/core-internal/test/shared/stdio.test.ts b/packages/core-internal/test/shared/stdio.test.ts index f8d27a4c1f..72127b2243 100644 --- a/packages/core-internal/test/shared/stdio.test.ts +++ b/packages/core-internal/test/shared/stdio.test.ts @@ -22,6 +22,18 @@ test('should only yield a message after a newline', () => { expect(readBuffer.readMessage()).toBeNull(); }); +test('should clear consumed buffer when newline is the final byte', () => { + const readBuffer = new ReadBuffer(); + + readBuffer.append(Buffer.from(JSON.stringify(testMessage) + '\n')); + expect(readBuffer.readMessage()).toEqual(testMessage); + expect((readBuffer as unknown as { _buffer?: Buffer })._buffer).toBeUndefined(); + + const nextChunk = Buffer.from(JSON.stringify(testMessage)); + readBuffer.append(nextChunk); + expect((readBuffer as unknown as { _buffer?: Buffer })._buffer).toBe(nextChunk); +}); + test('should be reusable after clearing', () => { const readBuffer = new ReadBuffer();