From d111d7b91c16ec420f231da4f6877a9b446de6d8 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 21 Mar 2018 13:01:41 +0100 Subject: [PATCH] stream: give error message if `write()` cb called twice Otherwise, this condition would result in an error that just reads `cb is not a function`, and which additionally could have lost stack trace context through a `process.nextTick()` call. PR-URL: https://github.com/nodejs/node/pull/19510 Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Matteo Collina --- lib/_stream_writable.js | 4 ++ .../test-stream-writable-write-cb-twice.js | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 test/parallel/test-stream-writable-write-cb-twice.js diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index df1d4076d02..d21daf0541d 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -37,6 +37,7 @@ const { getHighWaterMark } = require('internal/streams/state'); const { ERR_INVALID_ARG_TYPE, ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK, ERR_STREAM_CANNOT_PIPE, ERR_STREAM_DESTROYED, ERR_STREAM_NULL_VALUES, @@ -449,6 +450,9 @@ function onwrite(stream, er) { var sync = state.sync; var cb = state.writecb; + if (typeof cb !== 'function') + throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); if (er) diff --git a/test/parallel/test-stream-writable-write-cb-twice.js b/test/parallel/test-stream-writable-write-cb-twice.js new file mode 100644 index 00000000000..f066a0ecc4f --- /dev/null +++ b/test/parallel/test-stream-writable-write-cb-twice.js @@ -0,0 +1,49 @@ +'use strict'; +const common = require('../common'); +const { Writable } = require('stream'); + +{ + // Sync + Sync + const writable = new Writable({ + write: common.mustCall((buf, enc, cb) => { + cb(); + common.expectsError(cb, { + code: 'ERR_MULTIPLE_CALLBACK', + type: Error + }); + }) + }); + writable.write('hi'); +} + +{ + // Sync + Async + const writable = new Writable({ + write: common.mustCall((buf, enc, cb) => { + cb(); + process.nextTick(() => { + common.expectsError(cb, { + code: 'ERR_MULTIPLE_CALLBACK', + type: Error + }); + }); + }) + }); + writable.write('hi'); +} + +{ + // Async + Async + const writable = new Writable({ + write: common.mustCall((buf, enc, cb) => { + process.nextTick(cb); + process.nextTick(() => { + common.expectsError(cb, { + code: 'ERR_MULTIPLE_CALLBACK', + type: Error + }); + }); + }) + }); + writable.write('hi'); +}