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'); +}