diff --git a/lib/readline.js b/lib/readline.js index 6a1ed150d72cd2..60864f40afdbc1 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -1039,9 +1039,6 @@ function emitKeypressEvents(stream, iface) { } else { stream.on('newListener', onNewListener); } - if (iface) { - iface.once('close', () => { stream.removeListener('data', onData); }); - } } /** diff --git a/test/parallel/test-readline-reopen.js b/test/parallel/test-readline-reopen.js new file mode 100644 index 00000000000000..dead22d81ac961 --- /dev/null +++ b/test/parallel/test-readline-reopen.js @@ -0,0 +1,44 @@ +'use strict'; + +// Regression test for https://github.com/nodejs/node/issues/13557 +// Tests that multiple subsequent readline instances can re-use an input stream. + +const common = require('../common'); +const assert = require('assert'); +const readline = require('readline'); +const { PassThrough } = require('stream'); + +const input = new PassThrough(); +const output = new PassThrough(); + +const rl1 = readline.createInterface({ + input, + output, + terminal: true +}); + +rl1.on('line', common.mustCall(rl1OnLine)); + +// Write a line plus the first byte of a UTF-8 multibyte character to make sure +// that it doesn’t get lost when closing the readline instance. +input.write(Buffer.concat([ + Buffer.from('foo\n'), + Buffer.from([ 0xe2 ]) // Exactly one third of a ☃ snowman. +])); + +function rl1OnLine(line) { + assert.strictEqual(line, 'foo'); + rl1.close(); + const rl2 = readline.createInterface({ + input, + output, + terminal: true + }); + + rl2.on('line', common.mustCall((line) => { + assert.strictEqual(line, '☃bar'); + rl2.close(); + })); + input.write(Buffer.from([0x98, 0x83])); // The rest of the ☃ snowman. + input.write('bar\n'); +} diff --git a/test/parallel/test-readline-set-raw-mode.js b/test/parallel/test-readline-set-raw-mode.js index ddffd131d0baff..db42a5a9495a9e 100644 --- a/test/parallel/test-readline-set-raw-mode.js +++ b/test/parallel/test-readline-set-raw-mode.js @@ -74,8 +74,6 @@ assert(!rawModeCalled); assert(resumeCalled); assert(!pauseCalled); -// One data listener for the keypress events. -assert.strictEqual(stream.listeners('data').length, 1); // close() should call setRawMode(false) expectedRawMode = false; @@ -88,5 +86,5 @@ assert(!resumeCalled); assert(pauseCalled); assert.deepStrictEqual(stream.listeners('keypress'), []); -// Data listener is removed once interface is closed. -assert.strictEqual(stream.listeners('data').length, 0); +// one data listener for the keypress events. +assert.strictEqual(stream.listeners('data').length, 1);