From b8a169875f7015c35322e2b51c623ac7c78f0d1d Mon Sep 17 00:00:00 2001
From: Gil Pedersen <git@gpost.dk>
Date: Fri, 1 Jul 2022 21:42:26 +0200
Subject: [PATCH] stream: fix Transform with hwm 0 regression

Fixes: https://github.com/nodejs/node/issues/40935
Refs: https://github.com/nodejs/node/pull/40947
Refs: https://github.com/nodejs/node/issues/42457
---
 lib/internal/streams/transform.js           |  2 +-
 test/parallel/test-stream-transform-hwm0.js | 28 +++++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 test/parallel/test-stream-transform-hwm0.js

diff --git a/lib/internal/streams/transform.js b/lib/internal/streams/transform.js
index fdac76e4062b4b..3c5cac92467a21 100644
--- a/lib/internal/streams/transform.js
+++ b/lib/internal/streams/transform.js
@@ -165,12 +165,12 @@ Transform.prototype._write = function(chunk, encoding, callback) {
       wState.ended || // Backwards compat.
       length === rState.length || // Backwards compat.
       rState.length < rState.highWaterMark ||
-      rState.highWaterMark === 0 ||
       rState.length === 0
     ) {
       callback();
     } else {
       this[kCallback] = callback;
+      rState.needReadable = true; // Always call _read() on the next read() call
     }
   });
 };
diff --git a/test/parallel/test-stream-transform-hwm0.js b/test/parallel/test-stream-transform-hwm0.js
new file mode 100644
index 00000000000000..8e8971f21fa472
--- /dev/null
+++ b/test/parallel/test-stream-transform-hwm0.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('assert');
+const { Transform } = require('stream');
+
+const t = new Transform({
+  objectMode: true, highWaterMark: 0,
+  transform(chunk, enc, callback) {
+    process.nextTick(() => callback(null, chunk, enc));
+  }
+});
+
+assert.strictEqual(t.write(1), false);
+t.on('drain', common.mustCall(() => {
+  assert.strictEqual(t.write(2), false);
+  t.end();
+}));
+
+t.once('readable', common.mustCall(() => {
+  assert.strictEqual(t.read(), 1);
+  setImmediate(common.mustCall(() => {
+    assert.strictEqual(t.read(), null);
+    t.once('readable', common.mustCall(() => {
+      assert.strictEqual(t.read(), 2);
+    }));
+  }));
+}));