Skip to content

Commit 688abac

Browse files
addaleaxFishrock123
authored andcommitted
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: #8828 PR-URL: #8830 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> (backport info) Refs: #9030
1 parent 5e6be7b commit 688abac

File tree

2 files changed

+57
-41
lines changed

2 files changed

+57
-41
lines changed

lib/fs.js

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,17 +2196,18 @@ WriteStream.prototype.destroySoon = WriteStream.prototype.end;
21962196
// SyncWriteStream is internal. DO NOT USE.
21972197
// Temporary hack for process.stdout and process.stderr when piped to files.
21982198
function SyncWriteStream(fd, options) {
2199-
Stream.call(this);
2199+
Writable.call(this);
22002200

22012201
options = options || {};
22022202

22032203
this.fd = fd;
2204-
this.writable = true;
22052204
this.readable = false;
22062205
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
2206+
2207+
this.on('end', () => this._destroy());
22072208
}
22082209

2209-
util.inherits(SyncWriteStream, Stream);
2210+
util.inherits(SyncWriteStream, Writable);
22102211

22112212

22122213
// Export
@@ -2216,51 +2217,26 @@ Object.defineProperty(fs, 'SyncWriteStream', {
22162217
value: SyncWriteStream
22172218
});
22182219

2219-
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
2220-
var encoding, cb;
2221-
2222-
// parse arguments
2223-
if (arg1) {
2224-
if (typeof arg1 === 'string') {
2225-
encoding = arg1;
2226-
cb = arg2;
2227-
} else if (typeof arg1 === 'function') {
2228-
cb = arg1;
2229-
} else {
2230-
throw new Error('Bad arguments');
2231-
}
2232-
}
2233-
assertEncoding(encoding);
2234-
2235-
// Change strings to buffers. SLOW
2236-
if (typeof data === 'string') {
2237-
data = Buffer.from(data, encoding);
2238-
}
2239-
2240-
fs.writeSync(this.fd, data, 0, data.length);
2241-
2242-
if (cb) {
2243-
process.nextTick(cb);
2244-
}
2245-
2220+
SyncWriteStream.prototype._write = function(chunk, encoding, cb) {
2221+
fs.writeSync(this.fd, chunk, 0, chunk.length);
2222+
cb();
22462223
return true;
22472224
};
22482225

2226+
SyncWriteStream.prototype._destroy = function() {
2227+
if (this.fd === null) // already destroy()ed
2228+
return;
22492229

2250-
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
2251-
if (data) {
2252-
this.write(data, arg1, arg2);
2253-
}
2254-
this.destroy();
2255-
};
2256-
2257-
2258-
SyncWriteStream.prototype.destroy = function() {
22592230
if (this.autoClose)
22602231
fs.closeSync(this.fd);
2232+
22612233
this.fd = null;
2262-
this.emit('close');
22632234
return true;
22642235
};
22652236

2266-
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
2237+
SyncWriteStream.prototype.destroySoon =
2238+
SyncWriteStream.prototype.destroy = function() {
2239+
this._destroy();
2240+
this.emit('close');
2241+
return true;
2242+
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const spawn = require('child_process').spawn;
5+
const stream = require('stream');
6+
const fs = require('fs');
7+
const path = require('path');
8+
9+
// require('internal/fs').SyncWriteStream is used as a stdio implementation
10+
// when stdout/stderr point to files.
11+
12+
if (process.argv[2] === 'child') {
13+
// Note: Calling console.log() is part of this test as it exercises the
14+
// SyncWriteStream#_write() code path.
15+
console.log(JSON.stringify([process.stdout, process.stderr].map((stdio) => ({
16+
instance: stdio instanceof stream.Writable,
17+
readable: stdio.readable,
18+
writable: stdio.writable,
19+
}))));
20+
21+
return;
22+
}
23+
24+
common.refreshTmpDir();
25+
26+
const filename = path.join(common.tmpDir, 'stdout');
27+
const stdoutFd = fs.openSync(filename, 'w');
28+
29+
const proc = spawn(process.execPath, [__filename, 'child'], {
30+
stdio: ['inherit', stdoutFd, stdoutFd ]
31+
});
32+
33+
proc.on('close', common.mustCall(() => {
34+
fs.closeSync(stdoutFd);
35+
36+
assert.deepStrictEqual(JSON.parse(fs.readFileSync(filename, 'utf8')), [
37+
{ instance: true, readable: false, writable: true },
38+
{ instance: true, readable: false, writable: true }
39+
]);
40+
}));

0 commit comments

Comments
 (0)