From 78eb174ea2d26ee3bea89f707b78441a8c73c098 Mon Sep 17 00:00:00 2001 From: Nathan Rajlich Date: Fri, 6 Apr 2012 14:33:58 -0700 Subject: [PATCH] readline: use StringDecoder for decoding "normal" data The fix from #3059 was not handling multi-byte utf8 data properly. --- lib/readline.js | 23 +++++++++++++++-------- test/simple/test-readline-interface.js | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/readline.js b/lib/readline.js index 7da3ce7..6fb5e9f 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -93,6 +93,8 @@ function Interface(input, output, completer, terminal) { input.on('end', function() { self.emit('end'); }); + var StringDecoder = require('string_decoder').StringDecoder; // lazy load + this._decoder = new StringDecoder('utf8'); } else { @@ -264,22 +266,27 @@ Interface.prototype.write = function(d, key) { this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d, key); }; -// telnet on windows sends every single keystroke seperately, so we need -// to buffer them and only fire the 'line' event when a \n is sent -Interface.prototype._line_buffer = ''; - Interface.prototype._normalWrite = function(b) { if (b === undefined) { return; } - this._line_buffer += b.toString(); - if (this._line_buffer.indexOf('\n') !== -1) { - var lines = this._line_buffer.split('\n'); + var string = this._decoder.write(b); + if (this._line_buffer) { + string = this._line_buffer + string; + this._line_buffer = null; + } + if (string.indexOf('\n') !== -1) { + // got one or more newlines; process into "line" events + var lines = string.split('\n'); // either '' or (concievably) the unfinished portion of the next line - this._line_buffer = lines.pop(); + string = lines.pop(); + this._line_buffer = string; lines.forEach(function(line) { this._onLine(line + '\n'); }, this); + } else if (string) { + // no newlines this time, save what we have for next time + this._line_buffer = string; } }; diff --git a/test/simple/test-readline-interface.js b/test/simple/test-readline-interface.js index fc8d4f2..986fa1f 100644 --- a/test/simple/test-readline-interface.js +++ b/test/simple/test-readline-interface.js @@ -104,3 +104,19 @@ rli.on('line', function(line) { }); fi.emit('data', expectedLines.join('')); assert.equal(callCount, expectedLines.length - 1); + +// sending a multi-byte utf8 char over multiple writes +var buf = Buffer('☮', 'utf8'); +fi = new FakeInput(); +rli = new readline.Interface(fi, {}); +callCount = 0; +rli.on('line', function(line) { + callCount++; + assert.equal(line, buf.toString('utf8') + '\n'); +}); +[].forEach.call(buf, function(i) { + fi.emit('data', Buffer([i])); +}); +assert.equal(callCount, 0); +fi.emit('data', '\n'); +assert.equal(callCount, 1); -- 2.7.4