Skip to content

Commit

Permalink
readline: fix freeze if keypress event throws
Browse files Browse the repository at this point in the history
`emitKeys` is a generator which emits `keypress` events in an infinite
loop. But if `keypress` event handler throws, the error stops the loop,
leaving generator in a broken state. So this patch restarts the generator
when an error occures.

PR-URL: #2107
Reviewed-By: Christopher Monsanto <chris@monsan.to>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information
rlidwka committed Jul 11, 2015
1 parent cf14a24 commit bd01603
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
10 changes: 9 additions & 1 deletion lib/readline.js
Expand Up @@ -910,7 +910,15 @@ function emitKeypressEvents(stream) {
var r = stream[KEYPRESS_DECODER].write(b);
if (r) {
for (var i = 0; i < r.length; i++) {
stream[ESCAPE_DECODER].next(r[i]);
try {
stream[ESCAPE_DECODER].next(r[i]);
} catch (err) {
// if the generator throws (it could happen in the `keypress`
// event), we need to restart it.
stream[ESCAPE_DECODER] = emitKeys(stream);
stream[ESCAPE_DECODER].next();
throw err;
}
}
}
} else {
Expand Down
18 changes: 18 additions & 0 deletions test/parallel/test-readline-interface.js
Expand Up @@ -192,6 +192,24 @@ function isWarned(emitter) {
assert.equal(callCount, 1);
rli.close();

// Regression test for repl freeze, #1968:
// check that nothing fails if 'keypress' event throws.
fi = new FakeInput();
rli = new readline.Interface({ input: fi, output: fi, terminal: true });
var keys = [];
fi.on('keypress', function(key) {
keys.push(key);
if (key === 'X') {
throw new Error('bad thing happened');
}
});
try {
fi.emit('data', 'fooX');
} catch(e) { }
fi.emit('data', 'bar');
assert.equal(keys.join(''), 'fooXbar');
rli.close();

// calling readline without `new`
fi = new FakeInput();
rli = readline.Interface({ input: fi, output: fi, terminal: terminal });
Expand Down

0 comments on commit bd01603

Please sign in to comment.