Skip to content

Commit 107133c

Browse files
authored
quic: allow null body when opening streams
Signed-off-by: Efe Karasakal <hi@efe.dev> PR-URL: #66690 Reviewed-By: Tim Perry <pimterry@gmail.com>
1 parent 8ae0ad0 commit 107133c

3 files changed

Lines changed: 60 additions & 26 deletions

File tree

‎lib/internal/quic/quic.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,7 @@ function invokeOnerror(fn, error) {
12531253
}
12541254

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

‎src/quic/streams.cc‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,14 @@ std::unique_ptr<DataQueue::Entry> CreateEntryFromBuffer(
290290

291291
Maybe<std::shared_ptr<DataQueue>> Stream::GetDataQueueFromSource(
292292
Environment* env, Local<Value> value) {
293-
DCHECK_IMPLIES(!value->IsUndefined(), value->IsObject());
293+
DCHECK(value->IsUndefined() || value->IsNull() || value->IsObject());
294294
std::vector<std::unique_ptr<DataQueue::Entry>> entries;
295295
if (value->IsUndefined()) {
296296
// Return an empty DataQueue.
297297
return Just(std::shared_ptr<DataQueue>());
298+
} else if (value->IsNull()) {
299+
// Return an empty, completed data source.
300+
return Just(DataQueue::CreateIdempotent(std::move(entries)));
298301
} else if (value->IsArrayBuffer()) {
299302
auto buffer = value.As<ArrayBuffer>();
300303
auto length = buffer->ByteLength();

‎test/parallel/test-quic-stream-zero-length.mjs‎

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,57 @@ if (!hasQuic) {
1515
const { listen, connect } = await import('../common/quic.mjs');
1616
const { bytes } = await import('stream/iter');
1717

18-
const serverDone = Promise.withResolvers();
19-
20-
const serverEndpoint = await listen(mustCall((serverSession) => {
21-
serverSession.onstream = mustCall(async (stream) => {
22-
const received = await bytes(stream);
23-
assert.strictEqual(received.byteLength, 0);
24-
stream.writer.endSync();
25-
await stream.closed;
26-
serverSession.close();
27-
serverDone.resolve();
28-
});
29-
}));
30-
31-
const clientSession = await connect(serverEndpoint.address);
32-
await clientSession.opened;
33-
34-
const stream = await clientSession.createBidirectionalStream();
35-
stream.setBody(null);
36-
37-
await dump(stream);
38-
39-
await Promise.all([stream.closed, serverDone.promise]);
40-
await clientSession.close();
41-
await serverEndpoint.close();
18+
{
19+
const serverDone = Promise.withResolvers();
20+
21+
const serverEndpoint = await listen(mustCall((serverSession) => {
22+
serverSession.onstream = mustCall(async (stream) => {
23+
const received = await bytes(stream);
24+
assert.strictEqual(received.byteLength, 0);
25+
stream.writer.endSync();
26+
await stream.closed;
27+
serverSession.close();
28+
serverDone.resolve();
29+
});
30+
}));
31+
32+
const clientSession = await connect(serverEndpoint.address);
33+
await clientSession.opened;
34+
35+
const stream = await clientSession.createBidirectionalStream();
36+
stream.setBody(null);
37+
38+
await dump(stream);
39+
40+
await Promise.all([stream.closed, serverDone.promise]);
41+
await clientSession.close();
42+
await serverEndpoint.close();
43+
}
44+
45+
// Stream via createBidirectionalStream({ body: null }).
46+
{
47+
const serverDone = Promise.withResolvers();
48+
49+
const serverEndpoint = await listen(mustCall((serverSession) => {
50+
serverSession.onstream = mustCall(async (stream) => {
51+
const received = await bytes(stream);
52+
assert.strictEqual(received.byteLength, 0);
53+
stream.writer.endSync();
54+
await stream.closed;
55+
serverSession.close();
56+
serverDone.resolve();
57+
});
58+
}));
59+
60+
const clientSession = await connect(serverEndpoint.address);
61+
await clientSession.opened;
62+
63+
const stream =
64+
await clientSession.createBidirectionalStream({ body: null });
65+
66+
await dump(stream);
67+
68+
await Promise.all([stream.closed, serverDone.promise]);
69+
await clientSession.close();
70+
await serverEndpoint.close();
71+
}

0 commit comments

Comments
 (0)