diff --git a/CHANGELOG.md b/CHANGELOG.md index 2789b6b5c810b0..4b4e64ae788cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,8 @@ release. -21.6.0
+21.6.1
+21.6.0
21.5.0
21.4.0
21.3.0
diff --git a/doc/changelogs/CHANGELOG_V21.md b/doc/changelogs/CHANGELOG_V21.md index 77461d7a88f8c6..18b0c539d3115b 100644 --- a/doc/changelogs/CHANGELOG_V21.md +++ b/doc/changelogs/CHANGELOG_V21.md @@ -8,6 +8,7 @@ +21.6.1
21.6.0
21.5.0
21.4.0
@@ -42,6 +43,19 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2024-01-22, Version 21.6.1 (Current), @RafaelGSS + +### Notable Changes + +This release fixes a bug in `undici` using WebStreams + +### Commits + +* \[[`662ac95729`](https://github.com/nodejs/node/commit/662ac95729)] - _**Revert**_ "**stream**: fix cloned webstreams not being unref'd" (Matteo Collina) [#51491](https://github.com/nodejs/node/pull/51491) +* \[[`1b8bba8aee`](https://github.com/nodejs/node/commit/1b8bba8aee)] - **test**: add regression test for 51586 (Matteo Collina) [#51491](https://github.com/nodejs/node/pull/51491) + ## 2024-01-15, Version 21.6.0 (Current), @RafaelGSS diff --git a/lib/internal/webstreams/readablestream.js b/lib/internal/webstreams/readablestream.js index c7f492033ceaf8..35656216680875 100644 --- a/lib/internal/webstreams/readablestream.js +++ b/lib/internal/webstreams/readablestream.js @@ -596,8 +596,6 @@ class ReadableStream { [kTransferList]() { const { port1, port2 } = new MessageChannel(); - port1.unref(); - port2.unref(); this[kState].transfer.port1 = port1; this[kState].transfer.port2 = port2; return [ port2 ]; diff --git a/lib/internal/webstreams/transfer.js b/lib/internal/webstreams/transfer.js index c4cb4077f88403..136b0d81a99464 100644 --- a/lib/internal/webstreams/transfer.js +++ b/lib/internal/webstreams/transfer.js @@ -143,8 +143,6 @@ class CrossRealmTransformReadableSource { error); port.close(); }; - - port.unref(); } start(controller) { @@ -212,7 +210,7 @@ class CrossRealmTransformWritableSink { error); port.close(); }; - port.unref(); + } start(controller) { diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index c6f5c22bc7a95e..954bc6c2cc93d8 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -266,8 +266,6 @@ class WritableStream { [kTransferList]() { const { port1, port2 } = new MessageChannel(); - port1.unref(); - port2.unref(); this[kState].transfer.port1 = port1; this[kState].transfer.port2 = port2; return [ port2 ]; diff --git a/src/node_version.h b/src/node_version.h index 9bd5780a565438..e9c4f77782ab75 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -29,7 +29,7 @@ #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) diff --git a/test/parallel/test-webstream-structured-clone-no-leftovers.mjs b/test/parallel/test-webstream-structured-clone-no-leftovers.mjs new file mode 100644 index 00000000000000..e8af095cce18d5 --- /dev/null +++ b/test/parallel/test-webstream-structured-clone-no-leftovers.mjs @@ -0,0 +1,28 @@ +import '../common/index.mjs'; +import { test } from 'node:test'; +import assert from 'node:assert'; + +test('do not leak promises', async () => { + const buf = new Uint8Array(1); + const readable = new ReadableStream({ + start(controller) { + controller.enqueue(buf); + controller.close(); + } + }); + + const [out1, out2] = readable.tee(); + const cloned = structuredClone(out2, { transfer: [out2] }); + + for await (const chunk of cloned) { + assert.deepStrictEqual(chunk, buf); + } + + for await (const chunk of out2) { + assert.deepStrictEqual(chunk, buf); + } + + for await (const chunk of out1) { + assert.deepStrictEqual(chunk, buf); + } +}); diff --git a/test/parallel/test-webstreams-clone-unref.js b/test/parallel/test-webstreams-clone-unref.js deleted file mode 100644 index 88a9cebd9c3046..00000000000000 --- a/test/parallel/test-webstreams-clone-unref.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -require('../common'); -const { ok } = require('node:assert'); - -// This test verifies that cloned ReadableStream and WritableStream instances -// do not keep the process alive. The test fails if it timesout (it should just -// exit immediately) - -const rs1 = new ReadableStream(); -const ws1 = new WritableStream(); - -const [rs2, ws2] = structuredClone([rs1, ws1], { transfer: [rs1, ws1] }); - -ok(rs2 instanceof ReadableStream); -ok(ws2 instanceof WritableStream); diff --git a/test/parallel/test-whatwg-webstreams-transfer.js b/test/parallel/test-whatwg-webstreams-transfer.js index 7be01c339652c0..01cfaa02ad075e 100644 --- a/test/parallel/test-whatwg-webstreams-transfer.js +++ b/test/parallel/test-whatwg-webstreams-transfer.js @@ -464,23 +464,12 @@ const theData = 'hello'; tracker.verify(); }); - // We create an interval to keep the event loop alive while - // we wait for the stream read to complete. The reason this is needed is because there's - // otherwise nothing to keep the worker thread event loop alive long enough to actually - // complete the read from the stream. Under the covers the ReadableStream uses an - // unref'd MessagePort to communicate with the main thread. Because the MessagePort - // is unref'd, it's existence would not keep the thread alive on its own. There was previously - // a bug where this MessagePort was ref'd which would block the thread and main thread - // from terminating at all unless the stream was consumed/closed. - const i = setInterval(() => {}, 1000); - parentPort.onmessage = tracker.calls(({ data }) => { assert(isReadableStream(data)); const reader = data.getReader(); reader.read().then(tracker.calls((result) => { assert(!result.done); assert(result.value instanceof Uint8Array); - clearInterval(i); })); parentPort.close(); });