readline: use StringDecoder for decoding "normal" data

The fix from #3059 was not handling multi-byte utf8 data properly.
This commit is contained in:
Nathan Rajlich 2012-04-06 14:33:58 -07:00
Родитель 8652c11031
Коммит 78eb174ea2
2 изменённых файлов: 31 добавлений и 8 удалений

Просмотреть файл

@ -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;
}
};

Просмотреть файл

@ -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);