- streamToBuffer is not sensitive to empty buffers (and it shouldn't

be). But empty buffers are present sometimes if an invoked process
  returns with an error code. In the current architecture, callback
  functions can receive streams, which are available before the
  process exits and delivers an exit code. The callback can thus not
  be informed of  the error condition by the library and has to find out
  herself. This commit fixes a case when the callback is provided by
  the library, so that empty streams are reported as errors.
- streamToUnemptyBuffer checks the length of the buffer before
  delivering it, and if the buffer has a zero length, an error is
  delivered instead. This behavior is probably good for all the cases
  where streamToBuffer is used in this library, so I'm also dropping that as a
  dependency.
- Added a test case. All tests passing.
- Fixes #299
master
alcidesv 10 years ago
parent a5cce8a4b1
commit 48f277b011
  1. 42
      lib/command.js
  2. 1
      package.json
  3. 21
      test/streamerr.js

@ -8,7 +8,6 @@ var spawn = require('child_process').spawn;
var utils = require('./utils');
var debug = require('debug')('gm');
var series = require('array-series');
var streamToBuffer = require('stream-to-buffer');
/*
* Creates a pass through stream.
@ -44,6 +43,38 @@ module.exports = function (proto) {
return this;
}
}
function streamToUnemptyBuffer(stream, callback) {
var done = false
var buffers = []
stream.on('data', function (data) {
buffers.push(data)
})
stream.on('end', function () {
var result, err;
if (done)
return
done = true
result = Buffer.concat(buffers)
buffers = null
if (result.length==0)
{
err = new Error("Stream yields empty buffer");
callback(err, null);
} else {
callback(null, result);
}
})
stream.on('error', function (err) {
done = true
buffers = null
callback(err)
})
}
proto.in = args('_in');
proto.out = args('_out');
@ -100,6 +131,7 @@ module.exports = function (proto) {
if ("function" !== typeof callback) {
throughStream = new PassThrough();
console.log("artifical callback 1");
callback = function (err, stdout, stderr) {
if (err) throughStream.emit('error', err);
else stdout.pipe(throughStream);
@ -113,6 +145,7 @@ module.exports = function (proto) {
var self = this;
this._preprocess(function (err) {
console.log("Unbuffered");
if (err) return callback(err);
return self._spawn(self.args(), false, callback);
});
@ -137,9 +170,10 @@ module.exports = function (proto) {
}
return this.stream(format, function (err, stdout) {
console.log("artifical callback 2");
if (err) return callback(err);
streamToBuffer(stdout, callback);
streamToUnemptyBuffer(stdout, callback);
})
}
@ -173,7 +207,7 @@ module.exports = function (proto) {
* @param {Array} args
* @param {ReadableStream} stream
* @param {Boolean} shouldBuffer
* @param {Function} callback
* @param {Function} callback, signature (err, stdout, stderr) -> *
* @return {Object} gm
* @TODO refactor this mess
*/
@ -219,7 +253,7 @@ module.exports = function (proto) {
// we only need one
self._buffering = true;
streamToBuffer(self.sourceStream, function (err, buffer) {
streamToUnemptyBuffer(self.sourceStream, function (err, buffer) {
self.sourceBuffer = buffer;
self.sourceStream = null; // The stream is now dead
})

@ -43,7 +43,6 @@
"debug": "0.7.0",
"array-series": "~0.1.0",
"array-parallel": "~0.1.0",
"stream-to-buffer": "~0.0.1",
"through": "~2.3.1"
}
}

@ -0,0 +1,21 @@
var assert = require('assert')
module.exports = function (_, dir, finish, gm) {
var svg_file;
svg_file = new Buffer('<svg viewBox="0 0 20 17" style="background-color:#ffffff00" xmlns="http://www.w3.org/2000/svg" width="20" height="17"><g fill="#656C72"><path d="M0 0h20v3h-20zM0 7h20v3h-20zM0 14h20v3h-20z"/></g></svg>', 'ascii');
// The following invocation should fail, because 'convert'
// has no way of interpreting the file.
gm(
svg_file,
'./test.svg' // fiction
).options({
imageMagick: true
}).setFormat('png').toBuffer(function(err, buffer) {
assert.ok(err, "Expecting error on this buffer");
});
if (!gm.integration)
return finish();
}
Loading…
Cancel
Save