Browse Source

stream: Don't stop reading on zero-length decoded output

Fixes regression introduced in 7e1cf84c9e
v0.9.9-release
isaacs 12 years ago
parent
commit
a6c18472cd
  1. 6
      lib/_stream_readable.js
  2. 81
      test/simple/test-stream2-readable-empty-buffer-no-eof.js

6
lib/_stream_readable.js

@ -291,9 +291,6 @@ function onread(stream, er, chunk) {
return;
}
if (state.decoder)
chunk = state.decoder.write(chunk);
// at this point, if we got a zero-length buffer or string,
// and we're not in object-mode, then there's really no point
// continuing. it means that there is nothing to read right
@ -305,6 +302,9 @@ function onread(stream, er, chunk) {
0 === chunk.length)
return;
if (state.decoder)
chunk = state.decoder.write(chunk);
// update the buffer info.
state.length += state.objectMode ? 1 : chunk.length;
state.buffer.push(chunk);

81
test/simple/test-stream2-readable-empty-buffer-no-eof.js

@ -24,22 +24,26 @@ var assert = require('assert');
var Readable = require('stream').Readable;
var r = new Readable();
test1();
test2();
// should not end when we get a Buffer(0) or '' as the _read result
// that just means that there is *temporarily* no data, but to go
// ahead and try again later.
//
// note that this is very unusual. it only works for crypto streams
// because the other side of the stream will call read(0) to cycle
// data through openssl. that's why we set the timeouts to call
// r.read(0) again later, otherwise there is no more work being done
// and the process just exits.
function test1() {
var r = new Readable();
// should not end when we get a Buffer(0) or '' as the _read result
// that just means that there is *temporarily* no data, but to go
// ahead and try again later.
//
// note that this is very unusual. it only works for crypto streams
// because the other side of the stream will call read(0) to cycle
// data through openssl. that's why we set the timeouts to call
// r.read(0) again later, otherwise there is no more work being done
// and the process just exits.
var buf = new Buffer(5);
buf.fill('x');
var reads = 5;
r._read = function(n, cb) {
var buf = new Buffer(5);
buf.fill('x');
var reads = 5;
r._read = function(n, cb) {
switch (reads--) {
case 0:
return cb(null, null); // EOF
@ -65,21 +69,50 @@ r._read = function(n, cb) {
default:
throw new Error('unreachable');
}
};
};
var results = [];
function flow() {
var results = [];
function flow() {
var chunk;
while (null !== (chunk = r.read()))
results.push(chunk + '');
}
r.on('readable', flow);
r.on('end', function() {
}
r.on('readable', flow);
r.on('end', function() {
results.push('EOF');
});
flow();
});
flow();
process.on('exit', function() {
process.on('exit', function() {
assert.deepEqual(results, [ 'xxxxx', 'xxxxx', 'EOF' ]);
console.log('ok');
});
});
}
function test2() {
var r = new Readable({ encoding: 'base64' });
var reads = 5;
r._read = function(n, cb) {
if (!reads--)
return cb(null, null); // EOF
else
return cb(null, new Buffer('x'));
};
var results = [];
function flow() {
var chunk;
while (null !== (chunk = r.read()))
results.push(chunk + '');
}
r.on('readable', flow);
r.on('end', function() {
results.push('EOF');
});
flow();
process.on('exit', function() {
assert.deepEqual(results, [ 'eHh4', 'eHg=', 'EOF' ]);
console.log('ok');
});
}

Loading…
Cancel
Save