From d6b72e4514f6829a6d5a2efd636a5c486353a3a4 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Mon, 22 Sep 2014 12:59:26 +0200 Subject: [PATCH] Don't childProcess.spawn until the first .write call. --- lib/PngQuant.js | 88 +++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/lib/PngQuant.js b/lib/PngQuant.js index 8ef0fb2..bce6850 100644 --- a/lib/PngQuant.js +++ b/lib/PngQuant.js @@ -12,46 +12,17 @@ var binPath = pngQuantBin ? pngQuantBin.path : 'pngquant'; function PngQuant(pngQuantArgs) { Stream.call(this); - if (!pngQuantArgs || pngQuantArgs.length === 0) { - pngQuantArgs = [256]; + this.pngQuantArgs = pngQuantArgs; + + if (!this.pngQuantArgs || this.pngQuantArgs.length === 0) { + this.pngQuantArgs = [256]; } this.writable = this.readable = true; this.commandLine = binPath + (pngQuantArgs ? ' ' + pngQuantArgs.join(' ') : ''); // For debugging - this.pngQuantProcess = childProcess.spawn(binPath, pngQuantArgs); this.hasEnded = false; this.seenDataOnStdout = false; - - this.pngQuantProcess.on('error', this._reportError.bind(this)); - - this.pngQuantProcess.stderr.on('data', function (data) { - if (!this.hasEnded) { - this._reportError(new Error('Saw pngquant output on stderr: ' + data.toString('ascii'))); - this.hasEnded = true; - } - }.bind(this)); - - this.pngQuantProcess.on('exit', function (exitCode) { - if (exitCode > 0 && !this.hasEnded) { - this._reportError(new Error('The pngquant process exited with a non-zero exit code: ' + exitCode)); - this.hasEnded = true; - } - }.bind(this)); - - this.pngQuantProcess.stdout.on('data', function (chunk) { - this.seenDataOnStdout = true; - this.emit('data', chunk); - }.bind(this)).on('end', function () { - if (!this.hasEnded) { - if (this.seenDataOnStdout) { - this.emit('end'); - } else { - this._reportError(new Error('PngQuant: The stdout stream ended without emitting any data')); - } - this.hasEnded = true; - } - }.bind(this)); } util.inherits(PngQuant, Stream); @@ -64,22 +35,69 @@ PngQuant.prototype._reportError = function (err) { }; PngQuant.prototype.write = function (chunk) { + if (!this.pngQuantProcess) { + this.pngQuantProcess = childProcess.spawn(binPath, this.pngQuantArgs); + this.pngQuantProcess.on('error', this._reportError.bind(this)); + + this.pngQuantProcess.stderr.on('data', function (data) { + if (!this.hasEnded) { + this._reportError(new Error('Saw pngquant output on stderr: ' + data.toString('ascii'))); + this.hasEnded = true; + } + }.bind(this)); + + this.pngQuantProcess.on('exit', function (exitCode) { + if (exitCode > 0 && !this.hasEnded) { + this._reportError(new Error('The pngquant process exited with a non-zero exit code: ' + exitCode)); + this.hasEnded = true; + } + }.bind(this)); + + this.pngQuantProcess.stdout.on('data', function (chunk) { + this.seenDataOnStdout = true; + this.emit('data', chunk); + }.bind(this)).on('end', function () { + if (!this.hasEnded) { + if (this.seenDataOnStdout) { + this.emit('end'); + } else { + this._reportError(new Error('PngQuant: The stdout stream ended without emitting any data')); + } + this.hasEnded = true; + } + }.bind(this)); + + if (this.pauseStdoutOfPngQuantProcessAfterStartingIt) { + this.pngQuantProcess.stdout.pause(); + } + } this.pngQuantProcess.stdin.write(chunk); }; PngQuant.prototype.end = function (chunk) { if (chunk) { this.write(chunk); + } else if (!this.pngQuantProcess) { + // No chunks have been rewritten. Write an empty one to make sure there's pngquant process. + this.write(new Buffer(0)); } this.pngQuantProcess.stdin.end(); }; PngQuant.prototype.pause = function () { - this.pngQuantProcess.stdout.pause(); + if (this.pngQuantProcess) { + this.pngQuantProcess.stdout.pause(); + } else { + this.pauseStdoutOfPngQuantProcessAfterStartingIt = true; + } }; PngQuant.prototype.resume = function () { - this.pngQuantProcess.stdout.resume(); + if (this.pngQuantProcess) { + this.pngQuantProcess.stdout.resume(); + } else { + this.pauseStdoutOfPngQuantProcessAfterStartingIt = false; + } }; module.exports = PngQuant;