diff --git a/lib/internal/streams/transform.js b/lib/internal/streams/transform.js index 2f4d498bc780a3..a37ec17f9e06cd 100644 --- a/lib/internal/streams/transform.js +++ b/lib/internal/streams/transform.js @@ -174,7 +174,7 @@ Transform.prototype._write = function(chunk, encoding, callback) { return; } - if (val != null) { + if (val !== undefined) { this.push(val); } diff --git a/test/parallel/test-stream-transform-callback-null.js b/test/parallel/test-stream-transform-callback-null.js new file mode 100644 index 00000000000000..889d827066bc78 --- /dev/null +++ b/test/parallel/test-stream-transform-callback-null.js @@ -0,0 +1,66 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { Transform } = require('stream'); + +// Passing null as the second argument to the transform callback should be +// equivalent to calling this.push(null), signaling the end of the readable +// side. Refs: https://github.com/nodejs/node/issues/62769 + +{ + // Calling callback(null, null) should end the readable side of the transform stream. + const t = new Transform({ + transform(chunk, encoding, callback) { + callback(null, null); + }, + }); + + t.on('end', common.mustCall()); + t.on('data', (chunk) => { + // Null sentinel should not appear as a data chunk. + assert.fail('unexpected data event'); + }); + + t.write('hello'); + t.end(); +} + +{ + // Verify callback(null, data) still works normally. + const t = new Transform({ + transform(chunk, encoding, callback) { + callback(null, chunk); + }, + }); + + const received = []; + t.on('data', (chunk) => received.push(chunk.toString())); + t.on('end', common.mustCall(() => { + assert.deepStrictEqual(received, ['hello']); + })); + + t.write('hello'); + t.end(); +} + +{ + // Verify callback() with no second arg still works (no push). + const t = new Transform({ + transform(chunk, encoding, callback) { + callback(); + }, + flush(callback) { + callback(null, 'flushed'); + }, + }); + + const received = []; + t.on('data', (chunk) => received.push(chunk.toString())); + t.on('end', common.mustCall(() => { + assert.deepStrictEqual(received, ['flushed']); + })); + + t.write('hello'); + t.end(); +}