fs: make SyncWriteStream
inherit from Writable
Make the internal `SyncWriteStream` a proper `stream.Writable` subclass. This allows for quite a bit of simplification, since `SyncWriteStream` predates the streams2/streams3 implementations. Fixes: https://github.com/nodejs/node/issues/8828 PR-URL: https://github.com/nodejs/node/pull/8830 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
This commit is contained in:
parent
2a4b068aca
commit
a60f6078a1
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer;
|
const Buffer = require('buffer').Buffer;
|
||||||
const Stream = require('stream').Stream;
|
const Writable = require('stream').Writable;
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const constants = process.binding('constants').fs;
|
const constants = process.binding('constants').fs;
|
||||||
@ -58,65 +58,41 @@ exports.stringToFlags = stringToFlags;
|
|||||||
|
|
||||||
// Temporary hack for process.stdout and process.stderr when piped to files.
|
// Temporary hack for process.stdout and process.stderr when piped to files.
|
||||||
function SyncWriteStream(fd, options) {
|
function SyncWriteStream(fd, options) {
|
||||||
Stream.call(this);
|
Writable.call(this);
|
||||||
|
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
this.fd = fd;
|
this.fd = fd;
|
||||||
this.writable = true;
|
|
||||||
this.readable = false;
|
this.readable = false;
|
||||||
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
|
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
|
||||||
|
|
||||||
|
this.on('end', () => this._destroy());
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(SyncWriteStream, Stream);
|
util.inherits(SyncWriteStream, Writable);
|
||||||
|
|
||||||
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
|
|
||||||
var encoding, cb;
|
|
||||||
|
|
||||||
// parse arguments
|
|
||||||
if (arg1) {
|
|
||||||
if (typeof arg1 === 'string') {
|
|
||||||
encoding = arg1;
|
|
||||||
cb = arg2;
|
|
||||||
} else if (typeof arg1 === 'function') {
|
|
||||||
cb = arg1;
|
|
||||||
} else {
|
|
||||||
throw new Error('Bad arguments');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEncoding(encoding);
|
|
||||||
|
|
||||||
// Change strings to buffers. SLOW
|
|
||||||
if (typeof data === 'string') {
|
|
||||||
data = Buffer.from(data, encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeSync(this.fd, data, 0, data.length);
|
|
||||||
|
|
||||||
if (cb) {
|
|
||||||
process.nextTick(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
SyncWriteStream.prototype._write = function(chunk, encoding, cb) {
|
||||||
|
fs.writeSync(this.fd, chunk, 0, chunk.length);
|
||||||
|
cb();
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SyncWriteStream.prototype._destroy = function() {
|
||||||
|
if (this.fd === null) // already destroy()ed
|
||||||
|
return;
|
||||||
|
|
||||||
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
|
|
||||||
if (data) {
|
|
||||||
this.write(data, arg1, arg2);
|
|
||||||
}
|
|
||||||
this.destroy();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
SyncWriteStream.prototype.destroy = function() {
|
|
||||||
if (this.autoClose)
|
if (this.autoClose)
|
||||||
fs.closeSync(this.fd);
|
fs.closeSync(this.fd);
|
||||||
|
|
||||||
this.fd = null;
|
this.fd = null;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
SyncWriteStream.prototype.destroySoon =
|
||||||
|
SyncWriteStream.prototype.destroy = function() {
|
||||||
|
this._destroy();
|
||||||
this.emit('close');
|
this.emit('close');
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
|
|
||||||
|
|
||||||
exports.SyncWriteStream = SyncWriteStream;
|
exports.SyncWriteStream = SyncWriteStream;
|
||||||
|
40
test/parallel/test-fs-syncwritestream.js
Normal file
40
test/parallel/test-fs-syncwritestream.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const spawn = require('child_process').spawn;
|
||||||
|
const stream = require('stream');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// require('internal/fs').SyncWriteStream is used as a stdio implementation
|
||||||
|
// when stdout/stderr point to files.
|
||||||
|
|
||||||
|
if (process.argv[2] === 'child') {
|
||||||
|
// Note: Calling console.log() is part of this test as it exercises the
|
||||||
|
// SyncWriteStream#_write() code path.
|
||||||
|
console.log(JSON.stringify([process.stdout, process.stderr].map((stdio) => ({
|
||||||
|
instance: stdio instanceof stream.Writable,
|
||||||
|
readable: stdio.readable,
|
||||||
|
writable: stdio.writable,
|
||||||
|
}))));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
common.refreshTmpDir();
|
||||||
|
|
||||||
|
const filename = path.join(common.tmpDir, 'stdout');
|
||||||
|
const stdoutFd = fs.openSync(filename, 'w');
|
||||||
|
|
||||||
|
const proc = spawn(process.execPath, [__filename, 'child'], {
|
||||||
|
stdio: ['inherit', stdoutFd, stdoutFd ]
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.on('close', common.mustCall(() => {
|
||||||
|
fs.closeSync(stdoutFd);
|
||||||
|
|
||||||
|
assert.deepStrictEqual(JSON.parse(fs.readFileSync(filename, 'utf8')), [
|
||||||
|
{ instance: true, readable: false, writable: true },
|
||||||
|
{ instance: true, readable: false, writable: true }
|
||||||
|
]);
|
||||||
|
}));
|
Loading…
x
Reference in New Issue
Block a user