From 83e4cb2057e2878345fdbcfabc7107cda139bfa0 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 26 Jul 2026 22:13:37 +0200 Subject: [PATCH 01/10] quic: write desired size needs update on maxstream Without this update the streams can stall, if the chunks are close or bigger than the window size. Signed-off-by: Marten Richter --- src/quic/http3.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/quic/http3.cc b/src/quic/http3.cc index efaf1959427058..125d53b1273d7b 100644 --- a/src/quic/http3.cc +++ b/src/quic/http3.cc @@ -375,6 +375,7 @@ class Http3ApplicationImpl final : public Session::Application { Debug(&session(), "HTTP/3 application extending max stream data to %" PRIu64, max_data); + stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side nghttp3_conn_unblock_stream(*this, stream->id()); } From cffb9bce663e16beddea7e66b51c4567f4041b64 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Sun, 26 Jul 2026 22:29:53 +0200 Subject: [PATCH 02/10] quic: Fix lint --- src/quic/http3.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quic/http3.cc b/src/quic/http3.cc index 125d53b1273d7b..ba4b5c9eb0ffec 100644 --- a/src/quic/http3.cc +++ b/src/quic/http3.cc @@ -375,7 +375,7 @@ class Http3ApplicationImpl final : public Session::Application { Debug(&session(), "HTTP/3 application extending max stream data to %" PRIu64, max_data); - stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side + stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side nghttp3_conn_unblock_stream(*this, stream->id()); } From 910daf52e30db2da6b06ea44a9588ae940c19e83 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 07:39:21 +0200 Subject: [PATCH 03/10] quic: add test for maxstreamdata buffer stalls Co-authored-by: Tim Perry --- ...3-maxstreamdata-external-buffer-failure.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js new file mode 100644 index 00000000000000..f4dcbb422f7919 --- /dev/null +++ b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js @@ -0,0 +1,80 @@ +// Flags: --experimental-quic --experimental-stream-iter --no-warnings + +// Test: Quic maxstreamdata updates on http/3 +// Client sends a body that precisely fills the window size, +// and verifies that it is data transfer is not stalled. + +import { hasQuic, skip, mustCall } from '../common/index.mjs'; +import assert from 'node:assert'; +import { readFile } from 'node:fs/promises'; +import { setTimeout as sleep } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC is not enabled'); +} +const { listen, connect } = await import('node:quic'); +const { createPrivateKey } = await import('node:crypto'); +const { drainableProtocol } = await import('stream/iter'); + +const keys = 'test/fixtures/keys'; +const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); +const cert = await readFile(`${keys}/agent1-cert.pem`); + +const WINDOW = 4096; +// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for +// the HEADERS frame below, 3 for the DATA frame header). The send buffer then +// empties at the same moment the window reaches zero, leaving nothing in +// flight to ack. Any other size leaves bytes queued, and the ack for those +// wakes the writer instead, hiding the bug. +const BODY = WINDOW - 11; + +let letServerRead; +const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); + +const endpoint = await listen((session) => { + session.onstream = async (stream) => { + await serverMayRead; + for await (const _ of stream) { /* reading extends the window */ } + }; +}, { + sni: { '*': { keys: [key], certs: [cert] } }, + transportParams: { + initialMaxStreamDataBidiRemote: WINDOW, + initialMaxData: 1024 * 1024, + }, + onheaders() { this.sendHeaders({ ':status': '200' }); }, +}); + +const session = await connect(endpoint.address, { + servername: 'localhost', + verifyPeer: 'manual', +}); +await session.opened; + +// Budget well above the window, so the window is what stops the writer. +const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); +stream.sendHeaders({ + ':method': 'POST', + ':path': '/', + ':scheme': 'https', + ':authority': 'localhost', +}, { terminal: false }); + +const writer = stream.writer; +writer.writeSync(new Uint8Array(BODY)); + +// Long enough for every byte to be acked. The peer acks as data arrives, +// whether or not its application has read any of it, so by now the window is +// exhausted, the send buffer is empty, and no further ACK can arrive. +await sleep(500); + +const watchdog = setTimeout(() => { + console.error('STALLED: no drain after MAX_STREAM_DATA'); + process.exit(1); +}, 5000); + +letServerRead(); // extend the window, with no ack attached +await writer[drainableProtocol](); + +clearTimeout(watchdog); +process.exit(0); \ No newline at end of file From ddb84d61366805d9bd8cbc5ae7b0e6ee40aedc35 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 07:51:45 +0200 Subject: [PATCH 04/10] quic: rename test --- ....js => test-quic-h3-maxstreamdata-external-buffer-failure.mjs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/parallel/{test-quic-h3-maxstreamdata-external-buffer-failure.js => test-quic-h3-maxstreamdata-external-buffer-failure.mjs} (100%) diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs similarity index 100% rename from test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.js rename to test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs From 0db11eadc2d01fbe18f8fa31945e2a757d6726a2 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 08:03:51 +0200 Subject: [PATCH 05/10] quic: fix streamaxdata for non http/3 --- src/quic/application.cc | 1 + ...-maxstreamdata-external-buffer-failure.mjs | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs diff --git a/src/quic/application.cc b/src/quic/application.cc index 688a1309dea552..9740634568194e 100644 --- a/src/quic/application.cc +++ b/src/quic/application.cc @@ -425,6 +425,7 @@ class DefaultApplication final : public Session::Application { // The peer granted more flow control for this stream. Re-schedule // it so SendPendingData will resume writing. DCHECK_NOT_NULL(stream); + stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side stream->Schedule(&stream_queue_); } diff --git a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs new file mode 100644 index 00000000000000..c7b63df4f9daa7 --- /dev/null +++ b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs @@ -0,0 +1,75 @@ +// Flags: --experimental-quic --experimental-stream-iter --no-warnings + +// Test: Quic maxstreamdata updates on pure quic +// Client sends a body that precisely fills the window size, +// and verifies that it is data transfer is not stalled. + +import { hasQuic, skip, mustCall } from '../common/index.mjs'; +import assert from 'node:assert'; +import { readFile } from 'node:fs/promises'; +import { setTimeout as sleep } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC is not enabled'); +} +const { listen, connect } = await import('node:quic'); +const { createPrivateKey } = await import('node:crypto'); +const { drainableProtocol } = await import('stream/iter'); + +const keys = 'test/fixtures/keys'; +const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); +const cert = await readFile(`${keys}/agent1-cert.pem`); + +const WINDOW = 4096; +// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for +// the HEADERS frame below, 3 for the DATA frame header). The send buffer then +// empties at the same moment the window reaches zero, leaving nothing in +// flight to ack. Any other size leaves bytes queued, and the ack for those +// wakes the writer instead, hiding the bug. +const BODY = WINDOW; + +let letServerRead; +const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); + +const endpoint = await listen((session) => { + session.onstream = async (stream) => { + await serverMayRead; + for await (const _ of stream) { /* reading extends the window */ } + }; +}, { + alpn: 'foo', + sni: { '*': { keys: [key], certs: [cert] } }, + transportParams: { + initialMaxStreamDataBidiRemote: WINDOW, + initialMaxData: 1024 * 1024, + } +}); + +const session = await connect(endpoint.address, { + servername: 'localhost', + verifyPeer: 'manual', + alpn: 'foo' +}); +await session.opened; + +// Budget well above the window, so the window is what stops the writer. +const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); + +const writer = stream.writer; +writer.writeSync(new Uint8Array(BODY)); + +// Long enough for every byte to be acked. The peer acks as data arrives, +// whether or not its application has read any of it, so by now the window is +// exhausted, the send buffer is empty, and no further ACK can arrive. +await sleep(500); + +const watchdog = setTimeout(() => { + console.error('STALLED: no drain after MAX_STREAM_DATA'); + process.exit(1); +}, 5000); + +letServerRead(); // extend the window, with no ack attached +await writer[drainableProtocol](); + +clearTimeout(watchdog); +process.exit(0); \ No newline at end of file From f55f05a505c9fc12f2a3cd97eddcd6a676609bff Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 08:09:02 +0200 Subject: [PATCH 06/10] quic: Fix lint --- src/quic/application.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/quic/application.cc b/src/quic/application.cc index 9740634568194e..109771e0f58bac 100644 --- a/src/quic/application.cc +++ b/src/quic/application.cc @@ -425,7 +425,7 @@ class DefaultApplication final : public Session::Application { // The peer granted more flow control for this stream. Re-schedule // it so SendPendingData will resume writing. DCHECK_NOT_NULL(stream); - stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side + stream->UpdateWriteDesiredSize(); // the stream might be blocked on js side stream->Schedule(&stream_queue_); } From ead7e660b2ad1360c0915dd8f5c4bbcfed31bf59 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 07:40:35 +0000 Subject: [PATCH 07/10] quic: fix lint --- ...-maxstreamdata-external-buffer-failure.mjs | 161 +++++++++--------- ...-maxstreamdata-external-buffer-failure.mjs | 151 ++++++++-------- 2 files changed, 157 insertions(+), 155 deletions(-) diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs index f4dcbb422f7919..92666d42bf22b8 100644 --- a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs @@ -1,80 +1,81 @@ -// Flags: --experimental-quic --experimental-stream-iter --no-warnings - -// Test: Quic maxstreamdata updates on http/3 -// Client sends a body that precisely fills the window size, -// and verifies that it is data transfer is not stalled. - -import { hasQuic, skip, mustCall } from '../common/index.mjs'; -import assert from 'node:assert'; -import { readFile } from 'node:fs/promises'; -import { setTimeout as sleep } from 'node:timers/promises'; - -if (!hasQuic) { - skip('QUIC is not enabled'); -} -const { listen, connect } = await import('node:quic'); -const { createPrivateKey } = await import('node:crypto'); -const { drainableProtocol } = await import('stream/iter'); - -const keys = 'test/fixtures/keys'; -const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); -const cert = await readFile(`${keys}/agent1-cert.pem`); - -const WINDOW = 4096; -// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for -// the HEADERS frame below, 3 for the DATA frame header). The send buffer then -// empties at the same moment the window reaches zero, leaving nothing in -// flight to ack. Any other size leaves bytes queued, and the ack for those -// wakes the writer instead, hiding the bug. -const BODY = WINDOW - 11; - -let letServerRead; -const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); - -const endpoint = await listen((session) => { - session.onstream = async (stream) => { - await serverMayRead; - for await (const _ of stream) { /* reading extends the window */ } - }; -}, { - sni: { '*': { keys: [key], certs: [cert] } }, - transportParams: { - initialMaxStreamDataBidiRemote: WINDOW, - initialMaxData: 1024 * 1024, - }, - onheaders() { this.sendHeaders({ ':status': '200' }); }, -}); - -const session = await connect(endpoint.address, { - servername: 'localhost', - verifyPeer: 'manual', -}); -await session.opened; - -// Budget well above the window, so the window is what stops the writer. -const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); -stream.sendHeaders({ - ':method': 'POST', - ':path': '/', - ':scheme': 'https', - ':authority': 'localhost', -}, { terminal: false }); - -const writer = stream.writer; -writer.writeSync(new Uint8Array(BODY)); - -// Long enough for every byte to be acked. The peer acks as data arrives, -// whether or not its application has read any of it, so by now the window is -// exhausted, the send buffer is empty, and no further ACK can arrive. -await sleep(500); - -const watchdog = setTimeout(() => { - console.error('STALLED: no drain after MAX_STREAM_DATA'); - process.exit(1); -}, 5000); - -letServerRead(); // extend the window, with no ack attached -await writer[drainableProtocol](); - -clearTimeout(watchdog); -process.exit(0); \ No newline at end of file +// Flags: --experimental-quic --experimental-stream-iter --no-warnings + +// Test: Quic maxstreamdata updates on http/3 +// Client sends a body that precisely fills the window size, +// and verifies that it is data transfer is not stalled. + +import { hasQuic, skip } from '../common/index.mjs'; +import { readFile } from 'node:fs/promises'; +import { setTimeout as sleep } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC is not enabled'); +} +const { listen, connect } = await import('node:quic'); +const { createPrivateKey } = await import('node:crypto'); +const { drainableProtocol } = await import('stream/iter'); + +const keys = 'test/fixtures/keys'; +const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); +const cert = await readFile(`${keys}/agent1-cert.pem`); + +const WINDOW = 4096; +// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for +// the HEADERS frame below, 3 for the DATA frame header). The send buffer then +// empties at the same moment the window reaches zero, leaving nothing in +// flight to ack. Any other size leaves bytes queued, and the ack for those +// wakes the writer instead, hiding the bug. +const BODY = WINDOW - 11; + +let letServerRead; +const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); + +const endpoint = await listen((session) => { + session.onstream = async (stream) => { + await serverMayRead; + for await (const _ of stream) { + void _; /* reading extends the window */ + } + }; +}, { + sni: { '*': { keys: [key], certs: [cert] } }, + transportParams: { + initialMaxStreamDataBidiRemote: WINDOW, + initialMaxData: 1024 * 1024, + }, + onheaders() { this.sendHeaders({ ':status': '200' }); }, +}); + +const session = await connect(endpoint.address, { + servername: 'localhost', + verifyPeer: 'manual', +}); +await session.opened; + +// Budget well above the window, so the window is what stops the writer. +const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); +stream.sendHeaders({ + ':method': 'POST', + ':path': '/', + ':scheme': 'https', + ':authority': 'localhost', +}, { terminal: false }); + +const writer = stream.writer; +writer.writeSync(new Uint8Array(BODY)); + +// Long enough for every byte to be acked. The peer acks as data arrives, +// whether or not its application has read any of it, so by now the window is +// exhausted, the send buffer is empty, and no further ACK can arrive. +await sleep(500); + +const watchdog = setTimeout(() => { + console.error('STALLED: no drain after MAX_STREAM_DATA'); + process.exit(1); +}, 5000); + +letServerRead(); // Extend the window, with no ack attached +await writer[drainableProtocol](); + +clearTimeout(watchdog); +process.exit(0); diff --git a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs index c7b63df4f9daa7..be34e303a8e76a 100644 --- a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs @@ -1,75 +1,76 @@ -// Flags: --experimental-quic --experimental-stream-iter --no-warnings - -// Test: Quic maxstreamdata updates on pure quic -// Client sends a body that precisely fills the window size, -// and verifies that it is data transfer is not stalled. - -import { hasQuic, skip, mustCall } from '../common/index.mjs'; -import assert from 'node:assert'; -import { readFile } from 'node:fs/promises'; -import { setTimeout as sleep } from 'node:timers/promises'; - -if (!hasQuic) { - skip('QUIC is not enabled'); -} -const { listen, connect } = await import('node:quic'); -const { createPrivateKey } = await import('node:crypto'); -const { drainableProtocol } = await import('stream/iter'); - -const keys = 'test/fixtures/keys'; -const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); -const cert = await readFile(`${keys}/agent1-cert.pem`); - -const WINDOW = 4096; -// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for -// the HEADERS frame below, 3 for the DATA frame header). The send buffer then -// empties at the same moment the window reaches zero, leaving nothing in -// flight to ack. Any other size leaves bytes queued, and the ack for those -// wakes the writer instead, hiding the bug. -const BODY = WINDOW; - -let letServerRead; -const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); - -const endpoint = await listen((session) => { - session.onstream = async (stream) => { - await serverMayRead; - for await (const _ of stream) { /* reading extends the window */ } - }; -}, { - alpn: 'foo', - sni: { '*': { keys: [key], certs: [cert] } }, - transportParams: { - initialMaxStreamDataBidiRemote: WINDOW, - initialMaxData: 1024 * 1024, - } -}); - -const session = await connect(endpoint.address, { - servername: 'localhost', - verifyPeer: 'manual', - alpn: 'foo' -}); -await session.opened; - -// Budget well above the window, so the window is what stops the writer. -const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); - -const writer = stream.writer; -writer.writeSync(new Uint8Array(BODY)); - -// Long enough for every byte to be acked. The peer acks as data arrives, -// whether or not its application has read any of it, so by now the window is -// exhausted, the send buffer is empty, and no further ACK can arrive. -await sleep(500); - -const watchdog = setTimeout(() => { - console.error('STALLED: no drain after MAX_STREAM_DATA'); - process.exit(1); -}, 5000); - -letServerRead(); // extend the window, with no ack attached -await writer[drainableProtocol](); - -clearTimeout(watchdog); -process.exit(0); \ No newline at end of file +// Flags: --experimental-quic --experimental-stream-iter --no-warnings + +// Test: Quic maxstreamdata updates on pure quic +// Client sends a body that precisely fills the window size, +// and verifies that it is data transfer is not stalled. + +import { hasQuic, skip } from '../common/index.mjs'; +import { readFile } from 'node:fs/promises'; +import { setTimeout as sleep } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC is not enabled'); +} +const { listen, connect } = await import('node:quic'); +const { createPrivateKey } = await import('node:crypto'); +const { drainableProtocol } = await import('stream/iter'); + +const keys = 'test/fixtures/keys'; +const key = createPrivateKey(await readFile(`${keys}/agent1-key.pem`)); +const cert = await readFile(`${keys}/agent1-cert.pem`); + +const WINDOW = 4096; +// Fills the window exactly: HTTP/3 spends 11 of those bytes on framing (8 for +// the HEADERS frame below, 3 for the DATA frame header). The send buffer then +// empties at the same moment the window reaches zero, leaving nothing in +// flight to ack. Any other size leaves bytes queued, and the ack for those +// wakes the writer instead, hiding the bug. +const BODY = WINDOW; + +let letServerRead; +const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); + +const endpoint = await listen((session) => { + session.onstream = async (stream) => { + await serverMayRead; + for await (const _ of stream) for await (const _ of stream) { + void _; /* reading extends the window */ + } + }; +}, { + alpn: 'foo', + sni: { '*': { keys: [key], certs: [cert] } }, + transportParams: { + initialMaxStreamDataBidiRemote: WINDOW, + initialMaxData: 1024 * 1024, + } +}); + +const session = await connect(endpoint.address, { + servername: 'localhost', + verifyPeer: 'manual', + alpn: 'foo' +}); +await session.opened; + +// Budget well above the window, so the window is what stops the writer. +const stream = await session.createBidirectionalStream({ budget: 1024 * 1024 }); + +const writer = stream.writer; +writer.writeSync(new Uint8Array(BODY)); + +// Long enough for every byte to be acked. The peer acks as data arrives, +// whether or not its application has read any of it, so by now the window is +// exhausted, the send buffer is empty, and no further ACK can arrive. +await sleep(500); + +const watchdog = setTimeout(() => { + console.error('STALLED: no drain after MAX_STREAM_DATA'); + process.exit(1); +}, 5000); + +letServerRead(); // Extend the window, with no ack attached +await writer[drainableProtocol](); + +clearTimeout(watchdog); +process.exit(0); From 43af13bff9fc15073d8320df7a698d005ae11a67 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 07:49:59 +0000 Subject: [PATCH 08/10] Fix lint2 --- .../test-quic-h3-maxstreamdata-external-buffer-failure.mjs | 4 +--- .../test-quic-maxstreamdata-external-buffer-failure.mjs | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs index 92666d42bf22b8..860e55b425786c 100644 --- a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs @@ -33,9 +33,7 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const _ of stream) { - void _; /* reading extends the window */ - } + for await (const {} of stream) { /* reading extends the window */ } }; }, { sni: { '*': { keys: [key], certs: [cert] } }, diff --git a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs index be34e303a8e76a..6e85bbb3bbed9e 100644 --- a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs @@ -33,9 +33,7 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const _ of stream) for await (const _ of stream) { - void _; /* reading extends the window */ - } + for await (const {} of stream) { /* reading extends the window */ } }; }, { alpn: 'foo', From e71db8baccbe99ef751e356ee9e8de618f16e658 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 08:05:05 +0000 Subject: [PATCH 09/10] Fix lint 3 --- .../test-quic-h3-maxstreamdata-external-buffer-failure.mjs | 2 +- .../test-quic-maxstreamdata-external-buffer-failure.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs index 860e55b425786c..9f1e8bc6418384 100644 --- a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs @@ -33,7 +33,7 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const {} of stream) { /* reading extends the window */ } + for await (const {} of stream) { _ ; /* reading extends the window */ } }; }, { sni: { '*': { keys: [key], certs: [cert] } }, diff --git a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs index 6e85bbb3bbed9e..dd198dc4735963 100644 --- a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs @@ -33,7 +33,7 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const {} of stream) { /* reading extends the window */ } + for await (const {} of stream) { _ ; /* reading extends the window */ } }; }, { alpn: 'foo', From ad505ca517f9fad93225ee06c4f2560a9be2e8a7 Mon Sep 17 00:00:00 2001 From: Marten Richter Date: Wed, 29 Jul 2026 08:17:27 +0000 Subject: [PATCH 10/10] Fix lint 4 --- .../test-quic-h3-maxstreamdata-external-buffer-failure.mjs | 3 ++- .../test-quic-maxstreamdata-external-buffer-failure.mjs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs index 9f1e8bc6418384..df74e4db408b06 100644 --- a/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-h3-maxstreamdata-external-buffer-failure.mjs @@ -33,7 +33,8 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const {} of stream) { _ ; /* reading extends the window */ } + // eslint-disable-next-line no-unused-vars + for await (const _ of stream) { /* reading extends the window */ } }; }, { sni: { '*': { keys: [key], certs: [cert] } }, diff --git a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs index dd198dc4735963..79d11e05794a0b 100644 --- a/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs +++ b/test/parallel/test-quic-maxstreamdata-external-buffer-failure.mjs @@ -33,7 +33,8 @@ const serverMayRead = new Promise((resolve) => { letServerRead = resolve; }); const endpoint = await listen((session) => { session.onstream = async (stream) => { await serverMayRead; - for await (const {} of stream) { _ ; /* reading extends the window */ } + // eslint-disable-next-line no-unused-vars + for await (const _ of stream) { /* reading extends the window */ } }; }, { alpn: 'foo',