-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
readline: fix issue with newline-less last line
The logic for reading lines was slightly flawed, in that it assumed there would be a final new line. It handled the case where there are no new lines, but this then broke if there were some new lines. The fix in logic is basically removing the special case where there are no new lines by changing it to always read the final line with no new lines. This works because if a file contains no new lines, the final line is the first line, and all is well. There is some subtlety in this functioning, however. If the last line contains no new lines, then `lastIndex` will be the start of the last line, and `kInsertString` will be called from that point. If it does contain a new line, `lastIndex` will be equal to `s.length`, so the slice will be the empty string. Fixes: #47305 PR-URL: #47317 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
- Loading branch information
Showing
4 changed files
with
85 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// The lack of a newline at the end of this file is intentional. | ||
const getLunch = () => | ||
placeOrder('tacos') | ||
.then(eat); | ||
|
||
const placeOrder = (order) => Promise.resolve(order); | ||
const eat = (food) => '<nom nom nom>'; |
24 changes: 24 additions & 0 deletions
24
test/parallel/test-readline-interface-no-trailing-newline.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const ArrayStream = require('../common/arraystream'); | ||
const assert = require('assert'); | ||
|
||
common.skipIfDumbTerminal(); | ||
|
||
const readline = require('readline'); | ||
const rli = new readline.Interface({ | ||
terminal: true, | ||
input: new ArrayStream(), | ||
output: new ArrayStream(), | ||
}); | ||
|
||
// Minimal reproduction for #47305 | ||
const testInput = '{\n}'; | ||
|
||
let accum = ''; | ||
|
||
rli.output.write = (data) => accum += data.replace('\r', ''); | ||
|
||
rli.write(testInput); | ||
|
||
assert.strictEqual(accum, testInput); |
42 changes: 42 additions & 0 deletions
42
test/parallel/test-repl-load-multiline-no-trailing-newline.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const ArrayStream = require('../common/arraystream'); | ||
const fixtures = require('../common/fixtures'); | ||
const assert = require('assert'); | ||
const repl = require('repl'); | ||
|
||
common.skipIfDumbTerminal(); | ||
|
||
const command = `.load ${fixtures.path('repl-load-multiline-no-trailing-newline.js')}`; | ||
const terminalCode = '\u001b[1G\u001b[0J \u001b[1G'; | ||
const terminalCodeRegex = new RegExp(terminalCode.replace(/\[/g, '\\['), 'g'); | ||
|
||
const expected = `${command} | ||
// The lack of a newline at the end of this file is intentional. | ||
const getLunch = () => | ||
placeOrder('tacos') | ||
.then(eat); | ||
const placeOrder = (order) => Promise.resolve(order); | ||
const eat = (food) => '<nom nom nom>'; | ||
undefined | ||
`; | ||
|
||
let accum = ''; | ||
|
||
const inputStream = new ArrayStream(); | ||
const outputStream = new ArrayStream(); | ||
|
||
outputStream.write = (data) => accum += data.replace('\r', ''); | ||
|
||
const r = repl.start({ | ||
prompt: '', | ||
input: inputStream, | ||
output: outputStream, | ||
terminal: true, | ||
useColors: false | ||
}); | ||
|
||
r.write(`${command}\n`); | ||
assert.strictEqual(accum.replace(terminalCodeRegex, ''), expected); | ||
r.close(); |