Commit 107133ceb87 for nodejs

commit 107133ceb87ad9e7c33f3234a2cef652d69055ac
Author: Efe Karasakal <hi@efe.dev>
Date:   Mon Oct 19 23:16:23 2026 +0200

    quic: allow null body when opening streams

    Signed-off-by: Efe Karasakal <hi@efe.dev>
    PR-URL: https://github.com/nodejs/node/pull/66690
    Reviewed-By: Tim Perry <pimterry@gmail.com>

diff --git a/lib/internal/quic/quic.js b/lib/internal/quic/quic.js
index d80b5846682..2d75c5cbe00 100644
--- a/lib/internal/quic/quic.js
+++ b/lib/internal/quic/quic.js
@@ -1253,7 +1253,7 @@ function invokeOnerror(fn, error) {
 }

 function validateBody(body) {
-  if (body === undefined) return body;
+  if (body === undefined || body === null) return body;
   // ArrayBuffers, SharedArrayBuffers, and ArrayBufferViews are passed
   // through to the C++ layer which copies the bytes into its own
   // BackingStore. Callers can therefore safely reuse or mutate their
@@ -1290,6 +1290,7 @@ function validateBody(body) {
     'ArrayBufferView',
     'Blob',
     'FileHandle',
+    'null',
   ], body);
 }

diff --git a/src/quic/streams.cc b/src/quic/streams.cc
index 8e9d3570938..0a2af12d366 100644
--- a/src/quic/streams.cc
+++ b/src/quic/streams.cc
@@ -290,11 +290,14 @@ std::unique_ptr<DataQueue::Entry> CreateEntryFromBuffer(

 Maybe<std::shared_ptr<DataQueue>> Stream::GetDataQueueFromSource(
     Environment* env, Local<Value> value) {
-  DCHECK_IMPLIES(!value->IsUndefined(), value->IsObject());
+  DCHECK(value->IsUndefined() || value->IsNull() || value->IsObject());
   std::vector<std::unique_ptr<DataQueue::Entry>> entries;
   if (value->IsUndefined()) {
     // Return an empty DataQueue.
     return Just(std::shared_ptr<DataQueue>());
+  } else if (value->IsNull()) {
+    // Return an empty, completed data source.
+    return Just(DataQueue::CreateIdempotent(std::move(entries)));
   } else if (value->IsArrayBuffer()) {
     auto buffer = value.As<ArrayBuffer>();
     auto length = buffer->ByteLength();
diff --git a/test/parallel/test-quic-stream-zero-length.mjs b/test/parallel/test-quic-stream-zero-length.mjs
index 1c745ffc264..32f7bc52440 100644
--- a/test/parallel/test-quic-stream-zero-length.mjs
+++ b/test/parallel/test-quic-stream-zero-length.mjs
@@ -15,27 +15,57 @@ if (!hasQuic) {
 const { listen, connect } = await import('../common/quic.mjs');
 const { bytes } = await import('stream/iter');

-const serverDone = Promise.withResolvers();
-
-const serverEndpoint = await listen(mustCall((serverSession) => {
-  serverSession.onstream = mustCall(async (stream) => {
-    const received = await bytes(stream);
-    assert.strictEqual(received.byteLength, 0);
-    stream.writer.endSync();
-    await stream.closed;
-    serverSession.close();
-    serverDone.resolve();
-  });
-}));
-
-const clientSession = await connect(serverEndpoint.address);
-await clientSession.opened;
-
-const stream = await clientSession.createBidirectionalStream();
-stream.setBody(null);
-
-await dump(stream);
-
-await Promise.all([stream.closed, serverDone.promise]);
-await clientSession.close();
-await serverEndpoint.close();
+{
+  const serverDone = Promise.withResolvers();
+
+  const serverEndpoint = await listen(mustCall((serverSession) => {
+    serverSession.onstream = mustCall(async (stream) => {
+      const received = await bytes(stream);
+      assert.strictEqual(received.byteLength, 0);
+      stream.writer.endSync();
+      await stream.closed;
+      serverSession.close();
+      serverDone.resolve();
+    });
+  }));
+
+  const clientSession = await connect(serverEndpoint.address);
+  await clientSession.opened;
+
+  const stream = await clientSession.createBidirectionalStream();
+  stream.setBody(null);
+
+  await dump(stream);
+
+  await Promise.all([stream.closed, serverDone.promise]);
+  await clientSession.close();
+  await serverEndpoint.close();
+}
+
+// Stream via createBidirectionalStream({ body: null }).
+{
+  const serverDone = Promise.withResolvers();
+
+  const serverEndpoint = await listen(mustCall((serverSession) => {
+    serverSession.onstream = mustCall(async (stream) => {
+      const received = await bytes(stream);
+      assert.strictEqual(received.byteLength, 0);
+      stream.writer.endSync();
+      await stream.closed;
+      serverSession.close();
+      serverDone.resolve();
+    });
+  }));
+
+  const clientSession = await connect(serverEndpoint.address);
+  await clientSession.opened;
+
+  const stream =
+    await clientSession.createBidirectionalStream({ body: null });
+
+  await dump(stream);
+
+  await Promise.all([stream.closed, serverDone.promise]);
+  await clientSession.close();
+  await serverEndpoint.close();
+}