Skip to content

Commit a349bc1

Browse files
addaleaxjasnell
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]>
1 parent c6ee8ed commit a349bc1

File tree

2 files changed

+58
-42
lines changed

2 files changed

+58
-42
lines changed

lib/internal/fs.js

+18-42
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

@@ -14,65 +14,41 @@ exports.assertEncoding = assertEncoding;
1414

1515
// Temporary hack for process.stdout and process.stderr when piped to files.
1616
function SyncWriteStream(fd, options) {
17-
Stream.call(this);
17+
Writable.call(this);
1818

1919
options = options || {};
2020

2121
this.fd = fd;
22-
this.writable = true;
2322
this.readable = false;
2423
this.autoClose = options.autoClose === undefined ? true : options.autoClose;
25-
}
26-
27-
util.inherits(SyncWriteStream, Stream);
28-
29-
SyncWriteStream.prototype.write = function(data, arg1, arg2) {
30-
var encoding, cb;
31-
32-
// parse arguments
33-
if (arg1) {
34-
if (typeof arg1 === 'string') {
35-
encoding = arg1;
36-
cb = arg2;
37-
} else if (typeof arg1 === 'function') {
38-
cb = arg1;
39-
} else {
40-
throw new Error('Bad arguments');
41-
}
42-
}
43-
assertEncoding(encoding);
4424

45-
// Change strings to buffers. SLOW
46-
if (typeof data === 'string') {
47-
data = Buffer.from(data, encoding);
48-
}
25+
this.on('end', () => this._destroy());
26+
}
4927

50-
fs.writeSync(this.fd, data, 0, data.length);
51-
52-
if (cb) {
53-
process.nextTick(cb);
54-
}
28+
util.inherits(SyncWriteStream, Writable);
5529

30+
SyncWriteStream.prototype._write = function(chunk, encoding, cb) {
31+
fs.writeSync(this.fd, chunk, 0, chunk.length);
32+
cb();
5633
return true;
5734
};
5835

36+
SyncWriteStream.prototype._destroy = function() {
37+
if (this.fd === null) // already destroy()ed
38+
return;
5939

60-
SyncWriteStream.prototype.end = function(data, arg1, arg2) {
61-
if (data) {
62-
this.write(data, arg1, arg2);
63-
}
64-
this.destroy();
65-
};
66-
67-
68-
SyncWriteStream.prototype.destroy = function() {
6940
if (this.autoClose)
7041
fs.closeSync(this.fd);
42+
7143
this.fd = null;
72-
this.emit('close');
7344
return true;
7445
};
7546

76-
SyncWriteStream.prototype.destroySoon = SyncWriteStream.prototype.destroy;
47+
SyncWriteStream.prototype.destroySoon =
48+
SyncWriteStream.prototype.destroy = function() {
49+
this._destroy();
50+
this.emit('close');
51+
return true;
52+
};
7753

7854
exports.SyncWriteStream = SyncWriteStream;
+40
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)