Skip to content

Commit 8522801

Browse files
authored
fix(cli-repl): properly handle \r\n newlines in input MONGOSH-998 (#1141)
1 parent 1266ab7 commit 8522801

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

packages/cli-repl/src/line-by-line-input.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ describe('LineByLineInput', () => {
4545
lineByLineInput.nextLine();
4646
expect(forwardedChunks).to.deep.equal(['ab', '\n', 'c']);
4747
});
48+
49+
it('groups \\r\\n together', () => {
50+
stdinMock.emit('data', Buffer.from('ab\r\nc'));
51+
lineByLineInput.nextLine();
52+
expect(forwardedChunks).to.deep.equal(['ab', '\r\n', 'c']);
53+
});
4854
});
4955

5056
context('when block on newline is disabled', () => {

packages/cli-repl/src/line-by-line-input.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,27 @@ export class LineByLineInput extends Readable {
104104
return this._forwardWithoutBlocking(chunk);
105105
};
106106

107+
// eslint-disable-next-line complexity
107108
private _forwardAndBlockOnNewline(chunk: Buffer | null): void {
108109
const chars = chunk === null ? [null] : this._decoder.write(chunk);
109110
for (const char of chars) {
111+
// Look up the last character we have queued up, if any:
112+
const lastCharQueueEntry = this._charQueue.length ?
113+
this._charQueue[this._charQueue.length - 1] : '';
114+
const lastCharQueueChar = lastCharQueueEntry?.length ?
115+
lastCharQueueEntry[lastCharQueueEntry.length - 1] : '';
116+
110117
if (this._isCtrlC(char) || this._isCtrlD(char)) {
111118
this.push(char);
112119
} else if (
113-
this._isRegularCharacter(char) &&
114-
this._charQueue.length > 0 &&
115-
this._isRegularCharacter(this._charQueue[this._charQueue.length - 1])) {
120+
(
121+
char === '\n' && lastCharQueueChar === '\r'
122+
) || (
123+
this._isRegularCharacter(char) &&
124+
lastCharQueueChar !== '' &&
125+
this._isRegularCharacter(lastCharQueueChar)
126+
)
127+
) {
116128
(this._charQueue[this._charQueue.length - 1] as string) += char as string;
117129
} else {
118130
this._charQueue.push(char);

packages/cli-repl/test/e2e.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ describe('e2e', function() {
144144
const result = await shell.executeLine('"a"+\n"<\\101>"');
145145
expect(result).to.match(/a<A>/);
146146
});
147+
it('handles \\r\\n newline input properly', async() => {
148+
shell.writeInput('34+55\r\n');
149+
await promisify(setTimeout)(100);
150+
shell.writeInput('_+55\r\n');
151+
await promisify(setTimeout)(100);
152+
shell.writeInput('_+89\r\n');
153+
await eventually(() => {
154+
shell.assertContainsOutput('233');
155+
});
156+
});
147157
});
148158

149159
describe('set db', () => {

0 commit comments

Comments
 (0)