Skip to content

Commit 1f20912

Browse files
committedFeb 25, 2020
stream: throw invalid argument errors
Logic errors that do not depend on stream state should throw instead of invoke callback and emit error. PR-URL: #31831 Refs: #31818 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 9403250 commit 1f20912

10 files changed

+92
-88
lines changed
 

‎lib/_stream_writable.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,8 @@ Writable.prototype.write = function(chunk, encoding, cb) {
273273
cb = nop;
274274
}
275275

276-
let err;
277-
if (state.ending) {
278-
err = new ERR_STREAM_WRITE_AFTER_END();
279-
} else if (state.destroyed) {
280-
err = new ERR_STREAM_DESTROYED('write');
281-
} else if (chunk === null) {
282-
err = new ERR_STREAM_NULL_VALUES();
276+
if (chunk === null) {
277+
throw new ERR_STREAM_NULL_VALUES();
283278
} else if (!state.objectMode) {
284279
if (typeof chunk === 'string') {
285280
if (state.decodeStrings !== false) {
@@ -292,11 +287,18 @@ Writable.prototype.write = function(chunk, encoding, cb) {
292287
chunk = Stream._uint8ArrayToBuffer(chunk);
293288
encoding = 'buffer';
294289
} else {
295-
err = new ERR_INVALID_ARG_TYPE(
290+
throw new ERR_INVALID_ARG_TYPE(
296291
'chunk', ['string', 'Buffer', 'Uint8Array'], chunk);
297292
}
298293
}
299294

295+
let err;
296+
if (state.ending) {
297+
err = new ERR_STREAM_WRITE_AFTER_END();
298+
} else if (state.destroyed) {
299+
err = new ERR_STREAM_DESTROYED('write');
300+
}
301+
300302
if (err) {
301303
process.nextTick(cb, err);
302304
errorOrDestroy(this, err, true);

‎test/parallel/test-fs-write-stream.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,12 @@ tmpdir.refresh();
5656
// Throws if data is not of type Buffer.
5757
{
5858
const stream = fs.createWriteStream(file);
59-
stream.on('error', common.expectsError({
59+
stream.on('error', common.mustNotCall());
60+
assert.throws(() => {
61+
stream.write(42);
62+
}, {
6063
code: 'ERR_INVALID_ARG_TYPE',
6164
name: 'TypeError'
62-
}));
63-
stream.write(42, null, common.expectsError({
64-
code: 'ERR_INVALID_ARG_TYPE',
65-
name: 'TypeError'
66-
}));
65+
});
6766
stream.destroy();
6867
}

‎test/parallel/test-net-socket-write-error.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
const common = require('../common');
44
const net = require('net');
5+
const assert = require('assert');
56

67
const server = net.createServer().listen(0, connectToServer);
78

89
function connectToServer() {
910
const client = net.createConnection(this.address().port, () => {
10-
client.write(1337, common.expectsError({
11+
client.on('error', common.mustNotCall());
12+
assert.throws(() => {
13+
client.write(1337);
14+
}, {
1115
code: 'ERR_INVALID_ARG_TYPE',
1216
name: 'TypeError'
13-
}));
14-
client.on('error', common.expectsError({
15-
code: 'ERR_INVALID_ARG_TYPE',
16-
name: 'TypeError'
17-
}));
17+
});
1818

1919
client.destroy();
2020
})
+10-10
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
'use strict';
22
const common = require('../common');
33
const net = require('net');
4-
4+
const assert = require('assert');
55
const socket = net.Stream({ highWaterMark: 0 });
66

77
// Make sure that anything besides a buffer or a string throws.
8-
socket.write(null, common.expectsError({
8+
socket.on('error', common.mustNotCall());
9+
assert.throws(() => {
10+
socket.write(null);
11+
}, {
912
code: 'ERR_STREAM_NULL_VALUES',
1013
name: 'TypeError',
1114
message: 'May not write null values to stream'
12-
}));
13-
socket.on('error', common.expectsError({
14-
code: 'ERR_STREAM_NULL_VALUES',
15-
name: 'TypeError',
16-
message: 'May not write null values to stream'
17-
}));
15+
});
1816

1917
[
2018
true,
@@ -29,10 +27,12 @@ socket.on('error', common.expectsError({
2927
].forEach((value) => {
3028
// We need to check the callback since 'error' will only
3129
// be emitted once per instance.
32-
socket.write(value, common.expectsError({
30+
assert.throws(() => {
31+
socket.write(value);
32+
}, {
3333
code: 'ERR_INVALID_ARG_TYPE',
3434
name: 'TypeError',
3535
message: 'The "chunk" argument must be of type string or an instance of ' +
3636
`Buffer or Uint8Array.${common.invalidArgTypeHelper(value)}`
37-
}));
37+
});
3838
});

‎test/parallel/test-stream-writable-invalid-chunk.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,21 @@
22

33
const common = require('../common');
44
const stream = require('stream');
5+
const assert = require('assert');
56

67
function testWriteType(val, objectMode, code) {
78
const writable = new stream.Writable({
89
objectMode,
910
write: () => {}
1011
});
11-
if (!code) {
12-
writable.on('error', common.mustNotCall());
12+
writable.on('error', common.mustNotCall());
13+
if (code) {
14+
assert.throws(() => {
15+
writable.write(val);
16+
}, { code });
1317
} else {
14-
writable.on('error', common.expectsError({
15-
code: code,
16-
}));
18+
writable.write(val);
1719
}
18-
writable.write(val);
1920
}
2021

2122
testWriteType([], false, 'ERR_INVALID_ARG_TYPE');

‎test/parallel/test-stream-writable-null.js

+12-21
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,22 @@ class MyWritable extends stream.Writable {
1616

1717
{
1818
const m = new MyWritable({ objectMode: true });
19-
m.write(null, (err) => assert.ok(err));
20-
m.on('error', common.expectsError({
21-
code: 'ERR_STREAM_NULL_VALUES',
22-
name: 'TypeError',
23-
message: 'May not write null values to stream'
24-
}));
25-
}
26-
27-
{ // Should not throw.
28-
const m = new MyWritable({ objectMode: true }).on('error', assert);
29-
m.write(null, assert);
19+
m.on('error', common.mustNotCall());
20+
assert.throws(() => {
21+
m.write(null);
22+
}, {
23+
code: 'ERR_STREAM_NULL_VALUES'
24+
});
3025
}
3126

3227
{
3328
const m = new MyWritable();
34-
m.write(false, (err) => assert.ok(err));
35-
m.on('error', common.expectsError({
36-
code: 'ERR_INVALID_ARG_TYPE',
37-
name: 'TypeError'
38-
}));
39-
}
40-
41-
{ // Should not throw.
42-
const m = new MyWritable().on('error', assert);
43-
m.write(false, assert);
29+
m.on('error', common.mustNotCall());
30+
assert.throws(() => {
31+
m.write(false);
32+
}, {
33+
code: 'ERR_INVALID_ARG_TYPE'
34+
});
4435
}
4536

4637
{ // Should not throw.

‎test/parallel/test-stream-writable-write-error.js

+23-15
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,27 @@ const assert = require('assert');
44

55
const { Writable } = require('stream');
66

7-
function expectError(w, arg, code) {
8-
let errorCalled = false;
9-
let ticked = false;
10-
w.write(arg, common.mustCall((err) => {
11-
assert.strictEqual(ticked, true);
12-
assert.strictEqual(errorCalled, false);
13-
assert.strictEqual(err.code, code);
14-
}));
15-
ticked = true;
16-
w.on('error', common.mustCall((err) => {
17-
errorCalled = true;
18-
assert.strictEqual(err.code, code);
19-
}));
7+
function expectError(w, arg, code, sync) {
8+
if (sync) {
9+
if (code) {
10+
assert.throws(() => w.write(arg), { code });
11+
} else {
12+
w.write(arg);
13+
}
14+
} else {
15+
let errorCalled = false;
16+
let ticked = false;
17+
w.write(arg, common.mustCall((err) => {
18+
assert.strictEqual(ticked, true);
19+
assert.strictEqual(errorCalled, false);
20+
assert.strictEqual(err.code, code);
21+
}));
22+
ticked = true;
23+
w.on('error', common.mustCall((err) => {
24+
errorCalled = true;
25+
assert.strictEqual(err.code, code);
26+
}));
27+
}
2028
}
2129

2230
function test(autoDestroy) {
@@ -43,15 +51,15 @@ function test(autoDestroy) {
4351
autoDestroy,
4452
_write() {}
4553
});
46-
expectError(w, null, 'ERR_STREAM_NULL_VALUES');
54+
expectError(w, null, 'ERR_STREAM_NULL_VALUES', true);
4755
}
4856

4957
{
5058
const w = new Writable({
5159
autoDestroy,
5260
_write() {}
5361
});
54-
expectError(w, {}, 'ERR_INVALID_ARG_TYPE');
62+
expectError(w, {}, 'ERR_INVALID_ARG_TYPE', true);
5563
}
5664
}
5765

‎test/parallel/test-stream2-writable.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,12 @@ const helloWorldBuffer = Buffer.from('hello world');
422422
{
423423
// Verify that error is only emitted once when failing in write.
424424
const w = new W();
425-
w.on('error', common.mustCall((err) => {
426-
assert.strictEqual(w._writableState.errorEmitted, true);
427-
assert.strictEqual(err.code, 'ERR_STREAM_NULL_VALUES');
428-
}));
429-
w.write(null);
430-
w.destroy(new Error());
425+
w.on('error', common.mustNotCall());
426+
assert.throws(() => {
427+
w.write(null);
428+
}, {
429+
code: 'ERR_STREAM_NULL_VALUES'
430+
});
431431
}
432432

433433
{

‎test/parallel/test-zlib-invalid-input.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ const unzips = [
4343
];
4444

4545
nonStringInputs.forEach(common.mustCall((input) => {
46-
// zlib.gunzip should not throw an error when called with bad input.
47-
zlib.gunzip(input, (err, buffer) => {
48-
// zlib.gunzip should pass the error to the callback.
49-
assert.ok(err);
46+
assert.throws(() => {
47+
zlib.gunzip(input);
48+
}, {
49+
name: 'TypeError',
50+
code: 'ERR_INVALID_ARG_TYPE'
5051
});
5152
}, nonStringInputs.length));
5253

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
'use strict';
22

33
const common = require('../common');
4+
const assert = require('assert');
45
const { Gunzip } = require('zlib');
56

67
const gunzip = new Gunzip({ objectMode: true });
7-
gunzip.write({}, common.expectsError({
8-
name: 'TypeError'
9-
}));
10-
gunzip.on('error', common.expectsError({
11-
name: 'TypeError'
12-
}));
8+
gunzip.on('error', common.mustNotCall());
9+
assert.throws(() => {
10+
gunzip.write({});
11+
}, {
12+
name: 'TypeError',
13+
code: 'ERR_INVALID_ARG_TYPE'
14+
});

0 commit comments

Comments
 (0)
Please sign in to comment.