Skip to content

Commit e1ef536

Browse files
committed
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: nodejs#8828
1 parent c991d64 commit e1ef536

File tree

2 files changed

+56
-42
lines changed

2 files changed

+56
-42
lines changed

lib/internal/fs.js

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const Buffer = require('buffer').Buffer;
4-
const Stream = require('stream').Stream;
4+
const Writable = require('stream').Writable;
55
const fs = require('fs');
66
const util = require('util');
77
const constants = process.binding('constants').fs;
@@ -58,65 +58,41 @@ exports.stringToFlags = stringToFlags;
5858

5959
// Temporary hack for process.stdout and process.stderr when piped to files.
6060
function SyncWriteStream(fd, options) {
61-
Stream.call(this);
61+
Writable.call(this);
6262

6363
options = options || {};
6464

6565
this.fd = fd;
66-
this.writable = true;
6766
this.readable = false;
6867
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
69-
}
70-
71-
util.inherits(SyncWriteStream, Stream);
72-
73-
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
74-
var encoding, cb;
75-
76-
// parse arguments
77-
if (arg1) {
78-
if (typeof arg1 === 'string') {
79-
encoding = arg1;
80-
cb = arg2;
81-
} else if (typeof arg1 === 'function') {
82-
cb = arg1;
83-
} else {
84-
throw new Error('Bad arguments');
85-
}
86-
}
87-
assertEncoding(encoding);
88-
89-
// Change strings to buffers. SLOW
90-
if (typeof data === 'string') {
91-
data = Buffer.from(data, encoding);
92-
}
9368

94-
fs.writeSync(this.fd, data, 0, data.length);
69+
this.on('end', () => this._destroy());
70+
}
9571

96-
if (cb) {
97-
process.nextTick(cb);
98-
}
72+
util.inherits(SyncWriteStream, Writable);
9973

74+
SyncWriteStream.prototype._write = function(chunk, encoding, cb) {
75+
fs.writeSync(this.fd, chunk, 0, chunk.length);
76+
cb();
10077
return true;
10178
};
10279

80+
SyncWriteStream.prototype._destroy = function() {
81+
if (this.fd === null) // already destroy()ed
82+
return;
10383

104-
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
105-
if (data) {
106-
this.write(data, arg1, arg2);
107-
}
108-
this.destroy();
109-
};
110-
111-
112-
SyncWriteStream.prototype.destroy = function() {
11384
if (this.autoClose)
11485
fs.closeSync(this.fd);
86+
11587
this.fd = null;
116-
this.emit('close');
11788
return true;
11889
};
11990

120-
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
91+
SyncWriteStream.prototype.destroySoon =
92+
SyncWriteStream.prototype.destroy = function() {
93+
this._destroy();
94+
this.emit('close');
95+
return true;
96+
};
12197

12298
exports.SyncWriteStream = SyncWriteStream;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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+
console.log(JSON.stringify([process.stdout, process.stderr].map((stdio) => ({
14+
instance: stdio instanceof stream.Writable,
15+
readable: stdio.readable,
16+
writable: stdio.writable,
17+
}))));
18+
19+
return;
20+
}
21+
22+
common.refreshTmpDir();
23+
24+
const filename = path.join(common.tmpDir, 'stdout');
25+
const stdoutFd = fs.openSync(filename, 'w');
26+
27+
const proc = spawn(process.execPath, [__filename, 'child'], {
28+
stdio: ['inherit', stdoutFd, stdoutFd ]
29+
});
30+
31+
proc.on('close', common.mustCall(() => {
32+
fs.closeSync(stdoutFd);
33+
34+
assert.deepStrictEqual(JSON.parse(fs.readFileSync(filename, 'utf8')), [
35+
{ instance: true, readable: false, writable: true },
36+
{ instance: true, readable: false, writable: true }
37+
]);
38+
}));

0 commit comments

Comments
 (0)